ThirdPersonCamera
목표
마우스 x,y축에 대한 이동을 통해 카메라가 Capsule 오브젝트를 향하면서 공전하는 3인칭 시스템을 만들자
화면 마우스 움직임과 독립적으로 작동하는 wasd 시스템을 만들자
3인칭 카메라 시스템을 구축하자
3인칭은 1인칭과 다르게 카메라의 부모 자식 관계가 해제되어 있어야만 카메라에 여러 add-on을 자연스럽게 붙일 수 있다.(흔들림, damping, collison 등)
카메라와 오브젝트간 부모 자식 관계를 1인칭 3인칭 변환을 고려한다면 먼저 부모 자식 관계로 둔 다음에 3인칭 mode일때는 카메라에 할당된 parent를 null로 바꾸는 방식을 통해서
처리가 가능하다.
TPS Rotatioin
a. Mouse Input binding
Input action으로 마우스의 x, y 축에 대한 입력 값을 받는다.
Value, vector2로 받고 마우스는 delta에 대한 위치를 받아야 한다.
x축으로의 이동 -> 화면 왼쪽 오른쪽 회전(Yaw 축)
y축으로 이동 -> 화면 위쪽 아래쪽 회전(Pitch 축)
으로 사용할 목적임.
y축으로의 이동 값에 대해서는 무한정 위로 돌면 안되므로 clamp를 걸어준다
Yaw에 대해서는 회전 값을 그냥 +해주고 Pitch에 대해서 유니티 좌표계의 차이로 인해
-를 해 주어야만 값이 증가할 때 회전이 시계 방향으로 돌게 됨
b. Camera orbit
마우스의 x 움직임 -> Yaw축 이동,
마우스의 y축 움직임 -> pitch축 이동
으로 하여 Yaw축은 Vector3.up을 회전축으로, 각은 마우스 x축의 변화량에 대한 쿼터니언을,
Pitch축은 Vector3.right을 회전축으로, 각은 마우스 y축의 변화량에 대한 쿼터니언을 생성한다.
축각에 대한 쿼터니언은 AngleAxis로 생성할 수 있음.
target을 기준으로 하여 offset 벡터만큼 떨어져 있는 위치에 대해 회전 쿼터니언을 적용
적용 순서는 pitch를 먼저 곱하고 Yaw를 곱한다.
(유니티에서 회전의 축변환이 roll -> pitch -> yaw 순서임)
c. LookAt target
Target – camera의 Dir로 방향 벡터를 구하고
lookrotation으로 쿼터니언을 생성한다
이를 오브젝트 rotation에 적용한다
혹은 오일러 각을 쿼터니언으로 변환하여 target 방향을 보도록 한다
.
혹은 3인칭은 월드좌표를 기준으로 하여 캐릭터가 빙글 돌아도 카메라는
게속 월드 축을 직교 기저로 하도록 하므로
(local 공간으로 하면 target이 돌때 카메라도 target 회전에 따라 같이 돌게 되므로
이는 FPS와 다르게 원하는 현상이 아니다.)
lookrotation으로 쿼터니언 생성하지 않고 LookAt메서드를 바로 적용해도 무방하다.
TPS Movement
a. wasd binding
inputaction에서 wasd입력을 받기 위해
value, vector2, digital normalize( w(0,1) a(-1,0) s(0,-1) d(1,0)) 에서 동시에 누르는 경우
(1,1) 이런식으로 값이 커지므로 이를 정규화 하여 (0.7, 0.7) 이렇게 자동으로 처리해 준다.
b. target movement
입력값에 따라서 target을 wasd로 움직이도록 함.
여기서는 transform을 직접 움직이는 것보다 CharacterController 컴포넌트를 통해 Move 처리를 해 주는 것이 좋다.
Transform은 단순 위치 기반 움직임이기 때문에 collision이나 중력영향, 경사각 등이 캐릭터에 적용되지 않으므로 사용하기 까다롭다.
캐릭터의 움직임에 대한 부분만을 따로 처리하기 위해서 유니티에서는 CharacterController 컴포넌트를 제공하며 캐릭터의 처리만을 위하 만들어진 독립적인 물리 시스템을 주로 사용한다.
PhysX rigidbody와 별개로 charactercontroller는 충돌 + 이동에 대해서만 적용됨
Rigidbody vs CharacterController
Rigidbody는 물리가 기본적으로 적용되어 있는 상태이고 중력의 영향과 회전, slope등에 대해서 자동으로 계산된다.
CharacterController는 코드에서 직접적으로 처리해 주어야 함
Controller.Move에 대해서 원하는 동작의 방향과 힘 처리를 해 주어야 함
CharacterController는 Collider가 존재하는 물체에 대해서 충돌 검사를 실시함.
이때, charactercontroller에서 하는충돌 검사는 오브젝트에서 아래로 빛을 쏴서 충돌 검출하는 raycast기반이 아닌
Sweep test 기반 narrow-phase임
sweep이라고 하는 것은 오브젝트를 잡고 늘렸을 때의 형샹을 의미함
ex) 사각형을 sweep하면 직육면체가 됨
charactercontroller에서 충돌 검사 시 CharacterController의 Collider를 Sweep했을 때 다른 collider와 겹치는지 등에 대해서 경로를 검사함
c. Camera World Basis Linear Transform
wasd의 입력에 대하여
카메라의 forward, right 방향에 맞게 선형변환 처리하여 오브젝트를 바라보는 카메라의 현재 position에 따른 입력으로 바꾸어 주어야 함
Camera transform의 forward, right 벡터를 입력 받고
각 벡터에 대해서 y축에 대한 입력 값을 0으로 하여 기저 벡터를 출력함
(정확히 말하면 world 공간의 xz 평면으로 projection 하는 것과 동일함)
그 다음 wasd로 입력 받은 input.x input.y에 대하여 카메라 방향에 대한 기저 벡터와 곱하여
오브젝트가 움직일 방향을 결정함
MoveVector = (Input.y * forward + input.x * right) * MoveSpeed;
여기서 forward, right은 3차원 벡터이고, input.y, input.x는 vector2에서 각 성분을 추출한 float 값
d. Running, Sitting
input action에서 키 바인딩을 받을 때
start, performed, canceled, 에 대해서 제대로 알고 있어야 함
키 바인딩에서 중요한 것은 입력 순간의 한 프레임에 대한 event를 다룬다는 것
performed에서는 계속 누르고 있을 때 해당 프레임에 대해서는 true이지만 다음 프레임에서 performed 값은 false가 되어 버림
따라서 performed 값을 직접 bool 변수에 받는 방법 말고 따로 flag를 두어 해당 flag로 현재 상태가 뛰는 상태인지, 앉아있는 상태인지 등을 정의하는 것이 좋다.
Move 함수는 매 프레임마다 업데이트되므로 초기 움직임의 속도를 기본
walkspeed로 설정하고 차례대로
뛰는 state일 때 뛰는 속도로 변경
앉은 상태일 때 앉는 속도로 변경 처리한다.
앉은 상태에서 빠른 걸음으로 하는 경우 등등도 처리하여 총 4가지의 state를 만들 수 있다.
e. Jumping
xz축으로 작용하는 속도와 별개로 중력에 대한 vertical 성분도 따로 벡터에 더해준다
즉
Horizontal + vertical 의 벡터 합으로 표현될 수 있다.
뛰는 키를 누른 시점에 target이 지면에 있는지 판단하는 isGrounded 검사를 동시에 실시한다.
isGrounded 와 버튼이 눌러진 것이 동시에 참이라면 jump 상태 변화를 true로 함
1. 초기 점프 시점에서
올라가야 하는 높이가 h일 때
2as = v^2 – v0^2 에서 최고점에 도달하기 위한 최저점의 순간 속도는
Sqrt(2gh)
2. 낙하 시점에서
v = v0 + at 에서 매 프레임마다 속력이 점점 g*deltatime만큼 감소하는 방향으로 작용
중요한 포인트
a. 회전이동은 movement가 처리 된 다음 LateUpdate에서 처리되도록 한다.
b. 회전이동은 유니티 엔진에서는 z -> x -> y 순서로 처리됨. 따라서 quaternion 생성 후 곱셈시 순서 유의
c. 오일러각을 통해 쿼터니언을 생성하는 것이 직관적이고, 사원수의 곱으로 해서 처리해도 좋다.
단, 회전했을 때 target과 카메라의 방향 벡터가 갱신되도록 업데이트를 계속 해 주어야 함
'Unity Study' 카테고리의 다른 글
| 2025-01-02_Unity Blender Coordinate Difference (0) | 2026.01.03 |
|---|---|
| 2025-12-17_SmoothDamp, Critical Damped Oscillation (1) | 2025.12.17 |
| 2025-12-05_Script Cycle + GC (0) | 2025.12.05 |
| 2025-12-02_Quaternion(3) (0) | 2025.12.02 |
| 2025-12-01_Parent + Child Hierarchy TRS (0) | 2025.12.01 |