Starter Assets 파헤치기(1)

cometrue·2024년 8월 12일
0

1. 기본세팅


기본적인 지형과 플레이어를 생성한다.


Player에게 PlayerMove.cs와 Player Input을 생성한다.


다음과 같이 세팅해준다.

WASD키를 입력하여 이동할 수 있고 카메라가 바라보는 방향을 기준으로 전후좌우로 움직일 수 있다.
LEFT SHIFT키를 입력하여 달릴 수 있다

2. 움직임구현

PlayerMove.cs

using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif

[RequireComponent(typeof(CharacterController))]
#if ENABLE_INPUT_SYSTEM
[RequireComponent(typeof(PlayerInput))]
#endif
public class PlayerMove : MonoBehaviour
{
    [Header("Player")]
    [Tooltip("Player의 움직이는 속도 m/s")]
    public float MoveSpeed = 2.0f;

    [Tooltip("Player의 달리는 속도 m/s")]
    public float SprintSpeed = 5.335f;

    [Tooltip("가속 및 감속")]
    public float SpeedChangeRate = 10.0f;

    [Tooltip("Player가 이동 방향을 향하도록 하는 회전속도")]
    [Range(0.0f, 0.3f)]
    public float RotationSmoothTime = 0.12f;

    // player
    private float _speed;
    private float _animationBlend;
    private float _targetRotation = 0.0f;
    private float _rotationVelocity;
    private float _verticalVelocity;



    private Inputs _input;
    private CharacterController _controller;
    private GameObject _mainCamera;


    private void Awake()
    {       
        if (_mainCamera == null)
        {
            _mainCamera = GameObject.FindGameObjectWithTag("MainCamera");
        }
    }

    void Start()
    {
        _input = GetComponent<Inputs>();
        _controller = GetComponent<CharacterController>();
    }

    // Update is called once per frame
    void Update()
    {
        Move();
    }

    private void Move()
    {
        //이동속도와 달리기 속도는 달리기를 누른 기준으로 목표속도를 설정한다.
        float targetSpeed = _input.sprint ? SprintSpeed : MoveSpeed;

        //(Vector2의 == 연산자는 근사값을 사용해 비교하기 때문에
        //float-point-error(부동 소수점 오차 - 1.1+0.1 != 1.2같은 오류)가 발생하지 않으며
        //magnitude를 사용하는 것보다 비용이 적다.)
        if (_input.move == Vector2.zero)
        {
            targetSpeed = 0.0f;
        }

        //플레이어의 수평속도 
        float currentHorizontalSpeed = new Vector3(_controller.velocity.x, 0.0f, _controller.velocity.z).magnitude;

        float speedOffset = 0.1f;
        float inputMagnitude = _input.analogMovement ? _input.move.magnitude : 1f;

        //목표 속도까지 가속 또는 감속
        if (currentHorizontalSpeed < targetSpeed - speedOffset ||
           currentHorizontalSpeed > targetSpeed + speedOffset)
        {
            // 선형적인 결과가 아닌 곡선적인 부드러운 속도 변화를 나타낸다.
            // Lerp의 T는 클램프로 고정되어 있으므로 속도를 클램프할 필요가 없다.
            _speed = Mathf.Lerp(currentHorizontalSpeed, targetSpeed * inputMagnitude,
                Time.deltaTime * SpeedChangeRate);

            // 속도를 소수점 3자리까지 반올림한다
            _speed = Mathf.Round(_speed * 1000f) / 1000f;
        }
        else
        {
            _speed = targetSpeed;
        }

        _animationBlend = Mathf.Lerp(_animationBlend, targetSpeed, Time.deltaTime * SpeedChangeRate);
        if (_animationBlend < 0.01f)
        {
            _animationBlend = 0f;
        }


        // 방향 정규화
        Vector3 inputDirection = new Vector3(_input.move.x, 0.0f, _input.move.y).normalized;

        //이동 입력이 있는 경우 플레이어가 이동할 때 플레이어를 회전시킨다
        if (_input.move != Vector2.zero)
        {
            _targetRotation = Mathf.Atan2(inputDirection.x, inputDirection.z) * Mathf.Rad2Deg +
                              _mainCamera.transform.eulerAngles.y;
            float rotation = Mathf.SmoothDampAngle(transform.eulerAngles.y, _targetRotation, ref _rotationVelocity,
                RotationSmoothTime);

            // 카메라 위치를 기준으로 입력 방향을 향하도록 회전한다.
            transform.rotation = Quaternion.Euler(0.0f, rotation, 0.0f);
        }

        Vector3 targetDirection = Quaternion.Euler(0.0f, _targetRotation, 0.0f) * Vector3.forward;


        // Player를 움직인다. 
        _controller.Move(targetDirection.normalized * (_speed * Time.deltaTime) +
                         new Vector3(0.0f, _verticalVelocity, 0.0f) * Time.deltaTime);

    }
}

Inputs.cs

using UnityEngine;

#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif

public class Inputs : MonoBehaviour
{
    [Header("Character 입력값")]
    public Vector2 move;
    public bool sprint;


    [Header("이동 설정")]
    public bool analogMovement;


#if ENABLE_INPUT_SYSTEM
    public void OnMove(InputValue value)
    {
        MoveInput(value.Get<Vector2>());
    }
    public void OnSprint(InputValue value) 
    {
        SprintInput(value.isPressed);
    }
#endif
    public void MoveInput(Vector2 newMoveDirection)
    {
        move = newMoveDirection;
    }
    public void SprintInput(bool newSprintState)
    {
        sprint = newSprintState;
    }
}
  1. Animation
profile
게임개발자

0개의 댓글