유니티2D 입문 정리 3 - 입력과 캐릭터 이동

woollim·2024년 10월 7일
0

1. 유니티 스크립트 작성법

○ 유니티 스크립트 작성

  1. 프로젝트가 생성되면 Unity Editor를 열고, 스크립트를 작성할 수 있는 코드 편집기를 선택함 (예: Visual Studio)
  2. 스크립트를 작성할 폴더를 생성하고, 해당 폴더에 새로운 C# 스크립트 파일을 만듬
  3. 스크립트 파일을 더블 클릭하여 코드 편집기에서 스크립트를 염
  4. 스크립트 파일에는 게임의 로직, 오브젝트의 동작, 입력 처리 등을 정의하는 코드를 작성함

○ 스크립트 작성 방법

  • MonoBehaviour를 상속받은 클래스를 작성함. 이 클래스는 유니티의 게임 오브젝트와 연결된 스크립트로 동작함
    (유니티의 이벤트 함수를 사용하기 위해서 꼭 상속 받아야 함)
  • 필요한 변수, 함수, 이벤트 등을 정의하고 구현함. 게임의 동작을 위한 로직을 작성함
  • 필요한 Unity 함수들을 오버라이딩하여 원하는 동작을 구현할 수 있음.(진짜 오버라이딩은 아니고 오버라이딩과 비슷함)
    예를 들어, Start(), Update(), FixedUpdate() 등을 활용할 수 있음
  • 필요에 따라 다른 스크립트나 Unity의 컴포넌트와 상호작용하는 코드를 작성할 수 있음

○ 스크립트 라이프 사이클

  • Monobehaviour를 상속받는 클래스들은 유니티 이벤트 함수를 활용할 수 있음
  • 게임 오브젝트의 생명 주기 동안 호출되는 특정한 메서드들의 순서와 타이밍
  • 게임 오브젝트의 생성, 초기화, 업데이트, 파괴 등과 관련된 작업을 수행
  1. Awake : 게임 오브젝트가 생성될 때 호출되는 메서드. 주로 초기화 작업이 수행
  2. OnEnable : 게임 오브젝트가 활성화될 때 호출되는 메서드
  3. Start : 게임 오브젝트가 활성화되어 게임 루프가 시작될 때 호출되는 메서드. 초기 설정 및 시작 작업을 수행

[여기까지 첫 프레임 시작 전에 발동]

  1. FixedUpdate : 물리 엔진 업데이트 시 호출되는 메서드. 물리적인 시뮬레이션에 관련된 작업을 처리할 때 사용
    • OnTrigger
    • OnCollision
  2. Update : 매 프레임마다 호출되는 메서드로, 게임 로직의 주요 업데이트가 이루어짐
  3. LateUpdate : Update 메서드 호출 이후에 호출되는 메서드. 다른 오브젝트의 업데이트가 완료된 후에 작업을 수행하는 데 유용
    랜더링과 직접적으로 연관된 카메라 이동같은 것을 업데이트함
  4. OnDisable : 게임 오브젝트가 비활성화될 때 호출되는 메서드
  5. OnDestroy : 게임 오브젝트가 파괴될 때 호출되는 메서드. 자원 정리 및 해제 작업이 수행됨
  6. OnApplicationQuit : 껐을 때 호출되는 메서드
    이벤트 함수 실행 순서 참고링크


2. 핵심 기능 소개

○ Pixels Per Unit (PPU)

  • Pixels Per Unit (PPU): 스프라이트의 픽셀 수와 해당 스프라이트가 게임 세계에서 차지하는 공간의 관계를 설명함.
    예를 들어, PPU가 100이라면 스프라이트의 100픽셀은 게임 세계에서 1 유니티 단위를 나타냄
  • 스프라이트의 크기: PPU 값이 클수록 스프라이트는 작아짐. 이는 더 많은 픽셀이 동일한 게임 세계의 공간에 매핑되기 때문
  • 물리 시뮬레이션: PPU 값은 물리 시뮬레이션에 영향을 미침. 높은 PPU 값은 더 작은 스프라이트를 생성하므로, 이는 더 높은 해상도의 물리 시뮬레이션을 가능하게 함
  • 퍼포먼스: 높은 PPU 값은 더 많은 연산을 필요로 함. 이는 성능에 영향을 미칠 수 있음. 따라서, 필요한 만큼의 PPU 값을 설정하는 것이 중요함
  • 일관성: 모든 스프라이트에 대해 일관된 PPU 값을 사용하는 것이 좋음. 이는 스프라이트간의 크기 비율을 일정하게 유지하고, 물리적 행동의 일관성을 보장하는 데 도움이 됨.

○ 계층 구조 ('Transform' 구조)

  • 각 게임 오브젝트는 Transform 컴포넌트를 가지고, Transform 컴포넌트는 게임 오브젝트의 위치, 회전, 및 크기(scale)를 정의함
  • 게임 오브젝트는 다른 게임 오브젝트의 '자식'이 될 수 있음
  • 부모 게임 오브젝트의 Transform이 변경되면(예: 이동, 회전, 크기 변경), 그 자식 오브젝트들의 Transform도 동일하게 적용됨
  • 이렇게, 게임 오브젝트들 사이에 계층적인 관계가 형성되고 이를 '트리 구조'라고도 부름
  • 이 구조는 복잡한 씬을 구성하고 관리하는데 유용합니다. 예를 들어, 차량 게임 오브젝트 내부에 각각의 부품(바퀴, 핸들 등)을 자식 게임 오브젝트로 두면, 차량의 Transform이 변경될 때 각 부품들도 함께 움직임
  • 이름이 Transform인 이유
    이유는 트랜스폼의 데이터들이 부모에 대한 변환(Transformation)을 나타내고 있기 때문.
    예를 들어, position이 2, 0, 0인 트랜스폼이 있다면, 부모에 대해 position이 2만큼 x로 떨어져있다라는 것

○ 월드 좌표계(World Coordinate System)

  • 월드 좌표계는 게임 세계의 전체적인 참조 프레임을 제공함
  • 이는 모든 게임 오브젝트가 공유하며, 월드 좌표계에서의 위치는 게임 환경 내에서 오브젝트의 절대적인 위치를 나타냄
  • 월드 좌표계는 변하지 않고 일정하게 유지됨
  • 스크립트에서는 position, rotation, lossyScale 를 통해 참조함

○ 로컬 좌표계(Local Coordinate System)

  • 유니티에서 인스펙터창에서 볼 수 있는 position, scale, rotation 등이 로컬 좌표계에 따른 값에 해당함
  • 이는 월드 좌표계가 아닌 부모에 대한 좌표를 말하며, 부모에 대해 x축으로 2만큼 떨어져 있으면 이 오브젝트의 로컬 포지션은 (2, 0, 0)이 되는 것
  • 스크립트에서는 localPosition, localRotation, localScale 등이 있음

○ Input.GetAxis

  • Input.GetAxis는 유니티의 입력 시스템에서 사용되는 메서드
  • 이 메서드는 입력 축의 값을 반환함
  • 입력 축은 주로 키보드나 조이스틱과 같은 입력 장치의 입력을 나타냄
  • GetAxis 메서드는 -1부터 1 사이의 값을 반환하는데, 입력 장치의 움직임에 따라 해당 값이 변경됨
  • 값이 0에 가까울수록 입력이 없거나 중립 상태를 나타내며, 양수 값은 양 방향 입력을, 음수 값은 음 방향 입력을 나타냄
  • GetAxis 메서드는 주로 플레이어의 움직임, 회전, 점프 등을 처리하는 데 사용됨
  • 예를 들어, 수평 이동을 처리하는 경우, 좌우 화살키의 입력에 따라 Input.GetAxis("Horizontal")을 사용하여 좌우 방향의 값을 얻을 수 있음
  • 이 값은 플레이어의 이동 속도나 회전 속도와 같은 변수에 적용하여 게임 오브젝트를 제어할 수 있음

○ TIme.deltaTime

  • 이전 프레임부터 현재 프레임까지의 경과 시간을 나타냄
  • deltaTime은 게임의 프레임 속도에 상관없이 일정한 시간 간격으로 동작하는 게임을 만들 때 유용하게 사용됨
    (delta는 차이를 말할때 주로 쓰임)
  • 주로 움직임, 애니메이션, 물리 시뮬레이션 등에서 시간에 따른 변화를 조정하는 데 사용됨
  • 예를 들어, transform.Translate(Vector3.forward * speed * Time.deltaTime)과 같이 사용하면 프레임 속도에 관계없이 speed만큼의 일정한 이동 속도를 보장할 수 있음
  • Time.deltaTime은 초 단위의 값을 반환하며, 1초에 1에 가까운 값을 가짐
  • 게임의 로직이 매 프레임마다 일정한 속도로 실행되어야 할 때, deltaTime을 이용하여 이동, 회전, 애니메이션 등의 연산에 일정한 시간 간격을 적용할 수 있음
  • 이를 통해 게임이 일정한 속도로 동작하고, 다양한 기기나 환경에서도 일관된 경험을 제공하고 제어할 수 있음

○ 접근 제한자와 직렬화 속성

  • public
    • 직렬화 했다고도 표현함
    • 변수나 메서드가 외부에서 접근 가능하도록 공개
    • 다른 클래스나 스크립트에서 해당 멤버에 접근하여 값을 설정하거나 호출
  • private
    • 변수나 메서드가 같은 클래스 내에서만 접근 가능하도록 제한
    • 다른 클래스나 스크립트에서는 접근할 수 없고, 해당 클래스 내부에서만 사용
    • 보통 내부 상태를 관리하거나 내부 구현에 사용
  • SerializeField
    • private이지만 직렬화 하고 싶을 때 사용
    • private로 선언된 변수를 인스펙터에서 직접 접근
    • 기본적으로 private 변수는 인스펙터에 표시되지 않지만, SerializeField를 사용하면 해당 변수가 인스펙터에서 수정 가능한 필드로 표시
      참고링크
  • 예시코드
 public class ExampleClass : MonoBehaviour
{
    public int publicVariable;
    private int privateVariable;
    
    [SerializeField]
    private int serializedFieldVariable;
    
    private void Start()
    {
        publicVariable = 10;  // 외부에서 접근 가능
        privateVariable = 20; // 클래스 내부에서만 접근 가능
        serializedFieldVariable = 30; // 인스펙터에서 접근 가능
    }
}


3. 이동 기본 코드 작성

  • 구 인풋 시스템(InputManager)을 기반으로 코드를 작성
    (InputManager도 아직 많이 활용함)
  • InputManagerMovement 작성
using UnityEngine;

public class InputManagerMovement : MonoBehaviour
{
    Rigidbody2D rigidbody;
    // private이지만 인스펙터 표출은 하고 싶어!
    [SerializeField] private float speed;
    
    // Start is called before the first frame update
    void Start()
    {
        // Rigidbody2D를 캐싱합니다.
        rigidbody = GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    void Update()
    {
        // Input Manager에서 Vertical축과 Horizontal축의 입력을 받아옴
        // float vertical = Input.GetAxis("Vertical");
        // float horizontal = Input.GetAxis("Horizontal");
        // 퍼프레임마다 Vertical축과 Horizontal축을 가져옴
        // GetAxis는 보정이 있어서 캐릭터의 움직임이 딱딱 끊기지 않음
        
        float vertical = Input.GetAxisRaw("Vertical");
		float horizontal = Input.GetAxisRaw("Horizontal");
		// GetAxisRaw 는 +1, -1 입력만 받아서 딱딱 끊김

        Vector2 direction = new Vector2(horizontal, vertical);
        
        // 정규화를 하고 싶음 : 길이를 1로 만드는 작업
        // 벡터에 normalized를 하면 벡터의 길이를 1로 만듬
        // 예를 들어, vertical, horizontal 모두 1인 경우, direction의 크기는 1보다 크게 될 수 있는데, 이를 1로 맞춰줌
        direction = direction.normalized;

        // rigidbody.velocity는 해당 물체가 1초당 움직이는 거리를 말함
        rigidbody.velocity = direction * speed;
    }
}
  • Vector2
    • 2차원 벡터를 나타내는 자료형
    • 이를 통해 x와 y 좌표를 가진 점을 나타내거나 2D 게임이나 물리 연산에서 방향과 크기를 표현하는 데 사용됨
    • 주로 2D 공간에서의 위치, 속도, 힘 등의 벡터 값을 계산하는 데 유용
    • Vector3가 3차원 벡터를 나타내는 것과 달리 Vector2는 2D 공간에서 사용됨
    • Vector2는 두 개의 float 값을 갖는 자료형으로, 주로 다음과 같은 상황에서 사용됨
      • 게임 캐릭터의 위치나 이동 방향
      • 물리 연산에서 속도나 가속도 계산
      • UI 요소의 위치 계산

0개의 댓글