[Unity | vi] Cấu trúc Object trong Unity cùng cách thức truy vấn và hiệu chỉnh thuộc tính bằng lệnh

Mình đã có trải nghiệm làm game với Lua trên Roblox nên có thể cảm nhận rõ sự quan trọng của việc bắt đầu học lập trình Game qua việc nắm được cấu trúc của Game và biết cách truy cập cũng như hiệu chỉnh tính chất của các vật thể trong Game bằng lệnh.
Mỗi công cụ lập trình Game sẽ có các cách tiếp cận chuyện dùng lệnh để tương tác với các vật thể trong Game khác nhau. Roblox Studio chắc chắn sẽ có nhiều điểm khác với Unity.

Roblox Property Panel vs Unity Inspector

1. Mối quan hệ "Parent and Child"

Một vật thể A (hiển thị ngay ở tầng đầu tiên của cây thư mục) có thể chứa vật thể B. Vật thể B lại có thể chứa vật thể C.
Ta nói, A là Parent của B, B là Parent của C. Để truy cập vào C thì:

  • Trong Roblox: local objectC = workspace.A.B.C
  • Trong Unity: GameObject objectC = GameObject.Find("A/B/C");

2. Cấu trúc của một vật thể - Object

Một vật thể (Part hoặc Model) trong Roblox Studio thường gồm các thuộc tính, chúng được nhóm lại thành nhóm nhưng thường được truy cập trực tiếp với tên thuộc tính. Một vật thể (Object) trong Unity cũng có các thuộc tính, chúng cũng được phân thành nhóm. Tuy nhiên, các nhóm này có vai trò quan trọng và vì vậy chúng cũng có khái niệm riêng là "Component". Trong Unity, chúng ta cũng không thể truy cập trực tiếp tới thuộc tính của vật thể như Roblox mà phải thông qua Component. Nếu trong vật thể C bên trên mà có 2 thuộc tính Size thuộc phân mục Transform thì ta có thể lấy giá trị như sau:

  • Trong Roblox: local propertySize = objectC.Size (Roblox truy cập trực tiếp qua tên thuộc tính, không quan tâm phân mục)
  • Trong Unity: Vector3 propertySize = objectC.GetComponent<Transform>().Size; (trong Unity thực ra là thuộc tính localScale)

3. Vai trò của Script

Trong Unity và Roblox, Script đều được dùng để điều chỉnh tính chất của Object. Tuy nhiên vai trò này thể hiện rõ trong Unity hơn. Script trong Unity có thể được xem là Behavior Component, đóng vai trò định nghĩa hành vi của Object mà nó gắn vào. Cách thức truy cập vào Script cũng giống y như truy cập vào một Component bình thường. Do Roblox không xem Script như là một Component nên cách thức truy cập sẽ hơi khác. Nếu trong vật thể C có 1 SampleScript thì ta có thể truy cập vào SampleScript như sau:

  • Trong Roblox: local sampleScript = objectC.SampleScript
  • Trong Unity: SampleScript sampleScript = objectC.GetComponent<sampleScript>();

4. Chứa thông tin và truy cập thông tin từ nhiều Script

Trong Roblox, nếu dữ liệu được sử dụng bởi nhiều Script, chúng sẽ được lưu vào các ObjectValue, nằm tách biệt khỏi Script hoặc sẽ phải sữ dụng ModuleScript. Trong Unity, dữ liệu vẫn sẽ nằm trong biến thuộc chính Script đó. Một Script khác muốn truy cập vào biến này thì phải tìm được Script chứa biến đó trước đã, nó khá tương đồng với cách dùng ModuleScript của Roblox. Nếu SampleScript muốn sử dụng một biến SampleVar thuộc một ModuleScript nào đó thì:
Trong Roblox:

  1. local ModuleScript = require(script.Parent.ModuleScript)
  2. local sampleVar = ModuleScript .SampleVar (ModuleScript phải là một Module Script và SampleVar phải được return trong ModuleScript)

Trong Unity:

  1. ModuleScript moduleScript = objectA.GetComponent<ModuleScript>();
  2. int sampleVar = moduleScript.SampleVar ;

5. Hiệu chỉnh thuộc tính

Quay lại mục 1, chúng ta đã có thể lấy được thông tin thuộc tính của vật thể để lưu vào biến. Tuy nhiên, khi muốn thay đổi giá trị thuộc tính của vật thể, chúng ta cần lưu ý nho nhỏ sau. Vế bên phải của toán tử gán phải là đường dẫn tham chiếu đến thuộc tính đó chứ không thể là 1 biến. Như vậy, làm như bên dưới sẽ là sai:
Trong Roblox:

  1. local propertySize = objectC.Size
  2. propertySize = Vector3.new(5,5,5) (objectC.Size sẽ không đổi giá trị)

Trong Unity:

  1. Vector3 propertySize = objectC.GetComponent<Transform>().Size;
  2. propertySize = new Vector3(5,5,5); (objectC -> Size sẽ không đổi giá trị)

Thay vào đó, làm như sau sẽ cập nhật được giá trị mới:

  • Trong Roblox: objectC.Size = Vector3.new(5,5,5)
  • Trong Unity: objectC.GetComponent<Transform>().Size = new Vector3(5,5,5);