[Unity] Transform

이정석·2023년 6월 25일
0

Unity

목록 보기
1/22

Transform

Transform Component는 모든 GameObject에 존재하는 기본 컴포넌트로 Object의 위치(Position), 회전(Rotation), 크기(Scale)를 결정하는 컴포넌트이다.

Transform Component를 조작함으로 3D 공간의 Object를 어디에 배치하고 움직이고 변형시킬지에 대한 결정을 할 수 있다.

C#코드에서의 접근방법

cs코드에서 Transform Component에 접근하는 방법은 매우 간단하다. transform이라는 변수를 사용하면된다. 또한, Transform Component를 가지고 있는 GameObject에 접근하는 방법은 transform.gameObject로 접근할 수 있다.

transfromtransform.gameObject으로 접근하는 방법은 굉장히 많이 쓰인다.


Position

transform의 position에 접근하는 방법은 위에서 설명했던 것과 같이 transfrom.position으로 접근할 수 있다. getter와 setter로 값을 변경하는 것이 아닌 transfrom.position = new Vector3(0.0f, 0.0f, 1.0f);와 같이 변수처럼 다룰 수 있다.

1. 플레이어 이동

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);

PlayerController

움직이는 것을 보면 잠깐만 눌렀음에도 너무 빠르게 움직인다. 속도 조절할 방법이 필요하다.

2. 이동속도 조절

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

Rotate는 Transform Component에서 Object의 회전을 나타내는 요소로 x,y,z 축에 대한 회전한 각도를 나타낸다. Rotate의 접근 방법은 transfrom.rotate 변수로 직접 수정이 가능하다.

회전하는 각도는 각도를 나타내기 때문에 음수와 양수로 나타낼 수 있고 절대값이 같으면 방향만 반대인 Vector라고 생각하면 된다.

방향이 헷갈린다면 플레밍의 왼손법칙을 생각하자
엄지를 회전하고자 하는 축으로 생각하고 왼손으로 감싸는 방향이 +이다.

1. World좌표 Local좌표

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을 사용하면 된다.

2. Translate

World좌표계와 Local좌표계의 계산이 너무 복잡하다면 transform.Translate()라는 함수를 사용하면 된다.

  • transform.Translate()는 방향과 크기(벡터)를 입력하면 '바라보는 방향'을 기준으로 이동을 하기 때문에 좌표계를 신경쓰지 않아도 된다.

Scale

Scale은 Transform Component에서 Object의 크기를 나타내는 요소로 Vector3 형식으로 x,y,z축에 대한 상대적인 크기값을 나타낸다.

기본 값은 x,y,z=(1,1,1)이지만 (0.5,0.5,0.5)로 하면 크기가 절반, (2,2,2)로하면 크기가 2배가 되는 것이다.

  • 그래픽 모델을 만들 때 특정 상황에 맞는 크기에 맞춰서 만들 필요는 없다.
  • Background에 넣을 커다란 Object(ex. 성)를 만들 때 상대적으로 작게 만든 후 Scale을 키워줌으로 큰 Object를 구현한다.
profile
게임 개발자가 되고 싶은 한 소?년

0개의 댓글