진행한 것들

캐릭터 이동

캐릭터 이동은 InputController의 MoveAction의 콜백으로 PlayerMovement의 SetDirection을 호출하고 여기서 _direction을 초기화해준다. 이후에 Update에서 프레임마다 호출되는UpdateSpeed로 스피드를 계산해주고 FixedUpdate에서 Move를 호출하여 Rigidbody의 velocity를 세팅하여 적용된다.

- 중력이 필요하기 때문에 Transform으로의 이동 대신 Rigidbody 이동을 선택했다.

- Time.deltaTime이 필요한 계산은 Update로 rigidbody를 사용하는 Move는 FixedUpdate에서 호출하게 했다.

public class InputController : MonoBehaviour
{
    public event Action<Vector2> MoveAction;

    public void OnMove(InputAction.CallbackContext context)
    {
        if (context.canceled)
        {
            CallMoveAction(Vector2.zero);
            return;
        }

        Vector2 inputVec = context.ReadValue<Vector2>();
        // 전달
        CallMoveAction(inputVec);
    }

    private void CallMoveAction(Vector2 inputVec)
    {
        MoveAction?.Invoke(inputVec);
    }
}
[RequireComponent(typeof(Rigidbody))]
public class PlayerMovement : MonoBehaviour
{
    private void Update()
    {
        UpdateSpeed();
        Look();
    }

    private void FixedUpdate()
    {
        Move();
    }

    public void SetDirection(Vector2 direction)
    {
        _direction = direction;
    }

    private void UpdateSpeed()
    {
        _speed = _speedCalculator.CalculateSpeed(
            _controller.StatHandler.Data.SpeedMin,
            _controller.StatHandler.Data.SpeedMax,
            _direction == Vector2.zero);
    }

    private void Move()
    {
        _rigid.velocity = new Vector3(_direction.x, _rigid.velocity.y, 0f) * _speed;
    }
}

 

 

캐릭터 회전

구현해야할 것 : 플레이어가 회전할 때 정면을 바라보게끔 구현 (왼쪽에서 오른쪽으로 돌 때는 반시계방향으로, 오른쪽에서 왼쪽으로 돌 때는 시계방향으로)

문제점 : QuaternionLookRotation을 이용해 회전을 구현하면 제한을 걸기가 힘듬. 뒤를 바라보는 경우가 생기거나 문워크를 하는 경우가 생김

private void Look()
    {
        if (_direction == Vector2.zero)
        {
            transform.rotation = Quaternion.LookRotation(_preDirection);
            return;
        }

        _preDirection = (Vector3.right * _direction.x).normalized;

        Quaternion rotation = Quaternion.Slerp(
            transform.rotation, 
            Quaternion.LookRotation(_preDirection), 
            turningSpeed * Time.deltaTime);

        _rigid.velocity = new Vector3(_direction.x, _rigid.velocity.y, 0f) * speed;
        transform.rotation = rotation;
    }

 

해결 방안 : 이해하기 쉬운 Euler각을 이용하여 각도에 제한을 둠, 여기서 Vector3.SignedAngle()을 이용하여 좌/우측 둘 다 고려, Quaternion.RotateTowards는 더 작은 각도인 쪽으로 도는데 이를 이용한 트릭으로 Circle_Angle에(-90도, 90도) 방향으로 1을 더해주거나 빼줌으로써 정면만 바라보게 했음

public Quaternion CalculateRotation(Quaternion rotation, Vector3 _preDirection)
{
    float targetAngle = Vector3.SignedAngle(Vector3.forward, _preDirection, Vector3.up);

    float rotationY = rotation.eulerAngles.y;

    rotationY = targetAngle < 0 ? rotationY++ : rotationY--;

    if (targetAngle < 0)
        targetAngle += CIRCLE_ANGLE;

    Quaternion startRotation = Quaternion.Euler(new Vector3(rotation.x, rotationY, rotation.z));
    Quaternion targetRotation = Quaternion.Euler(new Vector3(rotation.x, targetAngle, rotation.z));

    Quaternion newRotation = Quaternion.RotateTowards(startRotation, targetRotation, _rotationSpeed);

    return newRotation;
}

 

 

 

오늘의 이슈 / 내일 할 것

내일 할 것 : 캐릭터 점프, 슬라이딩, UI 조이스틱 이동 연결

 

오늘의 회고

 오늘은 캐릭터 이동과 회전을 구현하였다. 이동은 비교적 쉽게 구현하였는데 회전은 신경써야할 게 더 많아서 좀 오래 걸렸던 것 같다. 구조에 대해서도 고민을 했는데 프로토타입이니 일단 구현부터 한 뒤에 리팩토링을 한다고 생각하고 진행해야겠다. 내일도 파이팅!

 

 

참고 : 

https://docs.unity3d.com/ScriptReference/Vector3.SignedAngle.html

 

Unity - Scripting API: Vector3.SignedAngle

The angle returned is the angle of rotation from the first vector to the second, when treating these first two vector inputs as directions. These two vectors also define the plane of rotation, meaning they are parallel to the plane. This means the axis of

docs.unity3d.com

 

+ Recent posts