Unity için Rigidbody Tabanlı Planet Oynatıcı Denetleyicisi

Bir oyuncu kontrolörü oluştururken, yer çekimi genellikle yalnızca tek yönde uygulanır, o da aşağı doğru.

Peki ya merkezi bir noktaya sahip olan yerçekimi? Bu gezegen yürüyüşçüsü için bir iştir.

Gezegensel yürüteç, oyuncunun, ağırlık merkezi kürenin merkezinde olacak şekilde küresel bir nesne (tıpkı gezegenler gibi) üzerinde yürümesine olanak tanıyan bir tür kontrol cihazıdır.

Adımlar

Aşağıda, merkezi ağırlık noktası Unity: olan, gezegensel sert cisimli bir yürüteç yapma adımları verilmiştir:

  • Sahneyi dairesel seviyenizle açın (benim durumumda özel yapım bir gezegen modelim ve Sahnede özel bir Skybox var)

  • yeni bir komut dosyası oluşturun, onu "SC_RigidbodyWalker" olarak adlandırın ve içine aşağıdaki kodu yapıştırın:

SC_RigidbodyWalker.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(CapsuleCollider))]

public class SC_RigidbodyWalker : MonoBehaviour
{
    public float speed = 5.0f;
    public bool canJump = true;
    public float jumpHeight = 2.0f;
    public Camera playerCamera;
    public float lookSpeed = 2.0f;
    public float lookXLimit = 60.0f;

    bool grounded = false;
    Rigidbody r;
    Vector2 rotation = Vector2.zero;
    float maxVelocityChange = 10.0f;

    void Awake()
    {
        r = GetComponent<Rigidbody>();
        r.freezeRotation = true;
        r.useGravity = false;
        r.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
        rotation.y = transform.eulerAngles.y;

        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
    }

    void Update()
    {
        // Player and Camera rotation
        rotation.x += -Input.GetAxis("Mouse Y") * lookSpeed;
        rotation.x = Mathf.Clamp(rotation.x, -lookXLimit, lookXLimit);
        playerCamera.transform.localRotation = Quaternion.Euler(rotation.x, 0, 0);
        Quaternion localRotation = Quaternion.Euler(0f, Input.GetAxis("Mouse X") * lookSpeed, 0f);
        transform.rotation = transform.rotation * localRotation;
    }

    void FixedUpdate()
    {
        if (grounded)
        {
            // Calculate how fast we should be moving
            Vector3 forwardDir = Vector3.Cross(transform.up, -playerCamera.transform.right).normalized;
            Vector3 rightDir = Vector3.Cross(transform.up, playerCamera.transform.forward).normalized;
            Vector3 targetVelocity = (forwardDir * Input.GetAxis("Vertical") + rightDir * Input.GetAxis("Horizontal")) * speed;

            Vector3 velocity = transform.InverseTransformDirection(r.velocity);
            velocity.y = 0;
            velocity = transform.TransformDirection(velocity);
            Vector3 velocityChange = transform.InverseTransformDirection(targetVelocity - velocity);
            velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
            velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
            velocityChange.y = 0;
            velocityChange = transform.TransformDirection(velocityChange);

            r.AddForce(velocityChange, ForceMode.VelocityChange);

            if (Input.GetButton("Jump") && canJump)
            {
               r.AddForce(transform.up * jumpHeight, ForceMode.VelocityChange);
            }
        }

        grounded = false;
    }

    void OnCollisionStay()
    {
        grounded = true;
    }
}
  • yeni bir komut dosyası oluşturun, onu "SC_PlanetGravity" olarak adlandırın ve içine aşağıdaki kodu yapıştırın:

SC_PlanetGravity.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SC_PlanetGravity : MonoBehaviour
{
    public Transform planet;
    public bool alignToPlanet = true;

    float gravityConstant = 9.8f;
    Rigidbody r;

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

    void FixedUpdate()
    {
        Vector3 toCenter = planet.position - transform.position;
        toCenter.Normalize();

        r.AddForce(toCenter * gravityConstant, ForceMode.Acceleration);

        if (alignToPlanet)
        {
            Quaternion q = Quaternion.FromToRotation(transform.up, -toCenter);
            q = q * transform.rotation;
            transform.rotation = Quaternion.Slerp(transform.rotation, q, 1);
        }
    }
}
  • Yeni bir GameObject oluşturun ve onu çağırın "Player"
  • Yeni bir Kapsül oluşturun, onu "Player" nesnesinin içine taşıyın ve konumunu (0, 1, 0) olarak değiştirin
  • Kapsül Çarpıştırıcısı bileşenini Kapsülden kaldırın
  • Ana Kamerayı "Player" nesnesinin içine taşıyın ve konumunu (0, 1,64, 0) olarak değiştirin
  • SC_RigidbodyWalker komut dosyasını "Player" nesnesine ekleyin (Rigidbody ve Capsule Collider gibi ek bileşenler ekleyeceğini fark edeceksiniz).
  • Kapsül Çarpıştırıcı Yüksekliğini 2 ve Merkezini (0, 1, 0) olarak değiştirin
  • SC_RigidbodyWalker'da Ana Kamerayı Oyuncu Kamerası değişkenine atayın
  • Son olarak attach SC_PlanetGravity betiğini "Player" nesnesine ekleyin ve gezegen modelinizi Planet değişkenine atayın

Oynat'a basın ve Oynatıcının gezegenin yüzeyine hizalanmasını gözlemleyin:

Sharp Coder Video oynatıcı

Önerilen Makaleler
Unity'de Oyuncu Hareketi Yaratmak
Unity için Yukarıdan Aşağıya Oyuncu Kontrol Eğiticisi
Unity için Helikopter Kontrolörü
Unity için Araç Kontrol Cihazı
Unity için Uçak Kontrol Cihazı
Birlik İçin Diyalog Sistemi
Unity için 2D Karakter Kontrol Cihazı