[유니티 중급]_2 Action대리자, 이벤트

0

유니티 엔진

목록 보기
13/21
post-thumbnail

Action과 Func를 이용하여 델리게이트를 쉽게 이용하기

델리게이트 형식과 인스턴스를 만드는게 길고 복잡해서
델리게이트를 편리하게 사용하기 위해서 나온 문법이 Action 대리자Func 대리자입니다.
간단하게 반환 형식(return)이 없으면 Action,
반환 형식(return)이 있으면 Func를 사용하면됩니다.

그리고 Action과 Func를 사용하기 위해선 using System;을 선언해 주어야합니다.

(참고)
다만 using System;을 선언하면
UnityEngine.Random 클래스와 System.Random가 충돌하므로

랜덤을 쓸때 유니티 엔진 네임스페이스를 명시해 주어야합니다.

Action

'Action대리자'클래스를 만들어 Action 인스턴스를 생성합니다.
(델리게이트와 다르게 형식을 만들지 않아도 괜찮습니다.)

하지만 만약 Action을 만들고 콜백함수를 등록하지 않은 상태로 실행하게 되면 에러가 나옵니다.

따라서 오류를 방지하기 위해서 Action대리자 인스턴스를 만들때
람다식을 이용하여 텅빈 메소드 한개를 넣어두면 오류가 나오지 않기 때문에
아래와 같은 방식으로 만드는 것이 좋습니다.

이벤트

evnet 키워드를 사용하여 다른곳에서 Invoke() 못하게 막기

델리게이트는 외부에서 Invok()를 통한 실행이 가능합니다.

하지만 델리게이트 체인을 만들때 델리게이트의 인스턴스를 생성한 클래스가 아닌,
다른 클래스에서는 델리게이트를 실행하지 못하게 막는것이 좋습니다.

델리게이트를 객체 외부에서 임의로 호출할 수 있다면
객체외부에서 허위로 상태 변화 이벤트를 일으킬 수 있게 되기 때문입니다.

즉, 인스턴스를 만든곳에서는 실행을 하고,
다른 클래스에서는 '콜백함수만' 등록할 수 있게 하는것으로
예기치 못한 오류를 막는것이 좋습니다.

이벤트는 델리게이트에 수식하여 델리게이트를 외부에서 직접 실행(Invok())할 수 없게 합니다.

따라서 이벤트는 델리게이트의 은닉성을 업그레이드 한 느낌입니다.

  • 이벤트는 외부에서 직접 호출할 수 없음. 객체의 은닉성 표현을 위해
  • 대리자를 event 한정자로 수식하여 선언

게임 오브젝트 파괴시 콜백함수 삭제하기

'구독자' 스크립트 컴포넌트를 가진 게임 오브젝트가 파괴되어도
'구독자'에 연결된 콜백함수가 동작하면 예기치 못한 에러가 발생할 수 있습니다.
따라서 구독자의 경우 OnDestroy() 이벤트 함수에서 콜백 함수를 삭제해두는 것이 좋습니다.

(참고)
게임오브젝트를 활성화, 비활성화 하는 형식으로 사용한다면,
OnEnable(), OnDisable() 함수에서 등록,삭제 해주시면 됩니다.

👇구독자 전체 코드

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class 구독자 : MonoBehaviour
{
    void Start()
    {
        Action대리자.myAction += OnInputSapceBar;
    }

    void OnDestroy()
    {
        Action대리자.myAction -= OnInputSapceBar;
    }

    public void OnInputSapceBar()
    {
        Debug.Log($"콜백함수 실행!");
    }
}

Action 실행하기

키보드 W를 누르면 Action 대리자가 실행됩니다.
(델리게이트와 다르게 Invoke()를 사용할 필요가 없습니다.)

👇Action대리자 클래스 전체코드

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using System;		//필수!

public class Action대리자 : MonoBehaviour
{
    public static event Action myAction = () => {};

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.W))
        {
            myAction();
        }
    }
}

코드가 델리게이트 형식에 비해서 훨씬 간략화 되었죠?

콜백함수를 등록,삭제하는 과정은 델리게이트와 동일합니다.

📃결과

매개변수를 받을 수 있는 Action 만들기

지금까지는 매개변수가 없는 콜백함수만 등록할 수 있었습니다.
매개변수를 받을 수 있는 Action을 만들어 보겠습니다.
(델리게이트에 비하여 매개변수를 받는 과정 또한 간략화 되었습니다.)

제네릭 Action

C#팀은 Action을 일반화하여 사용하여
최대 16개의 매개변수를 받을 수 있도록 만들어 놓았습니다.

만약 받고 싶은 매개변수가 2개라면 <>안에 매개변수의 데이터 형식을 2개 만들어줍니다.
(저는 int로 했지만 다른 데이터 형식도 괜찮습니다.)

(참고)

위와 같은 방식으로 람다식으로 텅빈 메소드를 한개 만들어서 넣어두면
콜백 함수가 등록되어 있지 않아도 오류를 일으키지 않습니다.

그리고 Action을 실행할 때 인자를 넘겨주면 됩니다.

👇Action대리자 클래스 전체코드

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using System;		//필수!

public class Action대리자 : MonoBehaviour
{	
	// 이 Action 대리자는 
	// int형식의 매개변수 2개를 가지고 있는 콜백함수를 등록할거야!
    public static event Action<int, int> myAction = (tempA, tempB) => { };   	
    											
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.W))
        {
            myAction(3,80);
        }
    }
}

이제 같은 데이터 형식을 가진 콜백함수를 만들어 등록해주면 됩니다.

👇구독자 전체 코드

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class 구독자 : MonoBehaviour
{
    void Start()
    {
        Action대리자.myAction += OnInputSapceBar;
    }

    void OnDestroy()
    {
        Action대리자.myAction -= OnInputSapceBar;
    }

    public void OnInputSapceBar(int a, int b)
    {
        Debug.Log($"{a},{b} 콜백함수 실행!");
    }
}

📃결과

0개의 댓글