Giao diện và TryGetComponent
Thuộc phần Kiến trúc trò chơi trong Unity trong hành trình Unity của Coddy. Bài học 8 trên 64.
TryGetComponent tìm một thành phần và cho bạn biết liệu nó có tìm thấy thành phần đó hay không, chỉ trong một lần gọi. Phương thức này cũng hoạt động với giao diện, nên đây là cách thường dùng để hỏi đối tượng bạn va phải xem nó có thể bị gây sát thương hay không. Quả mìn này gây sát thương cho mọi thứ xung quanh có thể nhận sát thương:
public class Mine : MonoBehaviour
{
public float radius = 3f;
public int damage = 5;
void OnTriggerEnter(Collider other)
{
foreach (Collider c in Physics.OverlapSphere(transform.position, radius))
{
if (c.TryGetComponent(out IDamageable target))
{
target.TakeDamage(damage);
}
}
Destroy(gameObject);
}
}out IDamageable target khai báo biến ngay trong lời gọi. TryGetComponent trả về true và gán giá trị cho target khi đối tượng có một thành phần triển khai IDamageable; nếu không thì phương thức trả về false và target là null. Phương thức chỉ kiểm tra chính đối tượng đó, không kiểm tra đối tượng cha hay con.
GetComponent báo thiếu lớp và thiếu giao diện theo cách khác nhau. Trong Editor, GetComponent<Rigidbody>() trên đối tượng không có Rigidbody trả về null giả của Unity: == null cho kết quả true, nhưng ?. không nhận ra giá trị này và lời gọi gây ra MissingComponentException. Giao diện không có null giả: GetComponent<IDamageable>() trả về null thực của C#, nên cả == null và ?. đều hoạt động. TryGetComponent tránh vấn đề này trong cả hai trường hợp, đồng thời không cấp phát gì trong Editor khi thiếu thành phần.
Thử thách
DễViết Fire() trong Laser: một tia, bốn kết quả.
- Bắn
Physics.Raycasttừ tháp dọc theotransform.forward, với độ dàirange. Nếu bắn trượt, ghi lạiMissed. - Nếu
hit.collider.TryGetComponent(out IDamageable target), gọiTakeDamage(damage)và ghi lại"Hit " + hit.collider.name. - Nếu không, nếu đối tượng có
Rigidbody, gọiAddForce(transform.forward * push, ForceMode.Impulse)và ghi lại"Pushed "cùng với tên; nếu không thì ghi lại"Blocked by "cùng với tên.
Nhấn Chơi, xoay và bắn theo mọi hướng. Sau đó nhấn Kiểm tra.
Tự làm thử
using UnityEngine;
using UnityEngine.InputSystem;
public class Laser : MonoBehaviour
{
public float range = 10f;
public int damage = 1;
public float push = 5f;
public float turnSpeed = 90f;
private InputAction moveAction;
void Start()
{
moveAction = InputSystem.actions.FindAction("Move");
}
void Update()
{
float turn = moveAction.ReadValue<Vector2>().x;
transform.Rotate(0f, turn * turnSpeed * Time.deltaTime, 0f);
if (Keyboard.current.spaceKey.wasPressedThisFrame)
{
Fire();
}
}
void Fire()
{
// Phóng một tia dài range đơn vị về phía trước và xử lý đối tượng mà tia chạm phải
}
}
Tất cả bài học trong Kiến trúc trò chơi trong Unity
1Thành phần, không phải hệ thống phân cấp
Thành phần nhỏTập lệnh kẻ địch cơ sởThành phần trừu tượngCác thành phần phối hợp với nhauÔn tập: tháp pháo mô-đunÔn tập: pháo nòng đôi4Dữ liệu tuần tự hóa
Lớp có thể tuần tự hóaDanh sách trong InspectorKiểu liệt kê trong InspectorÔn tập: Bảng vật phẩm rơiÔn tập: Quay vật phẩm2Giao diện trong Unity
IDamageableGiao diện và TryGetComponentGetComponentsÔn tập: phím tương tácÔn tập: đối tượng gần nhất trong tầm với5ScriptableObjects
Tài sản dữ liệuChỉ số vũ khíCài đặt dùng chungLưu gióSóng dưới dạng dữ liệuÔn tập: Cơ sở dữ liệu vật phẩmÔn tập: Mua hàng từ cửa hàng8Code có thể tái sử dụng
Phương thức mở rộngSingleton tổng quátCác hàm hỗ trợ tổng quátÔn tập: FindNearest3Sự kiện
Sự kiện C# trong UnityĐăng ký trong OnEnableCác trường UnityEventSự kiện điều khiển UIÔn tập: Cửa sổ bật lên thành tíchÔn tập: Bộ hẹn giờ cửa sổ bật lên6Lưu dữ liệu bằng JSON
JsonUtilityLưu trò chơiTải dữ liệu và giá trị mặc địnhÔn tập: các ô lưuChọn và xóa một ô lưu9Tái sử dụng đối tượng bằng pool
Vì sao cần pool đối tượngPool dùng hàng đợiObjectPool của UnityÔn tập: pool đạnTự luyện tập: Playground Unity