Controler de jucător planetar bazat pe corp rigid pentru Unity

Când creați un controler player, gravitația este de obicei aplicată într-o singură direcție, care este în jos.

Dar cum rămâne cu gravitația cu un punct central? Aceasta este o slujbă pentru plimbătorul planetar.

Un mers planetar este un tip de controler care permite jucătorului să meargă pe un obiect sferic (la fel ca și planetele), cu centrul de greutate fiind în centrul sferei.

Pași

Mai jos sunt pașii pentru a realiza un walker planetar cu corp rigid, cu un punct central de greutate în Unity:

  • Deschide Scena cu nivelul tău circular (în cazul meu am un model de planetă personalizat și un Skybox personalizat în Scenă)

  • Creați un script nou, numiți-l "SC_RigidbodyWalker" și inserați codul de mai jos în el:

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;
    }
}
  • Creați un nou script, numiți-l "SC_PlanetGravity" și inserați codul de mai jos în el:

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);
        }
    }
}
  • Creați un nou GameObject și apelați-l "Player"
  • Creați o nouă capsulă, mutați-o în interiorul obiectului "Player" și schimbați-i poziția în (0, 1, 0)
  • Scoateți componenta Capsule Collider din capsulă
  • Mutați camera principală în interiorul obiectului "Player" și schimbați-i poziția la (0, 1.64, 0)
  • Atașați scriptul SC_RigidbodyWalker la obiectul "Player" (veți observa că va adăuga componente suplimentare, cum ar fi Rigidbody și Capsule Collider).
  • Schimbați înălțimea dispozitivului de coliziune a capsulei la 2 și centrul la (0, 1, 0)
  • Atribuiți variabila Camera principală pentru Camera Player în SC_RigidbodyWalker
  • În cele din urmă, atașați scriptul SC_PlanetGravity obiectului "Player" și atribuiți modelul planetei variabilei Planet

Apăsați pe Play și observați alinierea Playerului cu suprafața planetei:

Sharp Coder Video player

Articole sugerate
Crearea mișcării jucătorilor în Unity
Controler de jucător RTS și MOBA pentru Unity
Controler de avion pentru Unity
Sistem de dialog pentru unitate
Tutorial 3D Worm Controller pentru Unity
Controler de caractere 2D pentru Unity
Controler de elicopter pentru Unity