Rigidbody-baseret Planetary Player Controller til Unity

Når du opretter en spillercontroller, anvendes tyngdekraften normalt kun i én retning, som er nedad.

Men hvad med tyngdekraften med et centralt punkt? Dette er et job for planetvandreren.

En planetarisk rollator er en type controller, der gør det muligt for spilleren at gå på et sfærisk objekt (ligesom planeterne), hvor tyngdepunktet er i midten af ​​kuglen.

Trin

Nedenfor er trinene til at lave en planetarisk rollator med stiv krop med et centralt tyngdepunkt i Unity:

  • Åbn scenen med dit cirkulære niveau (i mit tilfælde har jeg en skræddersyet planetmodel og en brugerdefineret Skybox i scenen)

  • Opret et nyt script, kald det "SC_RigidbodyWalker" og indsæt koden nedenfor i det:

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;
    }
}
  • Opret et nyt script, kald det "SC_PlanetGravity" og indsæt koden nedenfor i det:

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);
        }
    }
}
  • Opret et nyt GameObject og kald det "Player"
  • Opret en ny kapsel, flyt den ind i "Player"-objektet, og skift dens position til (0, 1, 0)
  • Fjern Capsule Collider-komponenten fra kapslen
  • Flyt hovedkameraet inde i "Player"-objektet og skift dets position til (0, 1,64, 0)
  • Vedhæft SC_RigidbodyWalker-scriptet til "Player"-objektet (du vil bemærke, at det vil tilføje yderligere komponenter såsom Rigidbody og Capsule Collider).
  • Skift Capsule Collider Højde til 2 og Center til (0, 1, 0)
  • Tildel hovedkamera til spillerkameravariabel i SC_RigidbodyWalker
  • Til sidst vedhæft SC_PlanetGravity-scriptet til "Player"-objektet og tildel din planetmodel til Planet-variablen

Tryk på Afspil og se, hvordan afspilleren er justeret til planetens overflade:

Sharp Coder Videoafspiller