Menu
CoddyTech

الواجهات و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 هذا الإشكال في الحالتين، ولا يخصّص أي ذاكرة في المحرّر عند غياب المكوّن.

challenge icon

التحدي

سهل

اكتب Fire() في Laser: شعاع واحد، وأربع نتائج.

  1. أطلق Physics.Raycast من البرج على امتداد transform.forward لمسافة range. إذا أخطأ، سجّل Missed.
  2. إذا كان hit.collider.TryGetComponent(out IDamageable target)، فاستدعِ TakeDamage(damage) وسجّل "Hit " + hit.collider.name.
  3. وإلا، إذا كان لديه 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

تدرّب بنفسك: Playground لـ Unity