Rigidbody-basert Planetary Player Controller for Unity

Når du oppretter en spillerkontroller, blir tyngdekraften vanligvis brukt i bare én retning, som er nede.

Men hva med tyngdekraften med et sentralt punkt? Dette er en jobb for planetvandreren.

En planetarisk rullator er en type kontroller som lar spilleren gå på et sfærisk objekt (akkurat som planetene), med tyngdepunktet i midten av sfæren.

Trinn

Nedenfor er trinnene for å lage en planetarisk rullator med stiv kropp, med et sentralt tyngdepunkt i Unity:

  • Åpne scenen med ditt sirkulære nivå (i mitt tilfelle har jeg en skreddersydd planetmodell og en tilpasset Skybox i scenen)

  • Lag et nytt skript, kall det "SC_RigidbodyWalker" og lim inn 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;
    }
}
  • Lag et nytt skript, kall det "SC_PlanetGravity" og lim inn 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);
        }
    }
}
  • Lag et nytt GameObject og kall det "Player"
  • Lag en ny kapsel, flytt den inne i "Player"-objektet, og endre dens posisjon til (0, 1, 0)
  • Fjern Capsule Collider-komponenten fra kapselen
  • Flytt hovedkameraet inne i "Player"-objektet og endre dets posisjon til (0, 1.64, 0)
  • Fest SC_RigidbodyWalker-skriptet til "Player"-objektet (du vil legge merke til at det vil legge til flere komponenter som Rigidbody og Capsule Collider).
  • Endre Capsule Collider Height til 2 og Center til (0, 1, 0)
  • Tilordne hovedkamera til spillerkameravariabel i SC_RigidbodyWalker
  • Til slutt, fest SC_PlanetGravity-skriptet til "Player"-objektet og tilordne planetmodellen din til Planet-variabelen

Trykk på Play og se at spilleren justerer seg etter planetens overflate:

Sharp Coder Videospiller