Unity 的基于刚体的行星播放器控制器

创建 玩家控制器 时,重力通常仅应用于一个方向,即向下。

但是有中心点的引力又如何呢?这是行星行走者的工作。

行星行走器是一种控制器,允许玩家在球形物体(就像行星)上行走,重心位于球体的中心。

脚步

以下是制作行星刚体步行器的步骤,其重心位于 Unity

  • 使用圆形水平仪打开场景(在我的例子中,场景中有一个定制的行星模型和一个定制的 Skybox

  • 创建 一个新脚本,将其命名为 "SC_RigidbodyWalker" 并将以下代码粘贴到其中:

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;
    }
}
  • 创建 一个新脚本,将其命名为 "SC_PlanetGravity" 并将以下代码粘贴到其中:

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);
        }
    }
}
  • 创建一个新的 GameObject 并调用它 "Player"
  • 创建一个新的 Capsule,将其移动到 "Player" 对象内,并将其位置更改为 (0, 1, 0)
  • 从 Capsule 中移除 Capsule Collider 组件
  • 将主摄像机移动到 "Player" 对象内并将其位置更改为 (0, 1.64, 0)
  • SC_RigidbodyWalker 脚本附加到 "Player" 对象(您会注意到它将添加其他组件,例如 Rigidbody 和 Capsule Collider)。
  • 将胶囊碰撞器高度更改为 2,将中心更改为 (0, 1, 0)
  • 在 SC_RigidbodyWalker 中将主摄像机分配给玩家摄像机变量
  • 最后,attach SC_PlanetGravity 脚本到 "Player" 对象并将您的行星模型分配给 Planet 变量

按“播放”并观察播放器与行星表面对齐:

Sharp Coder 视频播放器

推荐文章
在 Unity 中创建玩家运动
Unity 直升机控制器
在 Unity 中向 2D 平台游戏角色控制器添加双跳支持
如何在 Unity 中进行起重机控制
Unity 汽车控制器
角色控制器如何在 Unity 中添加推动刚体的功能
Unity 飞机控制器