[새로 배운] 3D 플레이어 움직임

가이등·2022년 9월 19일
0

John Lemon 프로젝트

목록 보기
2/8

이 글은 다음의 내용을 참고하여 작성하였습니다.


⚡ John Lemon 프로젝트에서 플레이어 움직임 구현 방식

해당 프로젝트에서는 주인공 프리팹과 2개의 애니메이션(idle, walk)이 제공된다.

왼쪽/오른쪽으로 꺾는 애니메이션이 없기 때문에 해당 애니메이션은 주인공 오브젝트 자체를 이동 방향으로 회전하는 방식으로 구현한다.


⚡ 회전 방향 설정

void FixedUpdate() {
	Vector3 movement;
	Quaternion rotation;

	float horizontal = Input.GetAxis("Horizontal");
    float vertical = Input.GetAxis("Vertical");
   
    movement.Set(horizontal, 0f, vertical);
    movement.Normalize();
    
    float turnSpeed = 20f;
    
	Vector3 desiredForward = Vector3.RotateTowards(transform.forward, movement, turnSpeed * Time.deltaTime, 0f);
	rotation = Quaternion.LookRotation(desiredForward);
    
    ...
    
}
Input.GetAxis("Horizontal");
//왼쪽 이동 키(←, a키)가 입력되면 0 ~ -1 값을, 오른쪽 이동키 (→, d키)가 입력되면 0 ~ 1 값을 리턴

Input.GetAxis("Vertical");
//아래쪽 이동 키(↓, s키)가 입력되면 0 ~ -1 값을, 오른쪽 이동키 (↑, w키)가 입력되면 0 ~ 1 값을 리턴

유니티 Edit > Project Settings > InputManager > Axes에서 GetAxis() 에 들어가는 인수 "Horizontal"과 "Vertical"의 정보를 확인할 수 있다.

Input.GetAxis()의 리턴값은 움직이지 않을 수록 0에, 해당 방향으로 움직일 수록 1 또는 -1에 가까워진다.

movement.Set(horizontal, 0f, vertical);
//플레이어가 움직일 방향을 나타내는 벡터 movement를 설정한다.

movement.Normalize();
//벡터의 방향은 그대로, 크기는 1로 만들어준다.


Normalize 과정을 거치지 않으면 플레이어는 대각선으로 이동할 때 더 빠르게 이동하며, 이는 의도하지 않은 동작이므로 Normalize 과정이 필요하다.

Vector3.RotateTowards(Vector3 current, Vector3 target, float maxRadiansDelta, float maxMagnitudeDelta);
//current 벡터를 target 벡터를 항하도록 회전한 값을 리턴하는 것 같다. (원문: Rotates a vector current towards target.)
//maxRadiansDelta는 각도의 변화량, maxMagnitudeDelta는 크기의 변화량을 의미한다.

transform.forward
//해당 transform을 가진 오브젝트에서 정면(Z축)을 보는 크기 1의 벡터를 리턴한다.

명확하게 이해되지는 않지만 Vector3.RotateTowards()는 current 벡터와 target 벡터를 참고하여 회전 벡터를 리턴하는 것 같다.
maxRadiansDelta의 경우 값이 올라가면 회전 속도가 빨라지고, 내려가면 느려진다.

Quaternion.LookRotation(Vector3 forwards)
//벡터 forwards 방향을 바라보는 회전 상태(Quaternion)를 반환한다. 

오브젝트의 회전값을 가지는 transform.rotation은 쿼터니언으로만 수치를 조정할 수 있다.

따라서 Vector3.RotateTowards()로 얻은 desiredForward(원하는 회전 방향) 벡터 값을 오브젝트에 적용하기 위해서 Quaternion.LookRotation()을 통해 쿼터니언으로 변환한다.

쿼터니언은 유니티에서 내부적으로 각도를 다루는 방법이며, 자세한 내용은 나중에 제대로 공부해 보아야 할 것 같다.


⚡ 회전, 이동 적용

void FixedUpdate() {

	...
    
	rigidbody.MovePosition(rigidbody.position + movement);
	rigidbody.MoveRotation(rotation);
}

이전에 계산해놓은 movement 벡터와 rotation 쿼터니언 변수를 사용한다.

계산한 값을 오브젝트의 rigidbody에 적용한다.


⚡ 이동하는 지 체크

bool hasHorizontalInput = !Mathf.Approximately(horizontal, 0f);
bool hasVerticalInput = !Mathf.Approximately(vertical, 0f);
bool isWalking = hasHorizontalInput || hasVerticalInput;
Mathf.Approximately(float a, float b);
//a가 b와 근사하면 true, 아니면 false를 리턴한다.

horizontal이 0 에 근사하면
Mathf.Approximately(horizontal, 0f) 는 true,
!Mathf.Approximately(horizontal, 0f) 는 false가 되며
수평 움직임이 있는지 체크하는 hasHorizontalInput 이 올바른 값(false)을 가지게 된다.

변수 isWalking은 애니메이션 설정 관련에서 유용하게 사용할 수 있다.


⚡ 결과

이동 방향에 맞게 움직이고 오브젝트가 회전하는 것을 확인할 수 있다. ‡

profile
안녕하세요구르트

0개의 댓글