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: