TIL 0118 게임개발 입문 개인과제 - 1 / 인풋 시스템, 이벤트 관리, 타일맵(+충돌) 생성

강성원·2024년 1월 18일
0

TIL 오늘 배운 것

목록 보기
19/69

오늘 공부한 내용

오늘부터 유니티를 시작했다.

오늘 과제에 대한 개발 내용은 없고 공부한 내용이 어려운 부분이 많아서 정리를 해야한다.

원래 알고있고 슥 넘어갈만한 부분은 제외하고 어려운 부분만 싹 가져와서 정리해본다.

PPU (Pixel Per Unit)

유니티에서 1 단위당 픽셀의 비율이다. PPU 50이면 1칸당 픽셀 50이 공간을 차지한다.

가로 16 픽셀의 스프라이트를 1칸에 채우고 싶으면 스프라이트의 PPU를 16으로 설정하면 된다.

PPU가 높아질 수록 엔진에서 부담하는 것이 높아진다.

New Input System

솔직히 이거 외우는건 말이 안되니까 여기다가 적어놓고 나중에 필요할 때 또 봐야겠다.

  1. 패키지 매니저에서 Input System을 설치한다.
  1. Project 창에서 Input Actions를 선택하여 생성한다. (이름은 상관없음)
  1. 만들어준 후 열어주면 아무 것도 없으니 스키마를 새로 만들어준다.
  1. 스키마를 선택 후 Action Maps를 하나 생성해준다.
    Action Maps는 입력 방법의 모음 같은 것이고, 나중에 플레이어 객체에 컴포넌트에 붙였을 때 선택해줄 수 있다.
  1. Actions를 "Move"라는 이름으로 하나 생성해준다. 이 이름은 나중에 이벤트 처리에서 중요하다.
    Actions는 어떤 키의 입력을 받을 것인지에 대해 설정할 수 있다.
  1. 아래 사진과 같은 것을 선택
  1. Action TypeValue
    Control TypeVector2로 해준다.
    Look과 Fire도 동일하게 한다.
  1. 내가 사용할 플레이어 객체에 Player Input이라는 컴포넌트를 붙여준다.
    • Actions에는 2번부터 7번까지 만든 것을 넣어준다.
    • Default Map에는 4번에서 만든 Action Maps를 선택할 수 있다.

이벤트 처리하기 (Input System과 연계)

  • 밑에 나오는 코드들의 대략적인 형태는 아래 사진과 같다.

이벤트 멤버를 가지고 있는 클래스 (CharacterController)

public class CharacterController : MonoBehaviour
{
    public event Action<Vector2> OnMoveEvent;
    public event Action<Vector2> OnLookEvent;
    
    public void CallMoveEvent(Vector2 direction)
    {
        OnMoveEvent?.Invoke(direction);
    }   
    
    public void CallLookEvent(Vector2 direction)
    {
        OnLookEvent?.Invoke(direction);
    }
}

나중에 입력에 따라서 호출할 메서드들을 받아놓을 이벤트 멤버는 클래스 CharacterController에 모아놓는다.

외부에서 클래스에 있는 이벤트 멤버에 접근할 수 없으니 이벤트를 호출하는 Call~메서드도 만들어준다.

CallMoveEvent의 내용은 아래와 같다.

if(OnMoveEvent != null)
	OnMoveEvent(direction);

Invoke는 특별한 기능은 없고 델리게이트의 메서드를 호출한다는 것을 명시하는 용도라고 생각하면 편하다.

입력에 따라 이벤트를 호출하는 클래스 (PlayerInputController)

이 코드가 제일 중요하다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerInputController : CharacterController
{
    private Camera _camera;

    private void Awake()
    {
        _camera = Camera.main; // 활성화된 카메라 중 "MainCamera" 태그 가진 Camera get
    }

    //InputValue : 인풋 시스템에 있는 클래스
    public void OnMove(InputValue value) 
    {
        Vector2 moveInput = value.Get<Vector2>().normalized;
        CallMoveEvent(moveInput);
    }

    public void OnLook(InputValue value)
    {
        Vector2 newAim = value.Get<Vector2>();
        //전체 스크린 좌표계에 종속된 마우스의 위치를 게임 화면의 좌표계로 변경
        Vector2 worldPos = _camera.ScreenToWorldPoint(newAim);
        newAim = (worldPos - (Vector2)transform.position).normalized;

        if(newAim.magnitude >= .9f)
            CallLookEvent(newAim);
    }    

    public void OnFire(InputValue value)
    {
        Debug.Log("OnFire" + value.ToString());
    }
}
  • 우선 using UnityEngine.InputSystem; 을 사용함으로써
    Send Messages 기능을 사용할 수 있다.
    그렇게 되면 Input Actions에서 만들었던 Move, Look, Fire는 각각 설정했던 키의 입력이나 알맞은 값이 들어오면 OnMove, OnLook, OnFire를 호출한다. 그리고 이 함수들은 재정의가 가능한 것 같다.
  • On~함수에서는 CharacterController에서 상속 받은 이벤트 호출 함수를 호출한다.

  • 간략히 말하면 이 클래스는 플레이어의 입력에 따라서 이벤트를 호출하는 메서드가 모인 클래스이다.

실제 움직임 구현한 클래스 (TopDownMovement)

public class TopDownMovement : MonoBehaviour
{
    private CharacterController _controller;

    private Vector2 _movementDirection = Vector2.zero;
    private Rigidbody2D _rigidbody;

    private void Awake()
    {
        _controller = GetComponent<CharacterController>();
        _rigidbody = GetComponent<Rigidbody2D>();
    }

    void Start()
    {
        _controller.OnMoveEvent += Move;
    }

    private void FixedUpdate()
    {
        ApplyMovement(_movementDirection);
    }

    private void Move(Vector2 direction)
    {
        _movementDirection = direction;
    }

    private void ApplyMovement(Vector2 direction)
    {
        direction = direction * 5;

        _rigidbody.velocity = direction;
    }
}
  • Start()에서는 일단 CharacterController의 이벤트에 시그니처가 맞는 Move 메서드를 등록한다.

  • Move()에서는 전달 받은 벡터 값으로 방향만 정해준다.

  • FixedUpdate()에서 ApplyMovement()를 방향을 인자로 계속 호출.

  • ApplyMovement()에서는 받은 방향에 일정 값 곱해서 강체의 속도로 할당해줌.


타일 맵 그리기 (충돌로 벽 만들기)

  1. [window] -> [2D] -> [Tile Palette]를 선택해서 타일 팔레트를 가져온다.
  1. 팔레트에 내가 원하는 스프라이트들을 드래그 앤 드랍한다.
  1. 하이어라키에서 [2D Object] -> [Tilemap] -> [Rectangular] 을 선택하여 타일 맵 객체를 하나 만들어준다.
  1. 팔레트에서 스프라이트 하나를 선택하여 원하는 타일 맵에 그대로 그려넣을 수 있다.

충돌은 간단하다.

  1. 다른 타일 맵을 하나 더 만든 후에 충돌을 넣어주고 싶은 부분을 아무 스프라이트로나 그려준다.

    그 후에 해당 타일 맵에 [Tilemap Collider 2D] 컴포넌트를 붙여주고 알파 값을 0으로 조정하여 완전 투명하게 만들어주면 된다.

오늘 하루를 마치며

입문 강의를 받아서 공부를 시작했는데,, 이거 입문이 아니라 중급으로 올라가는 난이도를..
(많은 분들이 당황하셨을 것 같다.)

솔직히 유튜버 골드메탈의 친절한 강의 수준을 생각했는데 그런거 없이 바로 불맛 난이도..

내가 필요로 하던 수준의 강의이긴 한데 너무 갑작스런 만남이라 좀 당황스럽다.

델리게이트, 이벤트의 활용은 꼭 알고싶었던 부분인데 갑자기 다가와서 이해하느라 오늘 진을 다 뻈다.
(갑작스런 패턴과의 만남 ㅋㅋㅋ)

어..일단 나의 특기인 [글 정리로 어떻게든 이해하기]를 계속 시전해야겠다는 생각뿐이다.

new input system과 이벤트 처리의 연계는 나중에 잘 정리해서 유니티 시리즈에 넣어놔야겠다.
아무리봐도 코드와 입력 처리 방식이 고급지고 참 좋아보인다.

파이팅이다.

profile
개발은삼순이발

0개의 댓글