Game Development, 게임개발/개발

UnityEvent, UnityAction - 유니티 이벤트, 유니티 액션[Unity]

게임이 더 좋아 2022. 2. 16. 00:19
반응형
728x170

오늘 나의 무능함을 느끼고.. 공부를 다시 시작해본다.

너무 우울하다.

서론이 길었다.

알아보자


 

UnityEvent란 무엇인지 먼저 알아보자

 

** using UnityEngine.Events 를 해야 쓸 수 있다.

** UnityEvent는 MonoBehavior를 상속받는 모든 클래스에 사용가능하다.

 

유니티는 수많은 콜백함수를 제공하는데 마지 옵저버 패턴과 같이 이벤트가 일어나길 기다리고 있다가

특정한 이벤트가 일어났을 때 수행하게 된다.

 

**우리가 UI의 버튼을 만들면 onClick에 수행할 함수나 객체를 등록해서 함수를 실행시키거나 객체 활성화 등을 할 수 있는 것과 같은 이치다.

 

??그럼 그냥 Inspector에서나 추가하면 되는 것이지..

뭣하러 스크립트에서 추가한대유???

 

에셋과 스크립트 충돌을 피하고 원활한 업데이트를 위해서 라고 말하더라..

(나도 정확한 이유는 모르겠다.)

 

예를 들어서 보면 더 이해가 잘된다.

using UnityEngine;
using UnityEngine.Events;
using System.Collections;

//네임스페이스 확인하고


//MonoBehaviour를 상속받는 일반적인 스크립트에서 다 사용 가능
public class ExampleClass : MonoBehaviour {

	
	UnityEvent m_MyEvent;
	
	void Start() {
   		//해당 이벤트를 생성하고
		if (m_MyEvent == null)
			m_MyEvent = new UnityEvent ();
		
        //이벤트에 Ping이라는 함수를 등록해놓는다.
		m_MyEvent.AddListener (Ping);
	}
	
    
    //Update에서 특정 조건을 만족하는지 본다.
	void Update() {
    
    	//Event가 생성되었고, 어떤 키를 누르게 되면
		if (Input.anyKeyDown && m_MyEvent != null)
		{
              //Event에 등록된 함수 모두가 실행된다.
			m_MyEvent.Invoke ();
		}
	}
	
    
    //UnityAction은 void 함수로 정의된다.
	void Ping() {
		Debug.Log ("Ping");
	}
}

 

 

**일반적으로 AddListener는 아래와 같은 꼴이다.

public void AddListener(Events.UnityAction call);

 

아하??? UnityEvent에 등록되는 것은 UnityAction이구나??

-> 맞다. 별 것은 아니다. 그냥 UnityAction(method1)하면 델리게이트 등록이다.

 

 

그렇다면 등록만 할 수 있느냐???

그건 아니다.

당연히 해당 Event에 등록된 것은 해제할 수도 있다!

 

예를 보자

//게임 오브젝트에 붙여서 실행하며
//이 스크립트에서 생성된 유니티 이벤트는 키가 눌렸을 때 메서드를 실행하게 한다.
//q를 눌러서 해제한다.
using UnityEngine;
using UnityEngine.Events;

public class Example : MonoBehaviour
{
    UnityEvent m_MyEvent = new UnityEvent();

    void Start()
    {
        //Add a listener to the new Event. Calls MyAction method when invoked
        m_MyEvent.AddListener(MyAction);
    }

    void Update()
    {
        // q를 감지해서 Event의 함수를 해제한다. 동시에 Application도 종료한다.
        if (Input.GetKeyDown("q") && m_MyEvent != null)
        {
            Debug.Log("Quitting");
            m_MyEvent.RemoveListener(MyAction);

            #if UNITY_EDITOR
            UnityEditor.EditorApplication.isPlaying = false;
            #endif
			
            Application.Quit();
        }
		
        //어느키라도 누르면 해당 이벤트에 함수가 등록된다. 정확히 UnityAction이 등록된다.
        if (Input.anyKeyDown && m_MyEvent != null)
        {
            //Begin the action
            m_MyEvent.Invoke();
        }
    }

    void MyAction()
    {
        Debug.Log("Do Stuff");
    }
}

 

아니 근데 인자가 없는 함수만 등록되는거야..??

아니다!! 인자가 있어도 된다.

다만 조금 방식이 다르다.

 

using UnityEngine;
using UnityEngine.Events;
using System.Collections;
using System.Collections.Generic;
 
 
// 먼저 public으로 클래스를 만든다.
// 이 클래스는 UnityEvent이 2개의 float을 인수로 받는다. 
[System.Serializable] public class XYEvent : UnityEvent<float, float> { }
 
 
 
public class Drawing : MonoBehaviour // for example, some sort of drawing class
{
    // public으로 이벤트를 선언한다.
   
    public XYEvent pointUpdates;
   
    // 물론 이 이벤트에는 인수가 있는 UnityAction만 넣을 수 있다.
   
   
    void Update()
    {
       
        //언제 인수를 넣느냐? 그것은 Invoke로 실행할 때 넣어준다.
        pointUpdates.Invoke(currentPosition.x, currentPosition.y);
    }
}

 

** UnityEvent는 인자값이 없거나 최대 4개까지 있는걸 받을 수 있다.

 

예를 더 보자

using UnityEngine;
using System.Collections;
using UnityEngine.Events;
using UnityEngine.UI; //버튼
 
public class UnityEventTest : MonoBehaviour
{
   int _index = 0;
   Button _btn; //이번엔 버튼이다. UI네?
   
   void Start()
   {
       GameObject go = new GameObject("createdGO");
       go.AddComponent<Button>();
       _btn = go.GetComponent<Button>();
       
       //#1 버튼의 onClick Event에 람다식 등록
       _btn.onClick.AddListener(() => Method1(_index));
       //#2 직접 등록
       _btn.onClick.AddListener(Method2);
       //#3 unityaction 을 람다식으로 만듬
       UnityEngine.Events.UnityAction action = ()=>{ Method3(_index);};
       _btn.onClick.AddListener(action);
       //#4 delegate으로 바로 등록
       _btn.onClick.AddListener(delegate{ Method4(_index); });
   }
 
   void Update ()
   {
       if (Input.GetKeyDown (KeyCode.A))
       {
           _btn.onClick.Invoke();
       }
   }
 
   void Method1(int index)    {     Debug.Log("Method1:" + index); }
   void Method2()            {     Debug.Log("Method2");}
   void Method3(int index)    {     Debug.Log("Method3:" + index); }
   void Method4(int index) {     Debug.Log("Method4:" + index); }
}

 

 

결과는 예상대로

Method1:0
Method2
Method3:0
Method4:0

 

 


참고링크

https://docs.unity3d.com/kr/530/ScriptReference/Events.UnityEvent.html

반응형
그리드형