الواجهات وTryGetComponent
جزء من قسم هندسة الألعاب في Unity في رحلة Unity على Coddy. الدرس 8 من 64.
يبحث TryGetComponent عن مكوّن ويخبرك ما إذا كان قد عثر عليه، في استدعاء واحد. وهو يعمل مع الواجهات أيضًا، ما يجعله الطريقة المعتادة لسؤال أي شيء تصيبه عمّا إذا كان يمكن إلحاق الضرر به. هذا اللغم يلحق الضرر بكل ما حوله مما يطبّق IDamageable:
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 المتغيّر داخل الاستدعاء. يُرجع TryGetComponent القيمة true ويملأ target عندما يحتوي الكائن على مكوّن يطبّق IDamageable؛ وإلا فيُرجع false وتكون قيمة target هي null. يبحث في ذلك الكائن وحده، ولا يبحث أبدًا في الكائن الأب أو الكائنات الفرعية.
يتعامل GetComponent بشكل مختلف مع الفئة المفقودة والواجهة المفقودة. في المحرّر، يُرجع GetComponent<Rigidbody>() على كائن لا يحتوي على Rigidbody قيمة null وهمية من Unity: تكون == null صحيحة، لكن ?. لا يتعرّف عليها ويؤدي الاستدعاء إلى إطلاق MissingComponentException. ليس للواجهة قيمة null وهمية: يُرجع GetComponent<IDamageable>() قيمة null حقيقية في C#، لذا يعمل كل من == null و?. معها. يتجنّب TryGetComponent هذا الإشكال في الحالتين، ولا يخصّص أي ذاكرة في المحرّر عند غياب المكوّن.
التحدي
سهلاكتب Fire() في Laser: شعاع واحد، وأربع نتائج.
- أطلق
Physics.Raycastمن البرج على امتدادtransform.forwardلمسافةrange. إذا أخطأ، سجّلMissed. - إذا كان
hit.collider.TryGetComponent(out IDamageable target)، فاستدعِTakeDamage(damage)وسجّل"Hit " + hit.collider.name. - وإلا، إذا كان لديه
Rigidbody، فنفّذAddForce(transform.forward * push, ForceMode.Impulse)وسجّل"Pushed "متبوعًا بالاسم؛ وإلا، سجّل"Blocked by "متبوعًا بالاسم.
اضغط «العب»، ووجّه وأطلق النار في كل الاتجاهات. ثم اضغط «تحقق».
جرّب بنفسك
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()
{
// أطلق شعاعًا إلى الأمام بطول range وحدة، وتعامل مع ما يصيبه
}
}
جميع دروس هندسة الألعاب في Unity
1المكوّنات، لا التسلسلات الهرمية
مكوّنات صغيرةنص برمجي أساسي للعدومكوّنات مجرّدةالمكوّنات تعمل معًامراجعة: برج معياريمراجعة: مدفع مزدوج4البيانات المُسلسلة
الأصناف القابلة للتسلسلالقوائم في Inspectorالتعدادات في Inspectorمراجعة: جدول الغنائممراجعة: اختيار الغنائم عشوائيًا2الواجهات في Unity
IDamageableالواجهات وTryGetComponentGetComponentsمراجعة: مفتاح التفاعلمراجعة: أقرب عنصر ضمن النطاقتدرّب بنفسك: Playground لـ Unity