게임 오브젝트 이동

Woogie_·2024년 6월 18일

Unity

목록 보기
3/20

Transform 컴포넌트를 이용한 오브젝트 이동

  • 카메라의 위치는 원점 (0, 0, 0)에 있는 오브젝트를 바라보는 것을 기준으로 설정하는 것이 일반적

  • 일반적으로 게임에 배치하는 오브젝트를 원점 기준으로 배치하기 때문에 카메라는 이 오브젝트들을 촬영할 수 있도록 뒤로 10만큼 떨어진 위치인 (0, 0, -10)에 그대로 두고 사용한다.

  • Camera 컴포넌트의 Clear Flags는 2D 게임 개발에서 Solid Color 를 많이 사용하고, Background 값을 바꿔 배경 색상을 설정한다.

  • Projection이 Orthographic 이면 직교 투영을 하는 2D 카메라로 설정되고, Size 값을 바꿔 시야 범위를 설정한다.

  • 플레이어로 사용할 2D Capsule 오브젝트를 생성하고 이름을 Player 로 변경 [GameObject - 2D Object - Sprites - Capsule]

  • 게임 오브젝트의 위치를 제어하는 컴포넌트는 Transform 컴포넌트
  • Transform 컴포넌트에 있는 position 정보를 수정하면 오브젝트 위치가 변경된다

  • 실제 게임을 진행할 때는 Unity Editor 나 Inspector View와 같은 화면을 볼 수 없기 때문에 코드를 이용해 Transform 컴포넌트의 position 정보를 수정해야 한다.

  • 유니티에서는 각각의 게임 오브젝트에 소속된 컴포넌트에 접근할 수 있으며, 컴포넌트 내부의 클래스에 있는 변수 데이터를 사용하거나 수정하고 사용자가 만든 메소드를 호출할 수 있다.

  • Transform 컴포넌트에 접근해 오브젝트의 이동을 제어하는 Movement2D 스크립트 생성 [Project View - "+" - C# Script]

  • 코드에 필요 없는 using문과 클래스 내부 코드 삭제

  • 게임이 실행된 직후 1회 호출되는 Awake() 메소드를 정의

  • 소문자 transform은 이 스크립트를 컴포넌트로 가지고 있는 게임 오브젝트의 Transform 컴포넌트를 나타낸다.
  • Transform 컴포넌트는 Inspector View에 보이는 Position, Rotation, Scale 변수에 접근해 "transform.position"과 같이 값을 열람하거나 "transform.position =" 과 같이 값을 수정할 수 있다.
  • 즉, 이 코드에서 대입 연산자 (=)를 기준으로 왼쪽 transform.position은 값을 설정하는 것이고, 오른쪽 transform.position은 현재 값을 열람하는 것
  • 값을 열람하는 부분을 현재 값으로 바꿔보면 "transform.position = (0, 0, 0) + (1, 0, 0) * 1;"과 같다.
  • 이 코드를 1번 실행하면 transform.position = (1, 0, 0)이 된다.

Vector3 구조체

  • 게임의 2D/3D 공간에서 이동, 회전, 크기를 표현하기 위해 (x, y) 또는 (x, y, z)의 좌표 체계를 나타내는 단위로 유니티에서 제작한 구조체 (struct)

  • 2차원, 3차원, 정수, 실수에 따라 Vector2, Vector3, Vector2Int, Vector3Int와 같이 구조체가 정의되어 있다.

  • Vector3 구조체를 기준으로 살펴볼 때 3차원의 x, y, z를 표현하기 위해 구조체 내부에 3개의 실수 float x, float y, float z가 선언되어 있다

  • 1 단위 방향, 두 점 사이의 거리, 각도 등의 연산을 위한 프로퍼티, 메소드 제공 (new Vector3(1, 0, 0)과 Vector3.right는 같다)

  • 일반적으로 방향은 -1.0 ~ 1.0 사이의 값으로 표현 (방향에 힘이 포함되지 않도록)

  • 방향을 new Vector3(1, 0, 0) 대신 Vector3.righr와 같이 방향 프로퍼티로 변경

  • 작성이 완료된 Movement2D 스크립트를 Player 오브젝트의 컴포넌트로 등록

  • Toolbar에 있는 플레이 버튼(▶)을 눌러 게임을 실행하면 Awake() 메소드는 게임을 실행 했을 때 최초 1회 호출되기 때문에 게임 실행 전에 (0, 0, 0)이었던 Player의 위치는 오른쪽으로 1만큼 이동한 (1, 0, 0)이 된다.

  • Movement2D 스크립트에서 Awake() 메소드는 씬이 실행되고 최초 1회만 호출되기 때문에 지속적으로 이동 코드가 실행되도록 메소드를 Update() 로 변경

  • Update() 메소드는 프레임에 따라 1초에 몇 번 호출할지 결정되는데 한 컴퓨터에서도 프레임이 계속 변하고, 사양이 다른 컴퓨터는 프레임이 다를 수 있기 때문에 이동 / 회전 / 크기 변화와 같은 연산을 일정하게 수행하기 위해 Time.deltaTime 값을 곱해준다.

Time.deltaTime

  • 서로 다른 두 컴퓨터에서 캐릭터를 이동할 떄

    • 캐릭터의 Update() 1회 당 이동거리를 5 m 라고 가정할 떄
    • A 컴퓨터는 60초에 update()가 60회 호출
    • B 컴퓨터는 60초에 update()가 120회 호출
  • 60초 후에 A 컴퓨터는 5 m 60회 = 300 m를 이동하게 되고, B 컴퓨터는 5 m 120회 = 600 m를 이동하게 된다

  • 즉, 컴퓨터 사양이 더 좋아 FPS가 높은 컴퓨터의 캐릭터가 더 많이 움직이게 된다.

  • 이런 문제를 해결하고, 두 컴퓨터의 캐릭터가 같은 시간동안 같은 거리를 이동하도록 해주는 것이 Time.deltaTime

Time.deltaTime 이란?

  • 이전 Update() 종료부터 다음 Update() 시간까지의 시간 즉, 업데이트 사이의 시간 (ex) 1분 (60초)에 Update()가 60번 호출된다면 Time.deltaTime은 1)

  • A 컴퓨터는 60초에 Update()가 60번 호출

    • Time.deltaTime의 값은 1
  • B 컴퓨터는 60초에 Update()가 120번 호출

    • Time.deltaTime의 값은 0,5
  • FPS (Frames per second) 60 일 때 초당 60회 호출

이동거리 = 방향 (Direction) * 속도(Speed) * Time.deltaTime

A 컴퓨터 5 m * 60회 * 1 = 300 m
B 컴퓨터 5 m * 120회 * 0.5 = 300 m
  • 화면에 이동을 출력하는 횟수는 차이가 나겠지만 A, B 컴퓨터의 캐릭터가 동일하게 300 m를 이동
  • 컴퓨터의 사양이 더 좋은 B 컴퓨터에서 캐릭터가 이동하는 모습을 더 많이 출력하기 때문에 시각적으로는 A컴퓨터보다 더 부드럽게 이동하겠지만 결과적으로 이동 거리는 300 m로 같다.
  • 또한 Update() 메소드에 작성한 이동 코드에 Time.deltaTime을 곱하면 방향 * 속도 값이 1초에 이동하는 거리

  • 게임을 실행하면 플레이어가 오른쪽 방향으로 계속 이동한다

Input 클래스를 이용한 이동 방향 제어

  • Movement2D 스크립트로 가서 클래스 내부 또는 외부에서 접근해 데이터를 쉽게 수정 또는 열람할 수 있도록 이동속도와 이동방향 변수를 선언

  • moveSpeed와 같이 변수 선언과 동시에 값을 초기화할 수도 있고, Awake() 메소드처럼 초기화를 위해 1회만 호출되는 메소드에서 값을 할당할 수도 있다

  • 변수를 사용하고 매직 넘버 (3, 5.2와 같이 특정 값) 사용을 지양해야 하는 이유는 한 예로 이동속도를 코드 내부에서 숫자 3으로 표현했는데 이동속도를 사용하는 코드가 100 줄이면? 이동속도를 3에서 5로 수정해야할 경우 100줄의 코드에 있는 3을 5로 수정해야 한다.

  • 이동방향과 이동 속도를 변수로 선언했기 때문에 이동 방향을 Vector3.right 대신 moveDirection 변수로 이동 속도를 1 대신 moveSpeed 변수 코드로 수정

방향키 입력

  • 유니티는 입력과 관련된 모든 프로퍼티, 메소드가 정의되어 있는 Input 클래스를 제공하는데 실습에서는 특정 키 입력 여부에 따라 boot 값을 반환하는 GetKey() 메소드를 사용

  • Update() 메소드가 실행될 때마다 제일 먼저 이동방향 moveDirection을 (0, 0, 0)으로 초기화해 키 입력이 없을 때는 오브젝트가 제자리에 멈춰있도록 설정

  • if (Input.GetKey(KeyCode.UpArrow) )와 같이 조건을 작성하면 위쪽 방향키를 눌렀을 때 조건문 내부가 실행

  • 조건문 내부는 moveDirection += Vector3.up; 과 같이 작성해 이동 방향을 (0, 1, 0) 즉, y축 방향으로 이동하도록 설정

  • moveDirection += Vector3.right; 와 moveDirection = Vector3.right; 의 차이점 : = 으로 설정했을 경우 : 마지막에 누른 키 값 선택 (4방향 이동) / += 으로 설정 했을 경우 : 누른 키 값이 중첩 (8방향 이동)

  • if와 else if는 한 쌍으로 위 or 아래, 왼쪽 or 오른쪽 중 한 방향으로만 이동이 되기 때문에 묶어서 사용했다.

  • Input 클래스는 PC 키보드, 마우스, 모바일 터치, 가속도 센서, 자이로 센서 등의 입력 메소드, 마우스 좌표와 같은 각종 프로퍼티 정보를 제공

  • 게임을 실행했을 때 상하좌우 방향키에 따라 플레이어가 이동

Input.GetAxis(), Input.GetAxisRaw() 메소드

  • Edit - Project Settings - Input 메뉴에 등록된 단축키를 입력에 이용할 때 사용한다 단축키 하나에 부적정(-) 2개, 긍정적 (+) 2개 값으로 총 4개의 키를 등록할 수 있다.

-GetKey() 메소드를 이용한 이동을 GetAxisRaw() 메소드로 이동으로 수정

  • Input.GetAxisRaw("Horizontal") 단축키는 'a', 'd', ←, → 키가 저장되어 있어 'a' or 왼쪽 방향키 (←)를 누르면 -1, 'd' or 오른쪽 방향키 (→)를 누르면 1 값이 반환된다.

  • Input.GetAxisRaw("Horizontal") 단축키는 'w', 's', ↑, ↓ 키가 저장되어 있어 's' or 아래 방향키 (↓)를 누르면 -1, 'w' or 위쪽 방향키 (↑)를 누르면 1 값이 반환된다.

  • 4개 키 중 어느 값을 누르지 않으면 0이 반환된다

  • 게임을 실행 해보면 이전과 동일하게 방향키로 이동할 수 있고, WASD 키로 이동할 수 있다.
profile
상상을 구현하는 개발자

0개의 댓글