Unity cho người bắt đầu : Cấu trúc thư mục và source code

Bạn đã tự hỏi tại sao cần tới một cấu trúc tốt ngay từ đầu cho một project? Với một cấu trúc tốt bạn càng thực hiện nó tốt nó sẽ giúp bạn tiết kiệm thời gian. Việc xây dựng nhiều dự án trên cùng một nền tảng được thiết kế tốt cũng giúp việc trao đổi giữa các dự án một cách dễ dàng hơn.

13 min read
Bởi phont
Unity cho người bắt đầu : Cấu trúc thư mục và source code

1. Tổng quan

Bạn đã tự hỏi tại sao cần tới một cấu trúc tốt ngay từ đầu cho một project? Với một cấu trúc tốt bạn càng thực hiện nó tốt nó sẽ giúp bạn tiết kiệm thời gian. Việc xây dựng nhiều dự án trên cùng một nền tảng được thiết kế tốt cũng giúp việc trao đổi giữa các dự án một cách dễ dàng hơn. Nhưng có lẽ lý do thuyết phục nhất cho một dự án có cấu trúc tốt ngay từ đầu là việc thực thi nó sẽ dễ dàng hơn.

arreveriecodeplanning

Khi phần mềm, ứng dụng trở nên lớn và phức tạp thì việc duy trì sẽ càng ngày càng khó khăn. Để không lãng phí thời gian vào việc quản lý một mớ hỗn độn hơn và việc tập trung vào các tính năng thì bạn cần có một cấu trúc tốt và giữ cho nó có cấu trúc tốt ngay từ đầu. Đây là một tập hợp các phương pháp tốt nhất mà chúng tôi đã đúc rút qua quá trình trải nghiệm và tổng kết từ một số trang web khác.

2. Phương pháp

2.1. Tránh phân tách các asset. Chỉ có một phiên bản duy nhất của bất kỳ asset nào. Nếu bạn cần thiết phân tách prefab, scence hoặc mesh hãy làm theo một quy trình rõ ràng cho các phiên bản. Các nhánh "sai" phải được làm nổi bật bằng cách đặt tên, ví dụ: sử dụng tiền tố dấu gạch dưới: _MainSence_Backup

2.2. Sử dụng công cụ quản lý phiên bản cho việc quản lý project.
2.3. Cố gắng giữ cho mọi thứ ngắn gọn và đơn giản. Cố gắng giữ cho các class của bạn ngắn gọn và rõ ràng. Một class nhỏ nên có ít hơn 100 dòng. Và các main class ngăn hơn 1000 dòng. Nếu vượt qua con số này thì bạn đang tạo ra một script tồi tệ và chúng ta cần phải tránh điều đó.

3. Cấu trúc thư mục và Scence

Cấu trúc thư mục giúp các thành viên trong nhóm của bạn sửa đổi, tìm kiếm, tổ chức project và các tài nguyên một cách dễ dàng và đồng thời. Có rất nhiều cách để làm điều này, và chúng tôi sẽ đưa ra một số ví dụ cụ thể mà chúng tôi thấy là hoạt động tốt. Nếu bố cục dự án của bạn đáp ứng những vấn đề sau, thì nó có thể là một bố cục khá tốt.

  • Ai làm nó?
  • Nó thuộc loại nào? Script, Audio, Art, Design?
  • Phạm vi của project bao gồm những gì?
  • Giá trị của asset và những dữ liệu nào bạn cần quan tâm nếu bạn thay đổi nó?

UnityFolderStructure

4. Streaming Assets:

Hầu hết các asset trong Unity được kết hợp vào project khi nó được xây dựng. Tuy nhiên, đôi khi rất hữu ích khi đặt các tệp này vào hệ thống tệp bình thường trên máy đích để làm cho chúng có thể truy cập qua đường dẫn. Một ví dụ về việc này là triển khai một tệp phim trên thiết bị IOS, tập tin phim gốc phải có sẵn từ một vị trí trong hệ thống tập tin sẽ được phát bởi chức năng PlayMovie.
Bất kỳ một tệp nào được đặt trong một thư mục có tên là StreammingAssets (phân biệt chữ hoa và chữ thường) trong một project Unity sẽ được sao chép đúng nguyên văn sang một thư mục cụ thể trên máy đích. Ban jcos thể truy xuất thư mục bằng thược tính Application.streamingAssetPath. Tốt nhất sử dụng Application.streamingAssetPath để lấy vị trí của thư mục StreamingAssets, vì nó sẽ luôn trỏ đến vị trí chính xác trên nền tảng nơi ứng dụng chạy.
Vị trí của thư mục này thay đổi theo nền tảng.

  • Trên máy tính để bàn (Mac OS hoặc Windows), vị trí các tệp có thể lấy bằng mã sau: path = Application.dataPath + "/StreamingAssets";
  • Trên iOS, sử dụng : path = Application.dataPath + "/Raw";
  • Trên Android, sử dụng: path = "jar:file://" + Application.dataPath + "!/assets/";

Unity cho bạn khả năng tùy biến. Đó là lý do tại sao nó thường xuyên lộn xộn, và vì chúng ta không thể nói về tổ chức mà không có cấu trúc thư mục dự án phù hợp. Đây là một ví dụ chúng tôi sử dụng trong thự tế

|-- Assets
       |-- Animations
       |   |-- 2DAnimations
       |   |-- 3DAnimations
       |-- Editor           //Special Folder
       |-- Media
       |   |-- Audio
       |   |-- Video
       |-- Models
       |-- Materials
       |-- Plugins          //Special Folder
       |   |-- Android
       |   |-- iOS
       |   |-- Special
       |-- Prefabs
       |-- Resources        //Special Folder
       |   |-- Android
       |   |-- iOS
       |   |-- Common
       |-- Scenes
       |   |-- Levels
       |   |-- Others
       |-- Scripts
       |   |-- Editor
       |-- Shaders
       |-- StreamingAssets  //Special Folder
       |-- SandBox
       |-- Sprites

Một vài điểm quan trọng cần ghi nhớ:

  • Không sử dụng dấu cách trong đặt tên tệp, vì công cụ dòng lệnh trong Unity3D không xử lý đường dẫn có dấu cách
  • Không lưu trữ bất kỳ tập tin asset nào trong thư mục gốc (Resources) . Sử dụng thư mục con bất cứ khi nào
  • Không tạo bất kỳ thư mục bổ sung nào trong thư mục gốc (Resources), trừ khi bạn thực sự cần.
  • Hãy đặt tên một cách nhất quán
  • Sử dụng thư mục "Third_Party" để lưu trữ các asset được nhập từ Asset Store. Chúng thường có cấu trúc riêng và không nên thay đổi
  • Sử dụng "SandBox" cho bất kỳ thử nghiệm nào của bạn không hoàn toàn chắc chặn. Khi bạn đang làm việc trên dự án với những người khác, hãy tạo thư mục con SandBox cá nhân của bạn như : SandBox/San

5. Cấu trúc phân cấp của Sence

Bên cạnh hệ thống phân cấp của project, cũng có hệ thống phân cấp của Sence. Như trên, chúng tôi sẽ giới thiệu cho bạn một ví dụ. Bạn có thể thay đổi nó theo nhu cầu của bạn.

  • Lights
  • Cameras
  • AR_Manager
  • World
  • GUI
  • Scene_Manager
  • _Dynamic

Một vài điểm quan trọng cần lưu ý:

  • Sử dụng các gameobject trống (empty) như các folder trong sence. Sắp xếp một cách cẩn thận secne của bạn để có thể dễ dàng tìm các đối tượng. Tất cả các gameobject trống cần phải đặt position (0,0,0) và rotision và scale mặc định

  • Khi bạn khởi tạo một đối tượng trong thời gian chạy, hãy nhớ đặt đối tượng đó trong _Dynamic

  • Đặt các prefabs và folders (empty gameobject) ở (0,0,0). Nếu tranform của nó không được sử dụng để định vị đối tượng, nó phải ở gốc. Bằng cách đó, có ít nguy cơ gặp phải sự cố với không gian địa phương và thế giới

  • Đặt nhân vật và đối tượng tại pivots, không tại centre. Điều này làm cho nó dễ dàng đặt các nhân vật và các đói tượng trên một sàn một cách chính xác. Nó cũng dễ dàng hơn để làm việc với 3D như thể là 2D cho logic trò chơi, AI và thậm chỉ cả vật lý.

  • Làm cho tất cả các mesh phải theo một hướng (trục z dương hoặc âm). Điều này áp dung cho các mesh như ký tự và các đối tượng khác có khái niệm hướng đối diện. Nhiều thuật toán được đơn giản hóa nếu mói thứ đều có cùng hướng đối diện.

  • Lấy scale đúng ngay từ đầu. Tạo tỷ lệ sao cho tất cả chúng có thể được nhập với hệ số tỷ lệ là 1 và transforms của chúng có thể được chia theo (1,1,1). Sử dụng đối tượng tham chiếu (Unity cube) để so sánh quy mô dễ dàng. Chọn một đơn vị Unity thống nhất, phù hợp với trò chơi/project của bạn

6. Sử dụng hệ quản lý phiên bản bên trong Unity

Bạn có thể sử dụng bất kỳ hệ quản lý nào: Git, Subversion hoặc bất kỳ VCS nào khác. Bạn nên tập trung tìm hiểu kỹ về tính năng của VCS mà bạn chọn để phục vụ cho việc quản lý phiên bản một cách tốt nhất. Nhiều người đang sử dụng những hệ thống VCS này với mục đích như một giải pháp sao lưu và đồng bộ hóa.

Thiết lập hệ thống quản lý phiên bản với Unity

Bạn sẽ thấy rằng trong hầu hết project Unity có khá nhiều tập tin và thư mục. Tuy nhiên, chỉ có 3 thư mục cần được kiểm soát là: Assets, Packages và ProjectSettings. Những thành phần còn lại được tạo ra từ chúng.
Dưới đây là tóm tắt về tất cả các tệp và thư mục

  • Assets: Thư mục chưa tất cả tài nguyên của game bao gồm: scripts, textures, sound, trình editors ... Đây là thư mục quan trọng nhất của project.
  • Library: bộ nhớ cache cục bộ cho các nội dung đã nhập, khi sử dụng VCS cần loại bỏ hoàn toàn
  • Packages: Thư mục này chưa các tệp dưới định dạng JSON được sử dụng để duy trì liên kết phụ thuộc
  • ProjectSettings: trong thư mục này chứa tất các các thiết lập của project như: Physic, Tags, Player Settings ...Nói cách khác, mọi thứ bạn thiết lập từ Edit -> Project Settings sẽ được chuyên vào thư mục này
  • Temp: cách thư mục cho các tệp tạm được tạo trong quá trình build, têp jddaau tiên được sử dụng bởi MonoDevelop, tếp thứ 2 bởi Unity
  • ProjectName.sln : các tệp giải pháp cho các IDE như Visual Studio

Unitycodestructure

Trước khi thực hiện việc quản lý phiên bản, bạn cần phải cấu hình Project để nó tương thích với việc lưu trữ trong VCS. Thực hiện các bước như sau:

  • Chuyển sang chế độ Visible Meta Files in Edit → Project Settings → Editor → Version Control Mode → Visible Meta Files.
  • Chuyển sang Force Text in Edit → Project Settings → Editor → Asset Serialization Mode

UnitySettings

Với thiết lập này sẽ hiển thị một tệp văn bản cho mọi nội dung trong thư mục Assets
Các tệp có phần mở rộng là .meta với phần đầu tiên là tên đẩy đủ của nội dung liên kết với nó. Việc di chuyển và đổi tên nội dung trong Unity cũng sẽ được cập nhật vào các tệp .meta liên quan. Tuy nhiên, nếu bạn di chuyển hoặc đổi tên nội dung từ một công cụ bên ngoài, hãy đãm bảo rằng đã đồng bộ hóa các tệp .meta liên quan.

Ví dụ : tạo một dự án mới và nhập nó vào kho lưu trữ VCS (GIT)

  1. Tạo một project mới trong Unity và đặt tên nó là ReverieSample.
  2. Kích hoạt Visible Meta files in Edit->Project Settings->Editor
  3. Chuyển Force Text in Edit → Project Settings → Editor → Asset Serialization Mode
  4. Tắt Unity (đảm bảo rằng tất cả các tập tin đã được lưu)
  5. Thiết lập bộ lọc .gitignore cho các thư mục và tệp không cần thiết
  6. Nhập project vào VCS bằng cách sử dụng công cụ GUI hoặc dòng lệnh và đẩy chúng lên VCS remote/ local Responsitory
  7. Kiểm tra các thư mục Assets, Packages và ProjectSettings đã có trong VCS chưa
  8. Mở project với Unity. Việc mở project sẽ tạo lại thư mục Library và các tệp thư mục cần thiết khác
  9. Cuối cùng, bạn có thể thực hiện và cập nhật các thay đổi. Project đã sẵn sàng sử dụng.

File .gitignore : http://www.arreverie.com/blogs/wp-content/uploads/resources/.gitignore

7. Prefabs

Sử dụng prefabs cho mọi thứ. Prefabs trong Unity là giải pháp tốt nhất mà bạn tìm thấy để chia sẻ các cấu trúc phân cấp được cấu hình sẵn. Nói chung, hãy thử để prefab tất cả mọi thứ mà bạn đưa và Sence. Điều này giúp dễ dàng thực hiện các thay đổi mà không cần thay đổi Sence.
Lý do tại sao bạn nên sử dụng Prefabs là khi có một thay đổi với prefab, thì nó sẽ thay đổi toàn bộ ở các Sence mà prefab được sử dụng. Bạn có 100 level và muốn thêm hiệu ứng camera vào tất cả chúng? Không thành vấn đề! Nếu camera của bạn là prefab, chỉ cần thêm hiệu ứng đó vào prefab của máy ảnh.
Sử dụng prefabs riêng biệt cho các trường hợp riêng biệt. Nếu bạn có hai loại enemy và chúng chỉ khách nhau bởi thuộc tính của chúng, hãy tạo các prefab riêng biệt cho cách thuộc tính và liên kết chúng. Điều này giúp cho

  • Mỗi loại được thay đổi ở một nơi
  • Thực hiện thay đổi mà không cần thay đổi Sence

Liên kết prefabs tới prefabs; không liên kết các cá thể tới các cá thể. Các liên kết đến prefabs được duy trì khi đặt một prefabs vào 1 sence; liên kết đến các cá thể thì không. Liên kết với prefabs có thể giảm việc cài đặt sence và việc thay đổi trong sences

Càng nhiều càng tốt, thiết lập liên kết giữa các cá thể một cách tự động. Nếu bạn cần liên kết các cá thể thãy thiết lập liên kết theo chương trình. Ví dụ, prefab player có thể tự đăng ký với GameManager khi nó khởi động, hoặc GameManager có thể tìm thấy cá thể Player Prefabs khi nó bắt đầu.

Không đặt mest vào prefabs nếu bạn muốn thêm các scripts khác. Khi bạn tạo prefab từ một mest, tạo một gameobject rỗng làm object cha, và đặt nó ở root. Đặt script vào root, không đặt trên mesh. Bằng cách đó, việc thay mesh bằng một mesh khác sẽ dễ dàng hơn và không làm mất dữ liệu mà bạn đã thiết lập trong chủ thể.

8. Documentation

Hầu hết các tài liệu được chú thích trong mã code tuy nhiên một số cần ghi lại ở bên ngoài. Chúng ta cần duy trì tệp README.txt trong project của mình

Tài liệu đáp ứng những điều sau:

  • Sơ đồ khối chi tiết và sơ đồ luồng của project giúp hiểu rõ kiến trúc project
  • Các chi tiết của script và một số thông tin về các tiêu chuẩn code được tuân thủ trong project
  • Lớp được dùng (cho collision, culling và raycasting)
  • Các Tag được sử dụng
  • GUI cho các lớp (những gì sẽ hiển thị)
  • Chi tiết thiết lập Sence
  • Cấu trúc Prefabs
  • Các lớp Animation và cá thông tin liên quan đến Animation

9. Kết luận

Chúng tôi vừa đưa ra một cách tổng quan ngắn gọn về việc xử lý cấu trúc. Những gì phù hợp với chúng tôi có thể không hiệu quả đối với bạn, do đó đừng ngần ngại điều chỉnh mọi thứ cho phù hợp với sở thích của riêng bạn. Cách tiếp cận mà chúng tôi đã sử dụng ở đây là thử nghiệm một cái gì đó, chỉnh sửa những gì không hiệu quả, sau đó thử lại. Đó là bí quyết của thành công.