위치와 회전, 스케일을 관리하는 컴포넌트 Transform. 어떻게 캐릭터를 움직일지 알아보자
유니티 Transform 메뉴얼
유니티 Transform 스크립트예시


위치, 회전, 크기를 저장하는 컴포넌트4x4 행렬로 구현한다. 대학교에서 배웠었던 사원수 즉, 헤밀턴수가 여기서 나온다.프로퍼티는 씬 창(직접 잡아서 이동 등), 인스펙터 창(직접 값 입력), C# 스크립트(값 지정 또는 수정)에서 바꿀 수 있다.transform은 행렬을 연산해서 구현한다

| x 축 회전 |
|---|
![]() |
| y 축 회전 |
|---|
![]() |
| z 축 회전 |
|---|
![]() |
x,y,z 3축으로 이루어져 있다. Vector3로 간단하게 표현 가능하다Transform.position = new Vector3(x, y, z);
// position을 이용한 이동
transform.position += new Vector3(0, 0, moveSpeed * Time.deltaTime);
// 직접적으로 좌표 값인 x, y, z를 이용한 이동
transform.Translate(0, 0, moveSpeed * Time.deltaTime);옮기다Transform.Translate(Direction * Speed);
// 벡터를 이용한 이동
transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);Transform.position = Vector3.Lerp(StartPosition, EndPosition, Interpolation)deltaTime을 곱할 경우, 1초당 해당 값이 적용된다Transform.position = Vector3.MoveTowards(transform.position, Target.Position, Speed);transform.Translate(0, 0, 1, Space.World);
transform.Translate(0, 0, 1, Space.Self);
transform.Translate(0, 0, 1, otherTransform);
DeltaTime은 0.02가 된다업데이트는 한 프레임마다 수행된다transform.Translate(Vector3.forward * 0.1f);
DeltaTime을 곱해줘야한다transform.Translate(Vector3.forward * 0.1f * Time.deltaTime);
float만큼의 오차가 있음DeltaTime의 값이 갱신되는 방법은 유니티의 라이프 사이클에서 알아볼 수 있음. Update 직전에 갱신됨
public class TankControll : MonoBehaviour
{
[SerializeField] GameObject go;
[Range(0,5)]
[SerializeField] float movePower;
void Update()
{
if(Input.GetKey(KeyCode.Space))
{
go.transform.Translate(transform.forward * movePower * Time.deltaTime);
}
}
}
Space를 누르면, movePower만큼 탱크가 움직인다
사이드얘기
- 그래서 원래 일전에 했던 공굴리기의 경우,
AddForce를 하는 것은 바람직 하지 않음. AddForce의 경우FixedUpdate()에서 쓰는것이 권장된다
오일러 각을 그대로 쓰기에는 짐벌락 현상이 생긴다. 쉽게말하자면, 물체를 돌리다 보면 축이 서로 겹치는 경우가 생긴다.x, y 축이 겹쳤을때, x축 방향으로는 돌릴 방법이 사라지는 경우가 생기는거다쿼터니언(사원수,헤밀턴수)으로 회전을 구현한다. 해당 내용은 대학교에서 수의 체계를 배울 때 있던 내용으로, 관련 내용을 배워보지 못한 학생들은 직관적으로 이해할 수 없다사원수라고 하는데, 여기에 이제 오일러 등식과 함께 사용하면 각도를 표현할 수 있게 된다x, y, z에 각도(방향)을 저장한다. 회전 시 새로운 방향을 연산하여 저장짐벌락 안생김사원수를 이해하기 어렵고 직관적이지 않음짐벌락 현상이 발생함Quaternion을 통해 회전각도를 계산하는 것은 직관적이지 않고 이해하기 어려움
유니티의 경우 Quaternion과 Eular의 변환 함수를 지원하므로 필요에 따라 변환하여 사용
Quaternion quaternion;
Vector3 euler;
quaternion = transform.rotation;
transform의 회전 값은 Euler 각도 표현이 아닌 Quaternion을 사용함euler = quaternion.eulerAngles;quaternion = Quaternion.Euler(euler);rotation에 값을 직접 지정해 회전하는 방법Euler를 이용해 Quaternion을 변환하여 사용 권장Transform.rotation = Quaternion.Euler(x, y, z);
Transform.Rotate(Vector3.up, Speed);// 축을 이용한 회전 (축을 기준으로 시계방향으로 회전)
transform.Rotate(Vector3.up, rotateSpeed * Time.deltaTime);
// 오일러를 이용한 회전
transform.Rotate(Vector3.up * rotateSpeed * Time.deltaTime);
// rotation을 이용한 회전
transform.Rotate(0, rotateSpeed * Time.deltaTime, 0);Transform.RotateAround(Target.position, Vector3.up, Speed);Transform.LookAt(Target.position);Quaternion도 Lerp가 있다Vector3 targetDir = (target.position - transform.position).normalized;
Quaternion targetRot = Quaternion.LookRotation(targetDir);
transform.rotation = Quaternion.Lerp(transform.rotation,targetRot,rate);
월드 스페이스), 상속 관계에서의 상대 좌표(로컬 스페이스)를 사용할 수 있다부모.position = 자식.position월드를 기준으로 좌표와 각도 값을 가지는데, 자식은 부모를 기준(로컬)으로 좌표와 각도 값을 가진다| 부모 |
|---|
![]() |
| 자식 |
|---|
![]() |
transform.Rotate(0, 0, 1, Space.World);transform.Rotate(0, 0, 1, Space.Self);transform.RotateAround(otherTransform.position, Vector3.up, 1);[SerializeField] Transform tank;
[SerializeField] Transform turret;
[SerializeField] float turret;
turret.rotation = Quaternion.identity; // 북쪽, 월드기준이라서 탱크를 회전시켜도 포탑은 고정된다
rotate -= 30*Time.deltaTime;
tank.rotation = Quaternion.Euler(0,rotate,0); // 월드 기준으로 rotate 만큼 회전시킨다
turret.localRotation = Quaternion.Euler(0,rotate,0); // 로컬기준으로 돌아간다. 탱크의 회전 각만큼 값이 더해진다
월드를 기준으로 방향을 정해 이동시키는 방법이다Spalce.World를 생략하면, Space.Self(로컬)로 된다.transform.Translate(Vector3.forward * Time.deltaTime, Space.World);Space.World를 추가하면, 오브젝트의 정수리가 아닌, 월드기준 윗 방향을 축으로 회전한다transform.Rotate(Vector3.up,60,Space.World);트랜스폼은 부모-자식관계 구현 가능위치, 회전, 크기 변경이 같이 적용됨하이라키 창에서 드래그 & 드롭을 통해 부모-자식 상태를 변경할 수 있음// 트랜스폼의 부모 설정
transform.parent = otherTransform.parent;
// 부모를 기준으로한 트랜스폼
Vector3 localPosition = transform.localPosition; // 부모트랜스폼이 있는 경우 부모를 기준으로 한 위치
Quaternion localRotation = transform.localRotation; // 부모트랜스폼이 있는 경우 부모를 기준으로 한 회전
Vector3 localScale = transform.localScale; // 부모트랜스폼이 있는 경우 부모를 기준으로 한 크기
// 트랜스폼의 부모가 null인 경우 월드를 기준
transform.parent = null;
// 월드를 기준으로한 트랜스폼
Vector3 worldPosition = transform.position; // 월드를 기준으로 한 위치
Quaternion worldRotation = transform.rotation; // 월드를 기준으로 한 회전
// Vector3 worldScale = transform.localScale; // 부모를 기준으로 한 크기