Menu
CoddyTech

الوقوف على الأرض

جزء من قسم الفيزياء وأسلوب اللعب في رحلة Unity على Coddy. الدرس 11 من 71.

لكل تماس متجه عمودي: اتجاه طوله 1، متعامد على السطح الذي لمسته، ويشير مبتعدًا عنه نحو جسمك. يشير collision.GetContact(0) إلى أول نقطة تماس، ويخبرك normal بأي جانب لمسته. عند الوقوف على أرض مستوية يكون (0, 1, 0)؛ وعند ملامسة جدار على يمينك يكون (-1, 0, 0)؛ وعند ارتطام رأسك بسقف يكون (0, -1, 0).

يميز هذا الصندوق بين الهبوط والارتطام بالجانب:

void OnCollisionEnter(Collision collision)
{
    Vector3 normal = collision.GetContact(0).normal;
    if (normal.y > 0.5f)
    {
        Debug.Log("Landed on " + collision.gameObject.name);
    }
    else
    {
        Debug.Log("Bumped the side of " + collision.gameObject.name);
    }
}

الاختبار هو normal.y > 0.5f بدلًا من 1 بالضبط، حتى تُحتسب المنحدرات أرضًا أيضًا: تكون قيمة y هي 0.5 على منحدر بزاوية 60 درجة، وهو أشد انحدارًا مما يستطيع أي شخص صعوده مشيًا. هناك رسالتان أخريان تساعدان في التعامل مع أي شيء يستمر: تعمل OnCollisionStay في كل خطوة فيزيائية ما دام التماس قائمًا، وتعمل OnCollisionExit مرة واحدة عند انتهائه. لا يحتوي حدث الخروج على نقاط تماس، إذ لم يعد أي شيء يلامس شيئًا آخر، لذا لا تستدعِ GetContact هناك.

challenge icon

التحدي

سهل

اجعل اللاعب يقفز فقط عندما يكون واقفًا على شيء ما.

  1. أضف private bool grounded;. في OnCollisionStay، اجعل قيمته true عندما يكون collision.GetContact(0).normal.y > 0.5f؛ وفي OnCollisionExit، اجعل قيمته false.
  2. في FixedUpdate()، اقفز فقط عند if (jumpPressed && grounded)، واجعل قيمة jumpPressed = false; بعد ذلك if، حتى يُتجاهل الضغط أثناء وجود اللاعب في الهواء.

اضغط على «العب» وجرّب القفز مرتين: الضغط الثاني لا يفعل شيئًا. ثم اضغط على «تحقق».

جرّب بنفسك

using UnityEngine;

public class Hopper : MonoBehaviour
{
    public float speed = 4f;
    public float jump = 6f;
    private Rigidbody rb;
    private bool jumpPressed;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            jumpPressed = true;
        }
    }

    void FixedUpdate()
    {
        float h = Input.GetAxisRaw("Horizontal");
        rb.linearVelocity = new Vector3(h * speed, rb.linearVelocity.y, 0);
        if (jumpPressed)
        {
            rb.AddForce(Vector3.up * jump, ForceMode.Impulse);
            jumpPressed = false;
        }
    }
}

جميع دروس الفيزياء وأسلوب اللعب

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