티스토리 뷰
벡터(vector), 스칼라(scala), 속도(velocity), 속력(speed) 그리고 오일러(euler), 사원수(quaternion)
progrunman 2022. 10. 14. 22:09수학, 물리랑 관계없이 살다가 게임개발에 발을 들여놓으니 모든것이 수학이요 물리다.
그동안 속력과 속도의 차이에 대해 생각없이 살았는데 개념상 차이가 있어 간단하게 정리를 한다.
vector와 scala
- vector(벡터) : 크기와 방향이 있는 물리량(e.g. 속도(velocity), 가속도, 힘, 중력장 등)
- scala(스칼라) : 크기만 있고 방향이 없는 물리량(e.g. 속력(speed), 시간, 부피, 질량 등)
Unity에서도 physics를 사용하면 `Rigidbody.AddForce`같이 힘을 가할때 vector를 인자로 받는다. 그리고 가중치값은 `float`과 같은 타입으로 정의한 scala를 사용한다. vector에 scala(가중치)를 곱하거나 나눠서 방향에 영향을 주지 않고 해당 벡터 크기를 변환한다.
또한 모든 GameObject들은 Transform컴포넌트를 가지며, `Transform.position`은 3D world space의 vector값이다. 다시말하면 모든 게임객체들은 월드좌표계에서 위치와 방향을 가진다는 소리이다. 예를들어 target오브젝트에서 player오브젝트의 position vector를 빼면 해당값은 player오브젝트에서 target오브젝트를 가리키는 vector값이 된다. 해당 vector값을 normalized시키면 방향을 알 수 있어 경로추적이나 투사체를 발사 등의 행위에 활용할 수 있다.
velocity(속도)와 speed(속력)
- velocity(속도) : 단위시간당 이동한 변위. 벡터. (변위 : 시작점부터 도착점까지의 직선거리. 즉, 벡터)
- speed(속력) : 단위시간당 이동한 거리. 스칼라. (거리 : 총 길이. 즉, 스칼라)
15km 자동차 경주를 예로들면
A자동차 : 속력 30km/h, 닌자처럼 지그재그로 달림
B자동차 : 속력 15km/h, 목표지점까지 직선으로 달림
A, B가 도착점에 1시간만에 동시에 도착했다면 자동차 속력(speed)은 다르지만, 경주 클리어 속도(velocity)는 둘다 15km/h로 동일하다고 표현 할 수 있다.
euler와 quaternion
- euler angle(오일러각) : x, y, z로 정의하는 3개의 축을 기준으로 회전을 정의 (흔히쓰는 360도)
- quaternion(사원수) : x, y, z 및 w로 정의되는 3차원 공간의 방향 및 회전에 대한 수학적 정의 (복소수 사용)
유튜브에서 회전축 빙글빙글 도는거 보다보니 내 머리도 도는것 같기에 Unity에서 만들어놓은 Quaternion API라도 훑어보기로 한다.
Unity의 Transform컴포넌트에서는 직관적이도록 euler angle로 표시되지만 gimbal-lock같은 문제를 회피하고 더 복잡한 회전을 계산하기 위해 내부적으로는 quaternion으로 저장되고 계산된다. 스크립트에서는 Quaternion클래스를 사용해 GameObject의 3차원 방향을 저장하고, 이를 통해 한 방향에서 다른 방향으로의 상대회전을 설명할 수 있다. 오일러각을 전혀 사용하지 않고도 회전을 만들고 조정 가능하며, 대부분의 일반적인 경우 Quaternion클래스의 함수를 사용하도록 권장하고 있다. 참고로 Unity에서 euler angle 회전은 z축, x축, y축 순서로 개별회전을 순차적으로 수행한다.
(gimbal-lock : 3차원 회전(3개의축)이 가능한 object의 2개 회전축이 겹쳐서(locked) 2차원 회전만 되는 이슈)
Unity에서 주로 사용되는 Quaternion함수는 아래와 같다.
- Quaternion.LookRotation : 지정된 정방향 및 위쪽 방향으로 회전하는 Quaternion 객체 반환
- Quaternion.Angle : Quaternion a와 b 사이의 각도 반환
- Quaternion.Euler : 오일러각 x, y, z 값을 인자로 받아 z > x > y 순서로 계산된 Quaternion 객체 반환 (Quaternion.eulerAngles는 반대 변환)
- Quaternion.Slerp : Quaternion a와 b 사이를 비율t로 spherically하게 보간 (t는 [0, 1] 범위)
- Quaternion.FromToRotation : fromDirection에서 toDirection으로 회전하는 Quaternion 객체 반환
- Quaternion.identity (Readonly) : world 또는 부모 중심축에 일치하는 회전이 없는 Quaternion을 반환. 즉 자신이 root면 world좌표 기준으로 회전 초기화되고, 자식이면 부모기준으로 회전 초기화
간단한 회전을 위해 아래와 같은 방법들을 사용 가능하다.
- Transform.Rotate(x, y, z)
- 현재개체 회전에 x, y, z 오일러각만큼 회전추가.
- world/local좌표계 기준설정 등 몇가지 오버로드된 함수들이 있어 필요에 따라 사용
- 보통 일반적인 회전은 이걸 사용하면 된다
- Transform.RotateAround(타겟position, 회전할중심축axis, 오일러angle값)
- 특정 포인트를 중심으로 회전시킬때 사용 (e.g. 플레이어 주변을 빙글빙글 도는 카메라)
- Transform.eulerAngles = new Vector3(x, y, z)
- x, y, z 오일러각만큼 회전 설정
- Transform.rotation = Quaternion.Euler(x, y, z)
- x, y, z 오일러각만큼 회전 설정
- Quaternion에 다양한 함수들이 있으니 좀 더 고급설정을 하고싶은 경우 사용
성능은 거의 동일하다고 하며 `Transform.rotation`보다 `Transform.eulerAngles`가 미세하게 빠르다고 하는데 별의미 없는듯하여 패스하기로 한다.
=> 직접 코드를 확인해보니 인터넷에 떠돌던 글이 옛날글인지 잘못된 테스트였는지 신빙성이 없었다. `Transform.Rotate()`함수나 `Transform.eulerAngles`프로퍼티에서 어차피 `Quaternion`으로 변환을 수행해서 `Transform.rotation`에 get/set 하고 있기 때문에 C# 컴파일 단계에 최적화된 거의 동일한 산출물이 나오지 않을까 예상되며, 굳이 따지자면 `Transform.rotation`이 가장 직접적으로 UnityEngine 네이티브 코드를 호출하며 나머지는 편의성을 위한 wrapper다.
결론
Unity에서는 Physics 계산을 위해 가상좌표공간을 따로 만들어 동기화를 시킨다고 한다.
때문에 프로젝트 이동처리에 Physics를 사용할건지 안할건지에 따라 Transform 직접사용에 주의할 필요가 있다.
Physics를 사용할경우 Rigidbody의 `AddForce()`, `AddTorque`를 사용해 이동과 회전처리를 하고 상황에 맞게 kinematic rigidbody의 경우 `MovePosition()`을 사용해 이동처리를 해야 좌표관련 불필요한 처리가 없다. 물리영향을 받고싶지 않은 캐릭터 이동은 CharacterController를 이용할수도 있다.
만약 Physics를 사용하지 않기로 결정했다면 Project Settings에서 'Auto Simulation', 'Auto Sync Transforms'를 끄고 `Transform.Translate()`, `Transform.Rotate()` 등을 사용하여 이동 및 회전처리를 최적화하여 구현할 수 있다.
References
"Life is not speed but direction" - 괴테
인생은 속력이 아니라 방향이다.
https://docs.unity3d.com/kr/current/Manual/ScriptingImportantClasses.html
https://docs.unity3d.com/kr/current/Manual/VectorCookbook.html
https://docs.unity3d.com/kr/current/Manual/class-Quaternion.html
https://docs.unity3d.com/kr/current/Manual/QuaternionAndEulerRotationsInUnity.html
https://answers.unity.com/questions/1074673/what-is-more-efficient-new-vector-3-vs-quaternione.html
'Game > Fundamental' 카테고리의 다른 글
[직렬화] Unity Serialization (0) | 2023.02.15 |
---|
- Total
- Today
- Yesterday
- selenium
- await
- firestore
- framework
- async
- 환경설정
- 싱글톤
- logging
- Python
- 코루틴
- .net
- Singleton
- coroutine
- Custom Package
- gcp
- initialize
- Visual Studio Code
- Debug
- git
- VS2022
- C#
- 닷넷
- github
- RuntimeInitializeOnLoadMethod
- Addressables
- vscode
- 비동기
- 유니티
- unity
- Scraping
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |