본문 바로가기

개발 프로젝트/Unity - WeaponGameProject

WeaponGameProject - Player 클래스 설계 (1) (Key Input을 클래스로 만들자)

 예전부터 Unity에서 키 입력을 받을 때는 굉장히 단순하게 처리를 했습니다. 예를 들면 

using UnityEngine

Class A {

	bool isBashPressed = false;
    
    private void Update () {
        if (Input.GetKeyDown(KeyCode.LeftShift))
                {
                    isBashPressed = true;
                }
                if (Input.GetKeyUp(KeyCode.LeftShift))
                {
                    isBashPressed = false;
                }
    }
	
}

이런 형태를 말합니다. 벌써 위험해 보입니다.

키 입력이 모여 있지 않고 클래스에 분산 되어 있으면

키 입력 Output이 어디 존재하고 어떻게 발동하는지 모르니 굉장히 위험하죠.

 

그런데 Unity 스크립트를 알려주는 대부분의 홈페이지와 심지어 특정 도서마저 키 입력을 단순하게 작성하게 유도합니다. 그러나 이런 형태 보다는 키 입력만을 담당하는 클래스를 만드는게 필요해 보였습니다. 이런 생각을 통해 이 프로젝트에서 처음 작성한 코드가 PlayerInput 클래스 입니다. 

using UnityEngine;


    public class PlayerInput : MonoBehaviour
    {
        private bool _attackInput;
        private bool _specialAttackInput;
        private bool isMousePressed;
        private Vector2 _movementInput;
        private bool _jumpInput;
        private bool _changeCameraModeInput;
        private bool _weaponPickUpInput;
        private bool _bashInput;
        private bool _skill01Input;
        private bool isBashPressed;
        private Vector2 _mouseInput;

        public bool AttackInput {get => _attackInput;}
        public bool SpecialAttackInput {get => _specialAttackInput;}
        public bool IsSpecialKeyHold { get => CheckSpecialKeyHold(); }
        public Vector2 MovementInput {get => _movementInput;}
        public bool JumpInput { get => _jumpInput; }
        public bool ChangeCameraModeInput {get => _changeCameraModeInput;}
        public bool WeaponPickUpInput { get => _weaponPickUpInput; }
        
        public bool BashInput { get => _bashInput;}

        public bool Skill01Input { get => _skill01Input;  }
        public bool IsBashKeyHold { get => CheckBashKeyHold(); }
        public Vector2 MouseInput { get => _mouseInput;}


        
        private void Update()
        {
            _attackInput = Input.GetMouseButtonDown(0);
            _specialAttackInput = Input.GetMouseButtonDown(1);
            _movementInput.Set(Input.GetAxis("Horizontal"),Input.GetAxis("Vertical"));
            _jumpInput = Input.GetButton("Jump");
            _changeCameraModeInput = Input.GetKeyDown(KeyCode.F);
            _weaponPickUpInput = Input.GetKeyDown(KeyCode.Q);
            _mouseInput = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
            _bashInput = Input.GetKeyDown(KeyCode.LeftShift);
            _skill01Input = Input.GetKeyDown(KeyCode.H);
        }

        private bool CheckSpecialKeyHold()
        {
            if (Input.GetMouseButtonDown(1))
            {
                isMousePressed = true;
            }

            // 마우스 왼쪽 버튼이 떼졌을 때
            if (Input.GetMouseButtonUp(1))
            {
                isMousePressed = false;
            }

           return isMousePressed;
        }

        private bool CheckBashKeyHold()
        {
            if (Input.GetKeyDown(KeyCode.LeftShift))
            {
                isBashPressed = true;
            }
            if (Input.GetKeyUp(KeyCode.LeftShift))
            {
                isBashPressed = false;
            }

            return isBashPressed;
        }
    }

PlayerInput은 MonoBehavior를 상속받는 유니티에 인스턴스화 되어 Update를 통해 동작하는 클래스입니다.

PlayerInput클래스의 정보는 다른 클래스에서 절대 Set할 수 없으며 오직 Get만 가능합니다.

모든 키 입력 정보 ,마우스 입력 정보는 PlayerInput 클래스를 통해서만 사용할 수 있습니다.

PlayerInput 클래스에 존재하는 bool 자료형을 살펴본다면 앞으로 무슨 기능을 소개할지 유추할 수 있겠군요.

 

아래는 사용 예시입니다.

 using UnityEngine
 public class ClassB{
 
 	private PlayerInput _playerInput;
    private CharacterController _characterController;
    void Start()
	{
		 _playerInput = GetComponent<PlayerInput>();		// 기본적으로 Player에게 탑재시키고 사용을 합니다.
         													//PlayerInput 인스턴스를 GameManger 인스턴스에 배치하여 FindObjectWithTag등으로 찾을 수도 있음.
	}
    
    void Update() {
    	Move();
    }
    
    private void Move()
        {
            var x = _playerInput.MovementInput.x;
            var y = _playerInput.MovementInput.y;
            (Vector3)moveDirection = new Vector3(x, 0, y);
            if (_playerInput.JumpInput){
                    //Jump 진행
            }
            
            _characterController.Move(moveDirection * Time.deltaTime); 	// Move진행
        }
 }

 

이러한 형태의 최고의 장점은

PlayerInput 클래스를 통해 참조 관리하기가 편하다는 점입니다.

만약 KeyInput 의 Output에서 버그가 생긴다면, 어떤 클래스에서 버그가 생기는지 쉽게 찾아갈 수 있지요.

이상 Player의 키 Input을 관리하는 PlayerInput 클래스 소개를 마칩니다.