Unity용 리지드바디 기반 유성 플레이어 컨트롤러

플레이어 컨트롤러를 생성할 때 중력은 일반적으로 아래쪽 한 방향으로만 적용됩니다.

하지만 중심점이 있는 중력은 어떻습니까? 이것은 행성 워커의 직업입니다.

유성 보행기(Planetary Walker)는 플레이어가 구형 물체(행성과 마찬가지로) 위를 걸을 수 있게 해주는 컨트롤러 유형으로, 무게 중심은 구의 중심에 있습니다.

단계

다음은 무게 중심이 Unity인 행성 강체 보행기를 만드는 단계입니다.

  • 원형 레벨로 장면을 엽니다(제 경우에는 장면에 맞춤 제작된 행성 모델과 맞춤 스카이박스가 있습니다)

  • 새 스크립트를 만들고 이름을 "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"
  • 새 캡슐을 만들고 "Player" 개체 내부로 이동한 후 위치를 (0, 1, 0)으로 변경합니다.
  • 캡슐에서 Capsule Collider 구성요소를 제거합니다.
  • Main Camera를 "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의 FPS 플레이어에 크라우칭 추가하기
Unity용 하향식 플레이어 컨트롤러 튜토리얼
Unity용 RTS 및 MOBA 플레이어 컨트롤러
Unity용 자동차 컨트롤러
Unity용 비행기 컨트롤러
Unity용 플레이어 3D 및 2D 벽 점프 튜토리얼