2D Player Controller

앞서 2월달에 올려놓은 플레이어 움직임에 대해서 많이 바뀌게 되어서 해당 내용을 포스팅하면서 공부할 예정이다.

2D 움직임

위 내용에서는 기본적인 움직임을 다루었다면 이번에는 키입력, 움직임코드 분리(객체지향적), 자연스러운 움직임 표현등을 목표한다.

Controller

입력에 대한 일반화를 위해서 컨트롤러를 만들어 두고 활용하는 방법을 채택했다.

  1. 스크립터블 오브젝트를 상속받는 추상클래스 InputController를 만든다.
  2. InputController 클래스 내부에 각 입력을 받는 추상메서드들을 작성한다.(점프, 공격, 움직임 등등..)
  3. InputController를 상속받는 PlayerController클래스를 만든다.
  4. PlayerController에서 추상화 메서드에 대한 정의를 작성한다.
  5. Controller클래스를 만들고 public형식으로 InputController를 형식으로 받는다.
using UnityEngine;

/// <summary>
/// 입력/출력 컨트롤러 스크립터블 오브젝트
/// 아래에 입력에 필요한 추상화 메서드 작성..!
/// </summary>
public abstract class InputController : ScriptableObject
{
    /// <summary>
    /// 좌/우 움직임을 받는 메서드
    /// </summary>
    /// <returns></returns>
    public abstract float RetrieveMoveInput();
    
    /// <summary>
    /// 점프 입력을 받는 메서드
    /// </summary>
    /// <returns></returns>
    public abstract bool RetrieveJumpInput();

    /// <summary>
    /// 점프 홀드
    /// </summary>
    /// <returns></returns>
    public abstract bool RetrieveJumpHoldInput();

    /// <summary>
    /// 공격 입력
    /// </summary>
    /// <returns></returns>
    public abstract bool RetrieveAttackInput();
}

위처럼 입력에 대한 처리를 추상메서드로 작성하게 되면 해당 컨트롤러를 상속받는 컨트롤러는 메서드를 필수적으로 구현해야하기 때문에 빠지는 실수가 줄어든다.

그렇다면 왜 입력에 대한 처리를 일반화 하였는지에 대한 의문이 들 수 있다.

PlayerController는 당연하게 상속받아서 사용하지만 일방적인 1차원 상속이라면 필요하지 않은 과정이기 때문이다.

하지만 AIController로 구분하여 사용한다면 몬스터, NPC움직임 컨트롤러로 다앙하게 추상적 프로그래밍이 가능해진다.

using UnityEngine;

/// <summary>
/// 플레이어 입력 컨트롤러
/// </summary>
[CreateAssetMenu(fileName = "PlayerController", menuName = "inputController/PlayerController")]
public class PlayerController : InputController
{
    public override float RetrieveMoveInput()
    {
        return Input.GetAxisRaw("Horizontal");
    }

    public override bool RetrieveJumpInput()
    {
        return Input.GetButtonDown("Jump");
    }

    public override bool RetrieveJumpHoldInput()
    {
        return Input.GetButton("Jump");
    }

    public override bool RetrieveAttackInput()
    {
        return Input.GetKey(KeyCode.Z);
    }
}

해당 스크립트 자체를 스크립터블 오브젝트로 변환하여 사용가능하게 만들어 두고 각 객체에 컴포넌트에 삽입하여 관리한다.

using UnityEngine;

/// <summary>
/// 컨트롤러 컴포넌트
/// </summary>
public class Controller : MonoBehaviour
{
    public InputController input = null;
}

위의 컴포넌트만 추가하고 나머지는 스크립터블 오브젝트를 삽입하여 관리하면 된다.

using UnityEngine;

/// <summary>
/// AI입력 컨트롤러(몬스터에 활용)
/// </summary>
[CreateAssetMenu(fileName = "AIController", menuName = "inputController/AIController")]
public class AIController : InputController
{
    public override float RetrieveMoveInput()
    {
        return 1f;
    }

    public override bool RetrieveJumpInput()
    {
        return true;
    }

    public override bool RetrieveJumpHoldInput()
    {
        return false;
    }

    public override bool RetrieveAttackInput()
    {
        return false;
    }
}

만약 controller를 가진 두가지의 객체가 있다고 해도 할당하는 오브젝트 성격에 따른 다른 입력처리를 할 수 있다.

태그: ,

카테고리:

업데이트:

댓글남기기