-
안녕하세요.
플레이어는 현재 조이스틱의 컨트롤러를 움직여
방향을 지정한 값을 PlayerMovement에 넘겨주어
이동을 하는 방식입니다.
맵을 디자인 하시는 분도 계시고
다른 퀴즈를 준비하는 분도 계셨고,
다양한 패턴의 적을 구현하는 분도 계셨습니다.
모두 이 플레이어를 이용해 동작을 구현하고 계셨기에
어찌 보면 중심이 되었다고도 할 수 있습니다.
요청이 들어온 것은 아니지만
회의를 하던 중
나중에 주석처리 및 보류를 하더라도
PC환경에서 테스트를 수월하게 할 수 있게
키보드로 값을 받아오는 건 어떨까? 하고 얘기가 나왔습니다.
저는 흔쾌히 승낙을 했고, 바로 집에 가서 코드를 작성했습니다.
코드를 작성하려던 저는
카메라 회전도 같이 된다면 좀 더 몰입감을 줄 수 있지 않을까?
라는 생각이 들어서
간단하게 테스트 동작 후 팀원들에게 보여줬고
긍정적인 답변을 받았습니다.
카메라를 제어하기 위해 FollowCam의 스크립트를 생성 후 작성하였습니다.
disAway : 플레이어로부터 카메라가 떨어져 있는 거리입니다.
diUp : 플레이어로부터 카메라가 떨어져 있을 높이입니다.
간단하게 그림을 보자면 이러한 그림이 됩니다.
(마우스라 그럽니다 손으로 그리면 잘 그립니다.)mouseX : GetAxis("Mouse X")의 반환 값을 받아올 변수입니다.
cam_Axis : 카메라의 중심 오브젝트입니다.
cam : 메인 카메라입니다.
메인 카메라는 CamAxis의 자식 오브젝트로 설정해 두었습니다.
즉 MainCamera가 직접 움직이지 않고
camAxis를 회전시키면 회전에 따른 MainCamera가 이동되는 구현을 위함입니다.
camSpeed : 카메라의 회전 스피드 값입니다.
카메라의 회전되는 기능의 함수인 CamMove는
Input.GetMouseButton(0)으로 마우스의 왼쪽 버튼이 눌린 상태에서만 가능하게 했습니다.
또한 Update 가 아닌 LateUpdate에서 해 주었는데
모든 Update가 실행되고 난 후 호출되는 함수로
호출 순서에 의해 카메라가 떨리는 현상을 방지하기 위함입니다.
CamMove함수입니다.
회전축을 x축만 회전을 할 것이기에
"Mouse X"의 값을 누적시켜 주었습니다.
Mouse X는 마우스의 X축 좌표를 -1.0f ~ 0 ~ 1.0f의 값을 반환해 줍니다.
이후 회전을 메인 카메라가 아닌 메인 카메라의 부모로 있는
cam_Axis를 쿼터니언 오일러 값으로 받아와 주었습니다.
주의점? 은 이동 값과 회전 값을 깜빡하지 않아야 하는 점입니다.
예를 들어 마우스의 이동 x축 이동 방식은
회전 값의 y축 이랑 같습니다.
또한 상/하로 움직이는 이동 y축 방식은
회전 값의 x축이 회전되는 것과 같습니다.
한 가지 더불어 y축은 현재 쓰이진 않았지만,
흔히 한국에서 생각하는 상/하 의 값이 반대로 되어있는 점이 있는데
이것을 해결하려면 -1을 곱해주면 됩니다.
즉 cam_Axis가 회전이 되면
자식으로 붙어있는 메인 카메라가 회전하는 효과가 보이게 되는 것입니다.
이번엔 PlayerMovement에 있는 Test용 PlayerMoveTest함수입니다.
이 함수는 플레이어의 이동을 키보드로 받게끔 구현되어 있습니다.
첫 번째로 Horizontal과 Vertical을 이용해
-1.0f ~ 0 ~ 1.0f의 상하좌우 w, s, a, d의 반환 값 즉 방향을
movement에 할당해 주었으며
(normalized) 방향벡터를 1로 해서 균일한 이동이 가능하게 만들어 주었습니다.
첫 번째의 조건으로 movement가!- Vector.zero 는
Vector가 0,0,0 이 아닐 시와 같은 말입니다.
즉 속도가 있을 시로 판단하는 조건문입니다.
PlayerAxis는 빈 오브젝트고
player는 현재 보이는 랜더러를 갖고 있는 player입니다.
스크립트는 PlayerAxis가 갖고 있기에
즉 transform은 Player가 아닌 PlayerAxis가 됩니다.
transform.rotation 은 Quaternion.Euler로 회전을 시켜 주었습니다.
간단히 코드를 보자면 현재 cam_Axis의 y축 회전 값과 + Mouse X의 값을 받아오는 코드입니다.
플레이어의 이동은 Translate로 이동시켜 주었습니다.
transform.Translate(movement * playerMoveSpeed * Time.deltaTime)
방향 * 스피드 * Time.deltaTime을 이용해 주어 이동을 시켜 주었으며
player의 실질적인 회전은
player.transform.localRotation = Quaternion.Slerp(
player.transform.localRotation, Quaternion.LookRotation(movement), 6 * Time.deltaTime)에서 이루어집니다.
Slerp함수는 A에서 B까지 0.0 ~ 1.0 퍼센트 비율로 보강하며 좀 더 부드러운 회전이 가능합니다.
구면 선형 보관법 이라고도 불리며
선형 보간법 에는 Lerp가 있습니다.
(다양한 방식들이 존재하기에 하나씩 다 해볼 수 있을까 싶긴 하지만..
기회가 된다면 직접 경험해보며 차이점을 눈에 익히고 싶습니다)
마지막으로 SetFlot의 "Speed"값은 현재 방향의 magnitude(길이)로 지정해 주었습니다.
다들 아시겠지만 한번 더 살펴보자면
현재 Idle에서 Move로 가는 값은
파라미터 float Speed 값으로 전환이 됩니다.
즉 스피드 값이 0.001보다 Greater(높다면) Idle애니메이션에서 Run 애니메이션으로 전환되며
스피드 값이 0.001보다 Less(낮다면) Run애니메이션에서 Idle애니메이션으로 전환됩니다.
마지막으로 플레이어의 이동을 담당하는 PlayerMovement 스크립트에서
cam_Axis의 위치를 플레이어의 위치로 잡아 주며
플레이어의 이동이 가능한 layer가 11 일 때
테스트 함수인 PlayerMoveTest를 실행되게 해 주면 됩니다.
00 : 38초 아직 모바일 환경이 아니라서 그런지..
확실히 테스트 하기도 훨씬 수월해졌으며
뭔가 몰입감이 더해지는 것 같습니다.
무엇보다 직접 움직인다는 것을 느끼게 해주는 것이 중요한 것 같습니다.
오늘은 이만 마치겠습니다.!!
감사합니다.
'팀업 프로젝트 > C.C.I' 카테고리의 다른 글
CCI - 12 - 장애물 2 (0) 2022.05.17 CCI - 11 - 장애물 (0) 2022.05.16 CCI - 09 - 맵 디자인 & Death zone (0) 2022.05.14 CCI - 08 - 플레이어 피격모션 (0) 2022.05.14 CCI - 07 - 적 & 펫 스킬 적용 (0) 2022.05.13