Rigidbody-gebaseerde Planetary Player Controller for Unity

Bij het maken van een spelercontroller wordt de zwaartekracht meestal in slechts één richting toegepast, namelijk naar beneden.

Maar hoe zit het met de zwaartekracht met een centraal punt? Dit is een taak voor de planetaire wandelaar.

Een planetaire wandelaar is een soort controller waarmee de speler op een bolvormig object kan lopen (net als de planeten), waarbij het zwaartepunt zich in het midden van de bol bevindt.

Stappen

Hieronder staan ​​de stappen om een ​​planetaire rigidbody walker te maken, met een centraal zwaartepunt in Unity:

  • Open de scène met je ronde niveau (in mijn geval heb ik een op maat gemaakt planeetmodel en een aangepaste Skybox in de scène)

  • Maak een nieuw script, noem het "SC_RigidbodyWalker" en plak de onderstaande code erin:

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;
    }
}
  • Maak een nieuw script, noem het "SC_PlanetGravity" en plak de onderstaande code erin:

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);
        }
    }
}
  • Maak een nieuw GameObject en roep het aan "Player"
  • Maak een nieuwe capsule, verplaats deze binnen het object "Player" en verander de positie in (0, 1, 0)
  • Verwijder het Capsule Collider-onderdeel uit de capsule
  • Verplaats de hoofdcamera binnen het object "Player" en wijzig de positie ervan in (0, 1,64, 0)
  • Voeg het SC_RigidbodyWalker-script toe aan het "Player"-object (je zult merken dat er extra componenten worden toegevoegd, zoals Rigidbody en Capsule Collider).
  • Verander de hoogte van de capsule-botser naar 2 en het midden naar (0, 1, 0)
  • Wijs de hoofdcamera toe aan de spelercameravariabele in SC_RigidbodyWalker
  • Tenslotte koppel het SC_PlanetGravity-script aan het "Player"-object en wijs uw planeetmodel toe aan de Planet-variabele

Druk op Play en kijk hoe de speler zich op het oppervlak van de planeet bevindt:

Sharp Coder Video speler

Voorgestelde artikelen
Spelersbeweging in eenheid creëren
Ondersteuning voor dubbele sprongen toegevoegd aan een 2D-platformgame-personagecontroller in Unity
2D-tekencontroller voor Unity
Top-Down Player Controller-tutorial voor Unity
Speler 3D- en 2D-muursprong-tutorial voor Unity
3D-wormcontroller-tutorial voor Unity
Unity Hoe u mobiele aanraakbedieningen maakt