Rigidbody-baserad Planetary Player Controller for Unity

När du skapar en spelarkontroll appliceras tyngdkraften vanligtvis i bara en riktning, som är nedåt.

Men hur är det med gravitationen med en central punkt? Det här är ett jobb för planetvandraren.

En planetrullator är en typ av kontroller som låter spelaren gå på ett sfäriskt föremål (precis som planeterna), med tyngdpunkten i mitten av sfären.

Steg

Nedan följer stegen för att göra en planetarisk rullator med stel kropp, med en central tyngdpunkt i Unity:

  • Öppna scenen med din cirkulära nivå (i mitt fall har jag en skräddarsydd planetmodell och en anpassad Skybox i scenen)

  • Skapa ett nytt skript, kalla det "SC_RigidbodyWalker" och klistra in koden nedan 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;
    }
}
  • Skapa ett nytt skript, kalla det "SC_PlanetGravity" och klistra in koden nedan 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);
        }
    }
}
  • Skapa ett nytt GameObject och anropa det "Player"
  • Skapa en ny kapsel, flytta den inuti objektet "Player" och ändra dess position till (0, 1, 0)
  • Ta bort Capsule Collider-komponenten från kapseln
  • Flytta huvudkameran inuti objektet "Player" och ändra dess position till (0, 1.64, 0)
  • Bifoga SC_RigidbodyWalker-skriptet till "Player"-objektet (du kommer att märka att det kommer att lägga till ytterligare komponenter som Rigidbody och Capsule Collider).
  • Ändra Capsule Collider Height till 2 och Center till (0, 1, 0)
  • Tilldela huvudkamera till spelarens kameravariabel i SC_RigidbodyWalker
  • Slutligen, fästa SC_PlanetGravity-skriptet till "Player"-objektet och tilldela planetmodellen till planetvariabeln

Tryck på Play och observera spelaren anpassa sig till planetens yta:

Sharp Coder Videospelare

Föreslagna artiklar
Skapa spelarrörelse i Unity
Lägga till stöd för dubbla hopp till en 2D Platformer Character Controller i Unity
2D Character Controller för Unity
Top-Down Player Controller Handledning för Unity
Handledning för 3D Worm Controller för Unity
RTS och MOBA Player Controller for Unity
Spelar 3D och 2D Wall Jump Tutorial för Unity