Giới thiệu
Unity component là các chức năng mà bạn thêm vào GameObject cho một mục đích cụ thể
Component là gì
Component là một chức năng mà bạn thêm vào GameObject. Cụ thể như sau :
|
|
Tất cả các chức năng mà chúng ta thường gọi là “camera” và “light” là component Bạn có thể thêm bao nhiêu component tùy thích vào GameObject.
Unity thêm component vào GameObject bằng cách thêm chúng. Bạn có thể tự do tạo chức năng của trò chơi.
Các tính năng của component
Component có thể thêm vào GameObject
Tính năng lớn nhất của component là nó có thể được thêm vào GameObject.
Mặt khác, một component không thể tự làm bất cứ điều gì. Nó chỉ hoạt động khi bạn thêm nó vào GameObject.
Component yêu cầu kế thừa từ class MonoBehaviour để có thể thêm vào GameObject
Các component cũng có thể được tạo bởi chính nhà phát triển. Như điều khiển nhân vật (CharacterControl), logic trò chơi (GameLogic), v.v. Đây gọi là phát triển chức năng trò chơi.
Bạn có thể thêm các component của riêng mình vào GameObject bằng cách kế thừa class MonoBehaviour.
Nhiều component giống nhau có thể được thêm vào GameObject
Bạn có thể thêm nhiều component giống nhau vào GameObject.
Các component giống nhau độc lập với nhau.
Nhìn vào hình ảnh bên dưới, chúng ta có thể thấy rằng Instance ID
của chúng là khác nhau
Các cách cơ bản để sử dụng component
Add component
Điều đầu tiên cần nhớ là cách thêm một component vào GameObject. Thực tế có bốn cách để thêm một thành phần
Thông qua nút Add Component trong cửa sổ Inspector
Thêm conponent thông qua menu Component trên menubar
bạn cần chọn GameObject muốn thêm conponent trước
Kéo thả trực tiếp từ Project vào GameObject
bạn cần chọn GameObject muốn thêm conponent trước
Lưu ý: bạn cần nhấn giữ mà không chỉ là nhấp vào tệp lệnh component, nếu không cửa sổ Inspector sẽ hiển thị thông tin của tệp lệnh component Bạn cũng có thể sử dụng tính năng khóa Inspector để khóa hiển thị Inspector hiện tại để dễ dàng kéo thả
Hoặc sử dụng tính năng nhiều Inspector trong Unity 2021+ để mở một Inspector khác cho nội dung được chỉ định và nó tách biệt với Inspector chính. Bạn có thể mở nó bằng cách nhấp chuột phải vào bất kỳ asset hoặc GameObject nào trong dự án của bạn và chọn properties ở cuối menu xuất hiện hoặc bằng cách nhấp chuột trái vào nó và sử dụng phím tắt Alt + P
Thông qua script
Các phương pháp được đề cập trước đó đều là thao tác với Editor. Cách tiếp theo sẽ được thao tác bằng script. Bạn có thể sử dụng phương thức AddComponent
|
|
Ví dụ: thêm thành phần PlayerMovement vào GameObject
|
|
AddComponent chỉ là một chức năng của GameObject để thực thi AddComponent cho GameObject Hãy nhớ điều này vì đó là một phương pháp bạn sử dụng rất nhiều.
Delete component
Có 2 cách để xóa component khỏi GameObject
Xóa compoment trong inspector
Sử dụng phương thức Destroy trong script
|
|
Đoạn mã mẫu sau đây là một ví dụ về việc thêm mới PlayerMovement và xóa nó sau 1 giây. Quá trình chờ 1 giây sử dụng một hàm có tên là coroutine.
|
|
hoặc có thể viết theo cách khác như sau
|
|
PlayerMovement đã được thêm và xóa sau 1 giây. Destroy được sử dụng rất nhiều nên hãy nhớ nó
GetComponent
Có ba cách để lấy các component.
Sử dụng GetComponent
Phương thức GetComponent sẽ trả về một component với kiểu chỉ định truyền vào Nó có thể được lấy bằng cách chỉ định tên của component.
Mã nguồn của GetComponent
|
|
Hãy xem xét đoạn mã cụ thể sau
|
|
Ở đây ta đang nhận được PlayerMovement bằng phương thức GetComponent.
Bạn có thể nhận được thành phần PlayerMovement khi PlayerMovement component được gắn vào cùng một GameObject như AddPlayerComponent như hình trên.
Nếu bạn không thể lấy thành phần bằng GetComponent Thì component đó có thể không được đính kèm trước vào GameObject. Trong trường hợp đó, giá trị trả về của GetComponent là null.
Nếu nó là null, bạn có thể muốn đính kèm một component mới vào. Bạn có thể thực hiện điều đó như sau
|
|
Nếu PlayerMovement không tồn tại, nó sẽ được thêm mới bằng cách sử dụng phương thức AddComponent Đó là một kỹ thuật bạn sẽ sử dụng rất nhiều, vì vậy hãy ghi nhớ nó.
Sử dụng GetComponents để nhận tất cả component của Type trong GameObject
Như đã giải thích ở trong phần tính năng của component là ta có thể thêm cùng một component nhiều lần vào GameObject
Để có được tất cả các component giống nhau cùng một lúc hãy sử dụng GetComponents Tương tự như GetComponent, nhưng lưu ý rằng nó có chữ “s” ở cuối.
|
|
Kết quả trả về một mảng, bạn có thể lấy từng component riêng lẻ bằng cách truy vấn mảng được trả về này
Sử dụng GetComponentInChildren
GameObject có thể có một hệ thống phân cấp như trong hình bên dưới.
GetComponent được giới thiệu trước đó chỉ có thể nhận được một cấp độ của component Bạn cũng có thể lấy các component của phân cấp con bằng cách sử dụng GetComponentInChildren, sẽ được giới thiệu bên dưới
Giống như hình ảnh cây phân cấp ở trên, đối tượng Movement nằm ở vị trí cuối cùng
Chúng ta sẽ sử dụng GetComponentInChildren để lấy component PlayerMovement gắn với đối tượng Movement. Với điều kiện class Player được gắn vào đối tượng Player
|
|
- Ghi chú: GetComponentInChildren cũng bao gồm kiểm tra cho chính bản thân nó
Như tên cho thấy, GetComponentInChildren có xu hướng chỉ nhắm mục tiêu đến hệ thống phân cấp con, nhưng trên thực tế, nó cũng sẽ kiểm tra chính bản thân nó
Lưu ý rằng phạm vi tìm kiếm cho GetComponentInChildren là một hệ thống phân cấp con bao gồm chính nó, như được hiển thị ở trên.
- Cách loại trừ các thành phần không hoạt động khỏi tìm kiếm
Ta có thể sử dụng GetComponentInChildren để lấy các thành phần của hệ thống phân cấp con. Nhưng trong một số trường hợp, bạn có thể muốn loại trừ các component không hoạt động.
Nói cách khác, nó trông giống như hình bên dưới.
Điều này có nghĩa là các component của GameObject deactive sẽ bị loại trừ khỏi tìm kiếm.
Điều này có thể đạt được đơn giản bằng cách gán true cho đối số của GetComponentInChildren.
|
|
Khi đó PlayerMovement của GameObject deactive sẽ bị loại trừ khỏi mục tiêu tìm kiếm.
Lưu ý rằng chỉ các GameObject deactive mới bị loại trừ khỏi tìm kiếm, nếu chỉ có component bị deactive thì nó sẽ không bị loại trừ Giống ảnh sau đây component PlayerMovement bị disable nhưng đối tượng GetComponentInChildren vẫn đang active nên kết quả sẽ không loại trừ đi nó
- Nhận nhiều component trong hệ thống phân cấp con với GetComponentsInChildren
Giống như GetComponent, GetComponentInChildren cung cấp một cách để nhận được nhiều hơn một component của Type. Đó là GetComponentsInChildren. Giống như GetComponent, nó có thêm chữ “s” ở cuối.
Ví dụ:
|
|
|
|
GetComponentsInChildren cũng loại trừ các component không hoạt động khỏi mục tiêu tìm kiếm nếu đối số được đặt thành true.
GetComponentInParent
Bạn có thể tìm kiếm component bên trong các đối tượng cha bằng cách sử dụng GetComponentInParent. Ví dụ:
|
|
Nhận component của cấu trúc phân cấp cha từ chính bạn như ví dụ trong hình bên dưới.
GetComponentInParent, giống như bất kỳ phương thức nào khác bạn có thể lấy nhiều thành phần bằng cách sử dụng “GetComponentsInParent”.
Bật tắt component với enable
BẬT / TẮT này có tác động như thế nào?
Nó có ảnh hưởng đến các ’event function’ như Start và Update …
Nếu nó là disable, các ’event function’ này sẽ không được thực thi. Nếu bạn không viết một ’event function’ cụ thể, hộp checkbox sẽ không được hiển thị.
Có tổng cộng 7 event function
- Start()
- Update()
- FixedUpdate()
- LateUpdate()
- OnGUI()
- OnDisable()
- OnEnable()
Checkboxe sẽ xuất hiện khi bạn viết các hàm này trong file script. Như đã đề cập ở trên, các hộp checkbox được kiểm soát bởi thuộc tính ’enable'.
Các kỹ thuật khác
Bây giờ bạn đã biết cách sử dụng cơ bản của các component. Dưới đây là 6 kỹ thuật khác để sử dụng.
Chỉ định component sẽ được thêm vào với RequireComponent
Có một số component luôn cần component khác được đính kèm theo để có thể hoạt động, chúng ta có thể thêm nó như mặc định bằng RequireComponent Thật tiện lợi khi sử dụng RequestComponent cho các component mà bạn luôn muốn nó sẽ được kèm theo
Ví dụ, component Image.
Như bạn có thể thấy trong video ở trên CanvasRenderer được thêm vào cùng lúc với component Image lúc được thêm vào đối tượng.
Bạn có thể đạt được điều này bằng cách sử dụng cú pháp sau
Chỉ cần viết [RequireComponent (typeof (component name))] trong phần định nghĩa class
Ví dụ:
|
|
Sau đó, nếu bạn thêm component player vào GameObject như thế này, component PlayerData sẽ được tự động thêm vào
Không thể loại bỏ component được chỉ định bởi RequestComponent
Nếu bạn muốn loại bỏ component được chỉ định bởi RequiComponent, bạn có thể xử lý nó theo hai cách sau.
- Xóa RequestComponent bên trong mã
- Loại bỏ component chứa RequestComponent trước khi loại bỏ component được chỉ định bởi RequireComponent
Bạn nên sử dụng RequestComponent, vì bạn có thể tránh được việc quên đính kèm component. Đây là một kỹ thuật component mà bạn chắc chắn nên nhớ.
Giống như ví dụ trên, trước tiên bạn cần xóa component Player trước khi có thể xóa component PlayerData
Sử dụng DisallowMultipleComponent để cấm thêm các component trùng lặp vào đối tượng
Có những trường hợp bạn không muốn đính kèm cùng một component vào một GameObject nhiều hơn một lần. Điều này có thể đạt được bằng cách sử dụng DisallowMultipleComponent.
|
|
DisallowMultipleComponent cũng cấm thêm component từ script
Thoạt nhìn, DisallowMultipleComponent có vẻ là một hạn chế chỉ trên trình soạn thảo Unity, nhưng nó thực sự cũng chặn AddComponent khỏi các tập lệnh. Trong khi chạy Unity, bạn sẽ nhận được thông báo sau về các lần thử AddComponent trùng lặp và không có component nào được thêm vào.
|
|
Hãy nhớ rằng DisallowMultipleComponent hữu ích khi bạn thực sự muốn chỉ có một component cho một Type.
Add Component Menu
Bạn thực sự có thể thêm các thành phần của riêng mình vào “Component Menu”
Nó rất dễ làm. Chỉ cần thêm một AddComponentMenu trước định nghĩa class như sau
```csharp
using UnityEngine;
[AddComponentMenu(“Gamespace/Unit/Player”)] public class Player : MonoBehaviour { }
|
|
Tất nhiên bạn có thể đạt được kết quả tương tự bằng cách null như đã nêu ở ví dụ trước đó. Bạn có thể sử dụng TryGetComponent nó được thêm vào từ Unity 2019.2 nó sẽ không phân bổ GC trong EDITOR nếu đối tượng không có component Bạn có thể chọn cách sử dụng nào đều được điều đó không ảnh hưởng đến performance
Thêm / Xóa component vào nhiều GameObject cùng một lúc
Bạn đã bao giờ muốn thêm một component vào nhiều GameObject cùng một lúc chưa?
Trên thực tế nó là có thể. Đầu tiên bạn chọn tất cả GameObject bạn muốn thêm trong cửa sổ Hierarchy Sau đó, bạn có thể thêm tất cả chúng cùng một lúc và rút ngắn thời gian làm việc.
Điều tương tự cũng áp dụng cho việc xóa. Nếu bạn đang thêm cùng một component. Chỉ cần chọn nhiều GameObject và nhấp vào remove component. Nó không phải là một kỹ thuật bạn sử dụng thường xuyên, nhưng nó là một kỹ thuật hữu ích có thể giúp bạn tiết kiệm thời gian nếu bạn biết nó.
Tham chiếu component
Hãy xem ví dụ bên dưới
|
|
sẽ được đổi thành
|
|
hoặc
|
|
Bằng cách khai báo một biến tham chiếu, lượng mã được giảm và quá trình xử lý tìm kiếm của GetComponent tại thời điểm chạy cũng được loại bỏ.
Tất nhiên, kỹ thuật này được giới hạn trong các trường hợp mà bạn có thể đặt tham chiếu trước. Nó không thể được sử dụng khi bạn muốn khai báo các component động trong trò chơi.
Để duy trì sự đóng gói của OOP. Vui lòng sử dụng [SerializeField]
Tìm kiếm toàn bộ trong scene với FindObjectOfType
Ngoài phương thức GetComponent, còn có một phương thức được gọi là FindObjectOfType để tìm kiếm toàn bộ cảnh.
Các phương thức được giới thiệu trước đó được giới hạn trong các GameObject tương đối như chính nó, cha và con.
|
|
FindObjectOfType là một phương pháp hữu ích để lấy một component ở đâu đó trong scene.
Sử dụng FindObjectsOfType nếu cảnh có nhiều component
|
|
Bạn có thể nhận tất cả PlayerMovement trong scene dưới dạng một mảng.
Cả FindObjectsOfType và FindObjectsOfType đều có thể loại trừ các component không hoạt động khỏi mục tiêu tìm kiếm. Điều này giống với GetComponentInChildren.
|
|
Notes
new Component bị cấm
Bạn đang cố gắng tạo MonoBehaviour bằng từ khóa ’new’. Điều này không được phép. MonoBehaviours chỉ có thể được thêm bằng AddComponent
GetComponentInChildren và GetComponentInParent trả về kết quả đầu tiên tìm thấy
GetComponentInChildren tìm kiếm trong hệ thống phân cấp con và GetComponentInParent tìm kiếm trong hệ thống phân cấp cha Cả hai phương thức này đều trả về kết quả đầu tiên mà nó tìm được
Điều quan trọng là thứ tự tìm kiếm. Cả hai đều tìm kiếm từ GameObjects gần đó bắt đầu từ chính nó.
Hãy cẩn thận khi tồn tại nhiều component giống hệt nhau.
Không sử dụng FindObjectOfType nếu có thể
Trong tài liệu Unity
|
|
|
|
Tốt hơn là không sử dụng FindObjectOfType càng nhiều càng tốt.
Nguyên nhân là do nó tìm kiếm toàn bộ scene. Nếu có nhiều GameObject trong scene, điều này tiêu tốn nhiều sức mạnh của CPU và khiến cho sụt giảm khung hình
Do đó, chúng ta hãy tìm hiểu nơi sử dụng FindObjectOfType. Thời điểm tốt nhất là lúc khởi tạo trò chơi sẽ không có vấn đề gì nếu trò chơi bị chậm đôi chút ở đây
FindObjectOfType rất hữu ích. Tuy thuận tiện nhưng nó cũng tiềm ẩn rủi ro lớn. Như đã giải thích ở trên, điều quan trọng là phải xác định cách sử dụng.
Ngoài FindObjectOfType, việc sử dụng phương thức Find cũng nên cẩn thận về hiệu suất.
Phạm vi truy cập của event function
Phạm vi truy cập của event function có thể là bất cứ thứ gì Phạm vi truy cập là các từ khóa được biết như public, private, internal hay protected mà bạn chỉ định cho class, biến hay phương thức
Chúng chỉ định phạm vi truy cập cho các lớp, phương thức và biến. Thông thường, phạm vi truy cập được đặt dựa trên mục đích sử dụng, nhưng Bỏ qua cho các event function.
Nó sẽ được thực thi cho dù nó là public hay private. Tất cả những gì bạn phải làm là viết một event function. Ngay cả khi component bị vô hiệu hóa (enable có giá trị false), vẫn có thể đặt event function thành một phương thức public và thực thi nó từ bên ngoài.
|
|
Như hình trên, phương thức Start được đặt là public. Hãy nhớ rằng tắt một component không có nghĩa là nó sẽ không được gọi, nó chỉ không được thực thi tự động theo system của Unity mà thôi