Contrôleur de lecteur planétaire basé sur Rigidbody pour Unity

Lors de la création d'un contrôleur de joueur, la gravité est généralement appliquée dans une seule direction, vers le bas.

Mais qu'en est-il de la gravité avec un point central ? C'est un travail pour le marcheur planétaire.

Un marcheur planétaire est un type de contrôleur qui permet au joueur de marcher sur un objet sphérique (tout comme les planètes), le centre de gravité étant au centre de la sphère.

Pas

Vous trouverez ci-dessous les étapes pour fabriquer un déambulateur à corps rigide planétaire, avec un point de gravité central en Unity:

  • Ouvrez la scène avec votre niveau circulaire (dans mon cas, j'ai un modèle de planète personnalisé et une Skybox personnalisée dans la scène)

  • Créez un nouveau script, appelez-le "SC_RigidbodyWalker" et collez-y le code ci-dessous:

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;
    }
}
  • Créez un nouveau script, appelez-le "SC_PlanetGravity" et collez-y le code ci-dessous:

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);
        }
    }
}
  • Créez un nouveau GameObject et appelez-le "Player"
  • Créez une nouvelle capsule, déplacez-la à l'intérieur de l'objet "Player" et changez sa position en (0, 1, 0)
  • Retirez le composant Capsule Collider de la capsule
  • Déplacez la caméra principale à l'intérieur de l'objet "Player" et changez sa position en (0, 1.64, 0)
  • Attachez le script SC_RigidbodyWalker à l'objet "Player" (vous remarquerez qu'il ajoutera des composants supplémentaires tels que Rigidbody et Capsule Collider).
  • Changer la hauteur du collisionneur de capsules à 2 et le centre à (0, 1, 0)
  • Affecter la caméra principale à la variable Player Camera dans SC_RigidbodyWalker
  • Enfin, attachez le script SC_PlanetGravity à l'objet "Player" et affectez votre modèle de planète à la variable Planet

Appuyez sur Play et observez le joueur s'aligner sur la surface de la planète:

Sharp Coder Lecteur vidéo

Articles suggérés
Créer le mouvement des joueurs dans Unity
Contrôleur d'avion pour Unity
Tutoriel de contrôleur de lecteur descendant pour Unity
Contrôleur d'hélicoptère pour Unity
Contrôleur de voiture pour Unity
Tutoriel sur le contrôleur de ver 3D pour Unity
Contrôleur de personnages 2D pour Unity