진행한 것들
캐릭터 이동
캐릭터 이동은 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 1기' 카테고리의 다른 글
DevLog - 이그라엘(IGRAL) 플레이어 더블 점프와 구르기 (0) | 2023.10.27 |
---|---|
DevLog - 이그라엘(IGRAL) 플레이어 이동 애니메이션과 상태머신 (1) | 2023.10.26 |
DevLog - 이그라엘(IGRAL) 기획과 플레이어 데이터 (0) | 2023.10.24 |
DevLog - 이그라엘(IGRAL) 기획(1) (1) | 2023.10.23 |
내일배움캠프 50일차 TIL - 한 주 프로젝트 마무리 (0) | 2023.10.20 |