2024-05-08
새로운 팀과 함께 새로운 주차가 시작되었다.
Unity 게임 개발 입문 강의를 통해,
2D 탑다운 형식의 게임을 따라 만들어보고,
개인 프로젝트 탑뷰 게임을 만들어보는 것이 이번 주차의 목표이다.

스크립트에서 Private 로 선언된 필드를 직렬화하기 위해 사용한다.
유니티 스크립트에서 public 필드만 직렬화 할 수 있다.
그러나, [SerializeField] 를 사용하여 private 필드도 직렬화 할 수 있다.
( 스크립트에서 private 로 지정한 변수는 Unity 인스펙터 창에서 볼 수 없다. )
public int publicVariable;
private int privateVariable;
[SerializeField] int serializeFieldVariable;
private void Start()
{
publicVariable = 10; // 외부에서 접근 가능
privateVariable = 20; // 클래스 내부에서만 접근 가능
serializeFieldVariable = 30; // 인스펙터에서 접근 가능
이외에도 직렬화를 커스터마이징 하고 싶을 때, 코드를 더 쉽게 업데이트하기 위해 등이 있다.
Square 오브젝트에 아래의 InputManager.cs 스크립트와 Rigidbody2D 컴포넌트를 추가해줘서
방향키로 오브젝트를 이동할 수 있게 만들었다.
| InputManager.cs | Inspector 창 |
|---|---|
![]() | ![]() |
[SerializeField] 로 선언해준 private float speed1 과 private float speed2 가 있는데,
Inspector 창의 InputManager 스크립트를 보면 Speed1 에만 접근할 수 있다.
위에서 사용한 InputManager 방법은
다양한 플랫폼 (플레이스테이션, 닌텐도 스위치, 모바일) 에 대응하거나,
키를 변경하는 리바인딩이 쉽지 않다.
확장성과 유지보수를 위해 기능별로 클래스를 나누는 방법인 단일 책임 원칙(Single Responsibility Principle) 을 통해 InputSystem 을 도입하였다.
Input System 을 사용하기 위해서는 패키지를 추가해줘야 한다.
Window - Package Manager - Unity Registry - Input System - Install
예시로 WASD 방향으로 이동시키고, 마우스를 향해 바라보는 플레이어를 만들 것이다.
| Action Type | 설명 |
|---|---|
| Value | 일반적인 상태에서 사용. 눌렀을 때, 누르고 있을 때, 뗄 때 등 다양한 상황에 대응 |
| Button | 눌렀을 때 발생하는 액션에 활용. Control Type 이 Button 으로 고정됨 |
| Pass-Through | Value 와 비슷하지만, 명확성를 사용하지 않음 |
TopDownController : 캐릭터의 이동과 회전을 처리하는 핵심 컨트롤러 역할
public class TopDownController : 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);
}
}
PlayerInputController : 플레이어의 입력을 처리하는 역할
using UnityEngine;
using UnityEngine.InputSystem;
using static UnityEngine.RuleTile.TilingRuleOutput;
public class PlayerInputController : TopDownController
{
private Camera camera;
private void Awake()
{
camera = Camera.main;
}
public void OnMove(InputValue value)
{
// Debug.Log("OnMove" + value.ToString());
Vector2 moveInput = value.Get<Vector2>().normalized;
CallMoveEvent(moveInput);
}
public void OnLook(InputValue value)
{
// Debug.Log("OnLook" + value.ToString());
Vector2 newAim = value.Get<Vector2>();
Vector2 worldPos = camera.ScreenToWorldPoint(newAim);
newAim = (worldPos - (Vector2)transform.position).normalized;
}
}
TopDownMovement : 실제 캐릭터의 이동을 구현하는 역할
using UnityEngine;
// TopDownMovement는 캐릭터와 몬스터의 이동에 사용될 예정입니다.
public class TopDownMovement : MonoBehaviour
{
private TopDownController movementController;
private Rigidbody2D movementRigidbody;
private Vector2 movementDirection = Vector2.zero;
private void Awake()
{
// 같은 게임오브젝트의 TopDownController, Rigidbody를 가져올 것
movementController = GetComponent<TopDownController>();
movementRigidbody = GetComponent<Rigidbody2D>();
}
private void Start()
{
// OnMoveEvent에 Move를 호출하라고 등록함
movementController.OnMoveEvent += Move;
}
private void FixedUpdate()
{
// 물리 업데이트에서 움직임 적용
ApplyMovement(movementDirection);
}
private void Move(Vector2 direction)
{
// 이동방향만 정해두고 실제로 움직이지는 않음.
// 움직이는 것은 물리 업데이트에서 진행(rigidbody가 물리니까)
movementDirection = direction;
}
private void ApplyMovement(Vector2 direction)
{
direction = direction * 5;
movementRigidbody.velocity = direction;
}
}
Player 라는 오브젝트를 생성하여, Rigidbody2D 와 Player Input 컴포넌트, Player Input Controller.cs 와 Top Down Movement.cs 를 추가해주었다.
갑자기 난이도가 확 올라간 느낌이다.
단순히 기능 구현을 목표로 공부하는 것이 아닌
현업에서 다양한 플랫폼에 지원하기 위해서 새로운 기술을 도입하고 응용하는 법을 배운 것 같아
신기하기도 하지만 아직까진 잘 와닿지 않는다.
개인 프로젝트를 진행하면서, 다시 강의를 들으며 복습해봐야겠다.