GAME ENGINE/Unity

Managers에 InputManager 집어넣어 event class 관리하기

혀니리리 2022. 9. 4. 03:35
728x90

저번에 만들었던 그 Managers에 이제 본격적으로 필요한 클래스들을 넣어서 그때그떄 필요할 때만 함수들을 출력하며 관리하려고 한다.

//Managers.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Managers : MonoBehaviour
{
    static Managers s_instance;
    static Managers Instance{ get { init(); return s_instance;} } //1.init()을 통해 씬에 Manager 없으면 만들고 안에 Managers.cs넣어서 instance출력 

    InputManagers _input = new InputManagers(); //2.우리가 지금 추가한 InputManager의 이벤트함수를 Managers.cs안에서 관리하기 위해 할당
    public static InputManagers Input { get { return Instance._input; } } //3.다른 곳에서 지금 우리가 만든 이 Managers.cs의 instance의 InputManager클래스 쓰기 위한 선언 
    // Start is called before the first frame update
    void Start()
    {
        init();
    }

    // Update is called once per frame
    void Update()
    {
        _input.OnUpdate(); //4.지금 추가한 inputManager의 함수 기능을 Update에 넣어 조건 충족 시 동작하도록 함
    }

    static void init()
    {
        if(s_instance == null)
        {
            GameObject go = GameObject.Find("@Managers");
            if(go == null)
            {
                go = new GameObject { };
                go.AddComponent<Managers>();
            }
            DontDestroyOnLoad(go);
            s_instance = go.GetComponent<Managers>();
        }
    }
}
//InputManagers.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class InputManagers
{
    public Action KeyAction = null; //5.리스너 패턴, using System을 사용

    public void OnUpdate() //6.안의 함수를 만들어서 가장 큰 부모 class인 Managers에서 이를 판단하게 함.
    {
        if (Input.anyKey == false)
            return;
        if (KeyAction != null) //7.액션이 있을 때 KeyAction에 그 키를 저장한다. 
            KeyAction.Invoke();
    }
}
//playerController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    [SerializeField]
    float speed = 10.0f;
    void Start()
    {
        Managers.Input.KeyAction -= OnKeyboard; //8.가장 큰 총괄 class Managers가 관리하는 Input Manager class의 KeyAction을 우선 비활성화(다른데서 끄기)
        Managers.Input.KeyAction += OnKeyboard; //지금 받은 키값으로 변경 (아래 함수를 실행시킴으로써)
    }
    void Update()
    {

    }

    void OnKeyboard()
    {
        if (Input.GetKey(KeyCode.W))
        {
            transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(Vector3.forward), 0.2f);
            transform.position += Vector3.forward * Time.deltaTime * speed;
        }
        if (Input.GetKey(KeyCode.S))
        {
            transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(Vector3.back), 0.2f);
            transform.position += Vector3.back * Time.deltaTime * speed;
        }
        if (Input.GetKey(KeyCode.A))
        {
            transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(Vector3.left), 0.2f);
            transform.position += Vector3.left * Time.deltaTime * speed;
        }
        if (Input.GetKey(KeyCode.D))
        {
            transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(Vector3.right), 0.2f);
            transform.position += Vector3.right * Time.deltaTime * speed;
        }

    }
}

기존에는 player안에 PlayerController.cs를 넣고, Update함수에 OnKeyboard()함수에 해당하는 모든 내용을 때려넣었다.

이랬을 경우의 문제점

1.player가 여러 명일 때 어디서 오류가 났는지 판단하기 어려움

2.계속해서 update함수에서 불필요한 경우에도 연산을 실행하기 때문에 대형 프로젝트에서는 연산량이 많이 듦

(player 6명이면 update도 6배)

같은 것들이 있다.

 

따라서, 우리가 저번 시간에 만들었던 프로젝트 내의 모든 class들을 가장 크게 관리하는 Manager에서 이 동작을 실행하게 해주면 전체에서 이 코드를 한번만 실행할 수 있게 된다. (update 한번)

 

앞으로도 다양한 class들을 manager하나에서 관리할 일이 많을테니 계속 하면서 익혀나가도록 하자.

728x90