Transform Component는 모든 GameObject에 존재하는 기본 컴포넌트로 Object의 위치(Position)
, 회전(Rotation)
, 크기(Scale)
를 결정하는 컴포넌트이다.
Transform Component를 조작함으로 3D 공간의 Object를 어디에 배치하고 움직이고 변형시킬지에 대한 결정을 할 수 있다.
cs코드에서 Transform Component에 접근하는 방법은 매우 간단하다. transform
이라는 변수를 사용하면된다. 또한, Transform Component를 가지고 있는 GameObject에 접근하는 방법은 transform.gameObject
로 접근할 수 있다.
transfrom
과transform.gameObject
으로 접근하는 방법은 굉장히 많이 쓰인다.
transform의 position에 접근하는 방법은 위에서 설명했던 것과 같이 transfrom.position
으로 접근할 수 있다. getter와 setter로 값을 변경하는 것이 아닌 transfrom.position = new Vector3(0.0f, 0.0f, 1.0f);
와 같이 변수처럼 다룰 수 있다.
position 즉, 어떤 Object의 위치를 옮기기 위한 이벤트의 예로 WASD 이동
이 있다. WASD 이동
은 다음과 같은 이벤트의 일종의 Action으로 position을 변경하면서 구현할 수 있다.
1. W를 누르면 앞으로 이동한다.
2. S를 누르면 뒤로 이동한다.
3. A를 누르면 왼쪽으로 이동한다.
4. D를 누르면 오른쪽으로 이동한다.
이벤트가 동작할 조건을 정의했으면 각각의 조건에 맞는 transform을 조작함으로 WASD 이동
을 구현할 수 있다.
if (Input.GetKey(KeyCode.W))
transform.position += new Vector3(0.0f, 0.0f, 1.0f);
if (Input.GetKey(KeyCode.S))
transform.position -= new Vector3(0.0f, 0.0f, 1.0f);
if (Input.GetKey(KeyCode.A))
transform.position -= new Vector3(1.0f, 0.0f, 0.0f);
if (Input.GetKey(KeyCode.D))
transform.position += new Vector3(1.0f, 0.0f, 0.0f);
움직이는 것을 보면 잠깐만 눌렀음에도 너무 빠르게 움직인다. 속도 조절할 방법이 필요하다.
WASD 이동
을 구현할 때의 코드를 보면 Update()안에 각각의 키를 눌렀을 때 position에 특정 벡터만큼 더하거나 빼줌으로 구현한 것을 알 수 있다.
void Update(){
if (Input.GetKey(KeyCode.W))
transform.position += new Vector3(0.0f, 0.0f, 1.0f);
if (Input.GetKey(KeyCode.S))
transform.position -= new Vector3(0.0f, 0.0f, 1.0f);
if (Input.GetKey(KeyCode.A))
transform.position -= new Vector3(1.0f, 0.0f, 0.0f);
if (Input.GetKey(KeyCode.D))
transform.position += new Vector3(1.0f, 0.0f, 0.0f);
}
그렇다는 것은 각 프레임마다 Update가 실행된다는 것이고 만약 10프레임(60fps기준 1/6초)동안 W를 누르고 있다면 총 10.0f만큼 앞으로 이동할 것이다.
이전 프레임과 현재 프레임 사이의 시간을 나타내는 Time.deltaTime을 사용하자
Time.deltaTime
은 뜻 그대로 이전 프레임과 현재 프레임 사이의 시간을 반환하는 변수로 하드웨어 환경마다 프레임 속도가 다를 수 있기 때문에 사용한다. Time.deltaTime
을 사용함으로 프레임 속도에 관계 없이 일관된 게임로직을 제공할 수 있다.
if (Input.GetKey(KeyCode.W))
transform.position += new Vector3(0.0f, 0.0f, 1.0f) * Time.deltaTime;
생각해보면 Time.deltaTime
은 다양한 fps환경에서의 일반화를 시켜준 것이지 속도조절
에 관련된 직접적인 기능은 아니다.
속도 조절을 위한 방법으로 가장 간단한 방법은
speed
라는 상수를 하나 정의하는 것이다.
속도를 높이거나 줄이고 싶을 때 speed를 변경하면 된다.
float _speed = 10.0f;
if (Input.GetKey(KeyCode.W))
transform.position += Vector3.forward * Time.deltaTime * _speed;
하드웨어 환경적인 요소를 Time.deltaTIme
으로, 속도의 크기 조절은 speed
라는 상수를 통해 다양한 환경에서의 일정한 속도를 보장
할 수 있다.
Rotate는 Transform Component에서 Object의 회전을 나타내는 요소로 x,y,z 축에 대한 회전한 각도를 나타낸다. Rotate의 접근 방법은 transfrom.rotate
변수로 직접 수정이 가능하다.
회전하는 각도는 각도를 나타내기 때문에 음수와 양수로 나타낼 수 있고 절대값이 같으면 방향만 반대인 Vector라고 생각하면 된다.
방향이 헷갈린다면
플레밍의 왼손법칙
을 생각하자
엄지를 회전하고자 하는 축으로 생각하고 왼손으로 감싸는 방향이+
이다.
Position에서 구현한 WASD 이동
을 Rotate된 상태에서 적용하면 놀랍게도 캐릭터가 바라보는 방향이 아닌 다른 방향으로 움직인다. 이러한 상황이 발생한 이유는 좌표계의 차이
로 인해 발생하는데 일반적인 물리학에서 다루는 그 좌표계로 생각하면 된다.
'어떻게 지평좌표계로 고정을 하셨죠?'라는 말이 떠오른다면 정답이다!
앞선 단계에서 WASD 이동
의 Action은 다음과 같이 정의했다.
1. W를 누르면 앞으로 이동한다.
2. S를 누르면 뒤로 이동한다.
3. A를 누르면 왼쪽으로 이동한다.
4. D를 누르면 오른쪽으로 이동한다.
이동하는 방향을 보면 앞
,뒤
,왼쪽
,오른쪽
으로 되어 있을 뿐 무엇을 기준으로 앞
,뒤
,왼쪽
,오른쪽
정해주질 않았다.
Unity는 따로 지정해주지 않으면 World좌표계를 기준으로 계산한다.
즉,W를 누르면 앞으로 이동한다.
는W를 누르면 (절대 좌표 기준)앞으로 이동한다.
로 행동한다.
만들고자 하는 것은캐릭터가 바라보는 방향
을 기준으로 하는 이동이다.
Unity에는 이를 위해 transform.TranformDirection
이라는 함수를 제공한다.
transform.TranformDirection
은 Local좌표를 World좌표로 좌표계산을 해준다.transform.TranformDirection
은 회전에 대한 계산을 한다. 즉, 스칼라값에 영향을 미치지 않는다.위 내용을 반영한 WASD 이동
의 구현은 다음과 같이 바꿀 수 있다.
if (Input.GetKey(KeyCode.W))
transform.position += transform.TransformDirection(Vector3.forward * Time.deltaTime * _speed);
if (Input.GetKey(KeyCode.S))
transform.position -= transform.TransformDirection(Vector3.back * Time.deltaTime * _speed);
if (Input.GetKey(KeyCode.A))
transform.position -= transform.TransformDirection(Vector3.left * Time.deltaTime * _speed);
if (Input.GetKey(KeyCode.D))
transform.position += transform.TransformDirection(Vector3.right * Time.deltaTime * _speed);
Vector3.forward
는 Unity에서 제공하는 예약어로 Vector3(0.0f, 0.0f, 1.0f)
와 같다.
Local -> World는
transform.TranformDirection
을 사용하고
World -> Local은transform.InverseTranformDirection
을 사용하면 된다.
World좌표계와 Local좌표계의 계산이 너무 복잡하다면 transform.Translate()
라는 함수를 사용하면 된다.
transform.Translate()
는 방향과 크기(벡터)를 입력하면 '바라보는 방향'을 기준으로 이동을 하기 때문에 좌표계를 신경쓰지 않아도 된다.Scale은 Transform Component에서 Object의 크기를 나타내는 요소로 Vector3 형식으로 x,y,z축에 대한 상대적인 크기값을 나타낸다.
기본 값은 x,y,z=(1,1,1)
이지만 (0.5,0.5,0.5)
로 하면 크기가 절반, (2,2,2)
로하면 크기가 2배가 되는 것이다.