2. 게임 구현과 현실은 차이가 있다
• 진짜 리얼한 물리엔진을 만드는 게 아님
• 시뮬레이션을 만드는 것도 아님
• 조작하는 ‘손 맛’이 제일 중요
• 테스트 해 보고 아니다 싶으면 비현실적인 해법으로 갈 수도 있
음
3. 속도와 가속도
• 3차원이므로 벡터량인 속도와 가속도는 x, y, z 축으로 각각 분
배된다
• 예를 들어 속도가 100km/s 일 때 x, y, z 축과 이루는 각도가 X,
Y, Z 라면
X축 방향 속도 : 100 * cos(X)
Y축 방향 속도 : 100 * cos(Y)
Z축 방향 속도 : 100 * cos(Z)
(단위 km/s)
가 되는 것이다
4. 속도와 가속도
• 앞과는 반대로, velocity(x, y, z) 값이 주어지면 이 값을 토대로
캐릭터의 속도를 구할 수 있다.
• 사실 구할 필요 없다.
• 다음 draw() 할 때 dt 만큼 각각의 속도에 곱해서 나온 값만큼 전역 좌
표계에서 이동시켜버리면 그만이다.
• Position(x, y, z) 에서 position.x = position.x + velocity.x * dt
• 나머지도 동일
• 속도가 있을 때 캐릭터 이동은 저렇게 하면 된다
• 속도가 변할 때는 어떻게 할까?
5. 속도와 가속도
• 게임을 생각해보면 속도가 점점 늘거나 줄어야 된다
• 일반 이동이 키 하나에 0에서 100으로 가속하는 방식이면 안 된다
• 그럼 가속도가 있어야 한다
• 가속도도 속도와 마찬가지로 세 축 성분의 합으로 나타낸다
6. 속도와 가속도
• Accel(x, y, z) 라는 가속도 항목을 두고
• Speed(x, y, z) 라는 속도 항목을 둔 다음
• dt 만큼 지났을 때 Speed(x, y, z)는?
• Speed.x = Speed.x + Accel.x * dt
• 나머지 항도 똑같음
• 자 이제 가속도가 있을 때 속도를 구해서 캐릭터 이동까지 가능
하다!
• 그런데 가속도가 변하면??
7. 속도와 가속도
• 만약 가속도가 10m/s2 일 때 가만 두면 속도가 영원히 증가한다
• 해결해야죠
• 가속도가 점점 줄어들게 만들어야 한다
• 아니면 가속도가 순간적으로 작동하고 사라지게 한다
• 등가속도 운동만 고려해도 상관이 없다
• 가속도가 바뀌면 update() 할 때 바꿔주고 등가속도로 계산하는 과정을
짧은 시간 동안 반복하면 가속도가 변하는 운동을 나타낼 수 있다.
• 구현이 간단하다.
그냥 이렇게 계산하자는 이야기
* 실제로는 훨씬 정확함
8. 속도와 가속도
• 속도 제한과 가속도 제한을 도입해야 한다.
• 추가로, 키 입력이 없을 때 가속도는 일정한 값을 가진다
If( 속도 > 0 || 속도 0 < )
가속도 = -a; (a는 속도의 부호와 같은 부호를 가짐)
Else // 속도 == 0
가속도 = 0;
• 그래야 속도가 줄어든다.
• 시간이 지날 수록 현재 속도에서 반대 방향 가속도만큼 빠지기 때문
9. 속도와 가속도
• 키 입력이 있으면 해당 방향으로 가속도를 덮어쓴다
• 이건 테스트를 좀 해봐야 하는데.. 기존의 가속도를 덮어쓰는 게 조작감
이 좋을 것 같긴 함
• 기존 속도는 살려두는 편이 현실감 있는 조작
• 정리하면 “속도는 살리고, 가속도는 죽인다”
10. 게임이라면?
int speed[3] = { 0, };
int accel[3] = { 0, };
1 2
유저가 어떤 방향(x, y, z)으로 가속
가속도 a를 세 방향으로 나눔3
4 가속도를 가지고 속도를 고침
accel[3] = { 3, 4, 5 };
accel[3] = { 3, 4, 5 };
float dt = 0.1;
speed[3] = { 0.3, 0.4, 0.5 };
5
speed[3] = { 0.3, 0.4, 0.5 };
속도를 가지고 위치를 고침
position[3] = { 0.03, 0.04, 0.05 };
11. 추가로 있어야 할 것
• 연료를 소비해서 속도를 0으로 맞추는 기능이 있어야 함
• 안 그러면 조작하기가 너무 힘들다
• 코딩으로 구현하기는 쉬움
• 가속도 반영 방식을 생각해봐야 한다
• Update() 함수가 불려 올 때 주기적으로 계산해주는 방법이 좋을지 아
니면 충돌이나 운동 즉시 속도에 반영하고 이후의 운동을 등속도운동
의 합으로 간주하는 것이 좋을지 결정
13. 위 모델은 병진 운동만 있을 경우
• 회전이 함께 있을 경우 에너지가 분산된다.
• 엄밀히 생각하면 충돌이 있을 때 물체의 질량 중심과 관성 모멘
트를 구해서 병진 운동과 회전 운동에 분배해줘야 한다.
• 만들기 어렵다
• 그렇다면 미리 물체의 중심과 회전축을 결정해두고 충돌이 있
을 때 벡터만 가지고 판정을 하자!
14. 아마 이렇게 되겠지
• 문제를 단순화 해서 2차원 물체의 질량 중심을 지나는 축과 동
일한 선 상에서 타격이 있다면
• 병진 운동 100% 회전 운동 0%
• 빗겨나서 충돌하면 병진과 회전이 동시에 발생
이때 충돌한 물체의 운동량은
(충돌지점 – 질량중심) 벡터와
(충돌지점 – 질량중심) 벡터에 수직인 벡터로 분할된다
전자는 병진운동, 후자는 회전운동에 영향을 준다
양쪽 벡터에 운동량의 정사영을 투사해 크기를 구할 수 있다
15. 3차원에서는?
• 축을 하나 더 늘리면 된다
• 회전축은 질량중심을 지나면서 충돌 벡터와 직교함
• 외적한 값이 (질량중심-충돌벡터)벡터가 되는 두 벡터가 회전을
결정하는 벡터
16. 여기서 잠깐 : 짐벌락
• 3D 물체를 회전시킬 때 중대한 문제가 있는데 Gimbal Lock 이
다.
• 물체를 회전 변환 시킬 때 같은 각도만큼 회전시켜도 적용하는 순서를
바꾸면 결과가 달라지는 현상이 생긴다.
• 이는 물체에서 한 축을 움직일 때 나머지 축도 영향을 받는다는 것이다
• 따라서 물체를 회전시키는 도중에 축이 겹쳐지는 경우가 생긴다.
• 이때 축의 자유도를 잃을 수 있는데 이것이 짐벌락이다.
• 짐벌락에 빠지게 되면 pitch, yaw, roll 중 일부가 불가능하게 된다.
17. 쿼터니언?
• 실수부와 허수부로 구성된 4원수
• 회전 변환에 매우 유용
• 짐벌락이 발생하지 않는다
• 회전 행렬 계산보다 더 적은 원소를 사용한다
• 하지만 수식이 직관적이지 않고 이동을 나타내기 어렵다
• Graphics Advanced에서 다룬다고 하니 필요하면 추가 스터디
18. 회전운동은 구현하기가 빡셈
• 병진운동까지는 유니티로 실험 가능
• 기본적인 속도와 가속도 개념을 바탕으로 우주에서만 가능한 독특한
이동방식을 만들었음
• freelancer 2에서 우주선 조작하는 느낌과 비슷함
19. 현재까지 문제점
• 프로토타이핑으로 조작감을 시험해보기가 쉽지 않다.
• Unity가 알아서 다 해버림
• Direct 3D로 만들려니 기반작업이 많이 필요
• 운동에 관한 모델링이 깔끔하지 않다
• 기본적인 물리를 머리에 넣고 실제 구현된 예제를 통해 보강해 나가야
• 남의 코드를 열심히 보자