* 진짜 오랜만에 쓰는 틸,,
일주일동안 한 것!
✨ 플레이어의 움직임 & 상태머신
✨ 주방기구 만들기
✨ 주방기구 - 플레이어 상호작용
✨ 요리 과정
어느 정도 구현이 되고 나니 뿌듯하기도 하고..
정말...정말 많은 일이 있었다..
우선 어제까지 구현한 모습! (지금은 수정 중)
우리 귀여운 아기토끼 진짜 열심히 일해요
팀 내에서 가장 부족한 사람인데 어쩌다보니 물리적인 반응이 요구되거나 움직이는 것들만 내가 맡게 되었다.
움직임이 들어가니 정말... 예상치 못한 일들이 너무 많이 일어나고 원하는 대로 잘 되지 않는다.
하지만 해냈죠?????? 🔥 🔥 🔥 🔥
아무튼 우리팀 사람들 다들 너무 잘하고... 저걸 어떻게 다 하나 싶고.. 그래서 멘탈이 더 나가는 것도 있지만 동시에 멘탈 잡아주는 것도 우리 팀원들이다 ❤ ❤
출시까지 가보자고.
기록
한 일을 크게 나누어보면 다음과 같다 :
1. 플레이어 움직임 구현
2. 상호작용 구현
3. 레일 구현
4. 상호작용 구조 수정
1. 플레이어 움직임 구현
- 테스트를 계속 진행하면서 Input System이 진짜 좋다는 것을 느꼈다. PC에서 가상조이스틱을 움직이면서 버튼을 동시에 누를 수 없어 키보드로 테스트하고자 했는데, 원래 쓰던 Input Actions에서 binding만 추가해주면 되는 것
- 가상 조이스틱의 경우에는 지난 번 TIL에 썼던 InputSystem의 OnScreenStick을 그대로 쓰고 있다. 하지만 모바일로 테스트 했을 때, 첫 터치가 핸들에 정확하게 위치하지 않으면 인식되지 않는 등의 불편함이 있었다. 그래서 시작 터치 범위를 변경하기 위해 스크립트를 새로 쓰거나, 핸들 부분 UI 이미지 크기를 키워서(여백이 많은 이미지로) 테스트 해보는 방법을 시도해봐야 할 것 같다.
private void ReadMovementInput()
{
stateMachine.MovementInput = stateMachine.Player.Input.PlayerActions.Move.ReadValue<Vector2>();
}
protected virtual void Move()
{
Vector3 movementDirection = GetMovementDirection();
float movementSpeed = stateMachine.Player.movementSpeed;
Vector3 targetPosition = stateMachine.Player.gameObject.transform.position + movementDirection;
Vector3 newPosition = Vector3.Slerp(stateMachine.Player.gameObject.transform.position, targetPosition, movementSpeed * Time.deltaTime);
newPosition.y = 0;
stateMachine.Player.gameObject.transform.position = newPosition;
if (movementDirection == Vector3.zero) return;
float rotationSpeed = 5.0f;
Quaternion targetRotation = Quaternion.LookRotation(movementDirection);
Quaternion newRotation = Quaternion.Slerp(stateMachine.Player.gameObject.transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
stateMachine.Player.gameObject.transform.rotation = newRotation;
}
private Vector3 GetMovementDirection()
{
Vector3 forward = Vector3.forward;
Vector3 right = Vector3.right;
return forward * stateMachine.MovementInput.y + right * stateMachine.MovementInput.x;
}
- 플레이어의 움직임은 단순하게 Input System으로 방향 정보를 받아와서 transform을 변경하는 방식을 사용했다. 처음에는 카메라가 비추는 화면을 기준으로 상하좌우를 결정했는데, 카메라를 Orthographic으로 설정하지 않는 이상 화각에 의해 움직임에도 왜곡이 생겨 불편함이 있었다. 이 부분도 단순하게 월드의 X축과 Z축을 기준으로 움직이도록 설정했다. 맵과 카메라 방향이 월드의 forward와 일치하면 이렇게 하는 것이 가장 깔끔한 것 같다.
- 움직임과 회전이 뚝뚝 끊기는 게 싫어서 Slerp로 처리하고 있는데, 드라마틱한 효과가 있는지는 모르겠다... 조작감이 좋지는 않다는 평이 있어서 움직임 구현은 다시 수정하고 싶다 무조건.
- 상태머신은 정말 복잡하긴 하다! 조건에 따라 다른 상태로 넘어가기도 해야 하고, 상태는 넘어가지만 실제 상호작용 메서드는 호출하지 않아야 하는 등 다양한 상황에 의해 복잡하게 얽혀 있다. 최대한 풀고 싶었는데, 다른 코드들에 비해 시급한 편은 아니라 리팩토링을 바로 진행하지는 않았다. 그래도 나름 구조를 염두하면서 만들었더니 크게 문제가 발생하지는 않는다.
- 아무튼 지금까지 개발하면서 느낀 것은 상태머신을 선택한 것 자체는 좋은 선택이었던 것 같다. 플레이어의 동작, 애니메이션, 상호작용/픽업 메서드가 상태에 영향을 받기 때문에 상태머신에서 일관성 있게 처리할 수 있어서 상태머신을 사용하지 않을 때보다 깔끔할 것 같다고 느꼈다.
2. 상호작용 구현 (줍기, 내려놓기 포함)
- 1차 상호작용은 이런 방식으로 구현했다. KitchenInteraction은 주방기구들이 상속받는 상위 클래스이다. 각 주방기구들의 스크립트에서 구체적인 메서드를 오버라이드 하고 있고, 주방기구들은 플레이어를 감지해서 자신의 메서드를 플레이어의 이벤트에 걸어둔다. 실제 Input이 들어와서 상태가 변경될 때 해당 메서드들이 실행되면서 상호작용이 일어나게 된다.
- 메서드를 전달하는 형태 자체는 괜찮았으나, 주방기구가 플레이어를 인식하는 과정에서 트리거 체크를 하다 보니 문제점이 꽤 발생했다. 따라서 주방기구의 구조를 전체적으로 수정하는 일이 있었다. 이 부분은 4번에서
3. 레일 구현
애증의 레일...
- 레일이 가장 많은 문제를 불러일으켰다. 아무래도 자신이 움직이는 것도 아니고 다른 놈을 움직이다보니까...
- 레일의 벨트가 돌아가는 모양새는 머티리얼의 offset을 조절하도록 했다.
- 벨트 내부에 ConvetyPots라는 컴포넌트와 콜라이더가 붙은 오브젝트를 두었다. 현재 로직은 콜라이더에 감지된 물체가 Movable 컴포넌트를 가지고 있을 경우 자신이 가지고 있는 방향으로 transform을 옮기도록 했다.
- 사실 벨트가 냄비들 옮기는 로직만 한 5번은 수정한 것 같다. (레일이 자신 위의 물체를 밀어내는 직관적인 사실에 기반해서) Rigidbody의 AddForce를 쓰는 방법도 써보고, ConveyPots의 자식요소로 냄비를 집어넣어서 움직이는 방식도 해보았다 (효율성 문제)
- 가장 고민되었던 부분은 서로 다른 월드 방향으로 물체를 옮기고 있는데, (y축 방향이 아닌) 움직이는 방향에 수직인 방향은 ConveyPots의 중심에 고정시켜야 안정적으로 가동할 수 있다는 것이었다. 냄비가 해당 ConveyPots에 닿을 때 자식요소로 넣는다면 해결이 되긴 하는데, 냄비가 한 바퀴 돌 때마다 8번 부모가 바뀌게 되고 냄비가 최대 6개가 될 수 있으니 게임이 돌아가는 시간 동안 정말 비효율적인 동작을 하게 될 것 같았다. 쓰다 보니 각 ConveyPots의 중심점을 구해서 고정시키는 방법도 괜찮을 것 같다. 대각선만 로직을 잘 짜면 될 듯하니 주말에 시도해봐야겠다.
- 우선은 콜라이더를 미세하게 조정해서 냄비가 감지되는 타이밍, 냄비가 나가지 못하도록 막아둔 콜라이더에 닿일 때의 각 등을 잘 맞추어 현재까지 문제가 발생하지는 않았다. (하지만 애초에 안정적인 구조라 할 수 없고 언제 어떻게 무슨 문제가 발생할지 모르기 때문에 변경해야 할 듯)
4. 상호작용 구조 수정
처음 콜라이더를 통해 트리거 감지를 한 이유는 지속적으로 상호작용 중인 주방기구를 체크하기보다는 상호작용 대상에 처음 닿았을 때만 호출해서 효율을 높이고 싶었기 때문이다.
하지만 트리거 체크로 인해 문제가 많이 발생했다.
두 개 이상의 주방기구가 플레이어의 콜라이더에 닿아서 상호작용/픽업 기능이 제대로 호출되지 않는 문제,
잔잔바리 오류들로 인해 추가적인 예외처리가 늘어나면서 코드가 더러워지는 문제,
주방기구가 플레이어를 인식하면서 정보 전달에서 오류가 발생하는 문제 등
결국 플레이어가 자신이 상호작용 중인 대상을 인식하고, 이를 관리하는 것이 효율적일 것이라는 판단을 했고, 플레이어 콜라이더가 아닌 RayCast를 활용해서 감지 대상의 콜라이더 크기를 늘리고, 감지 주체의 감지 수단 면적을 좁혀서 정확한 판단을 하도록 하는 것이 게임성에 좋을 것 같다는 판단을 했다.
걸리는 부분은 플레이어가 RayCast체크를 Update에서 하고 있기 때문에 프레임마다 메서드가 호출된다는 것이다.
효율에 얼마나 걸리는지 다시 한 번 체크해보기...
✨ 아무튼 우리 게임 우당탕탕하고 귀여워요 🐇🍡
TODO
✅ 가상 조이스틱 수정
✅ 플레이어 움직임 조작감 좋게 수정할 수 있는 방법 찾기
✅ 레일 로직 수정해보기
'👾 내일배움캠프 > 🎮 TIL & WIL' 카테고리의 다른 글
내일배움캠프 65일차 TIL - 씬 전환 (1) | 2023.11.15 |
---|---|
내일배움캠프 61일차 TIL - 델리게이트 / 이벤트 / 람다 (0) | 2023.11.09 |
내일배움캠프 55일차 TIL - InputSystem과 가상 조이스틱 (On-Screen Button / On-Screen Stick) (0) | 2023.10.31 |
내일배움캠프 54일차 TIL - struct와 class (0) | 2023.10.29 |
내일배움캠프 53일차 TIL - 접근제한자에 대한 이해 (0) | 2023.10.26 |