inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

절대강좌! 유니티 6 - TPS 게임으로 배우는 유니티 마스터클래스

BehaviorGraph - ScriptableObject를 활용한 Event Chanel

Player에 Event 연결 관련 질문

94

Rio Song

작성한 질문수 5

0

안녕하세요.

image.pngimage.png

 

위와 같이 정상적으로 Event Channel를 만들고, Scriptable Object도 생성 후 연결한 상황입니다.

그런데, PlayerController에서 Event를 연결시켜야 하는데, Event가 없습니다.

image.png

지우고 다시 해봐도 Event가 나타나지 않는데, 혹시 제가 잘못한 부분이 있을까요?

C# unity

답변 2

0

이재현

안녕하세요. Rio Song님,

확인해보니 최신 BehaviorGraph 1.0.10에서는 Event 프로퍼티를 직접 접근하는 방식이 변경되었습니다. ㅠㅠ

우선 아래 코드와 같이 변경해서 적용해주세요. 아직 강의 원본 프로젝트에 적용시켜 보지 않아서 정확하지는 않을 수 있습니다.

 

원본 강의 프로젝트를 업그레이드 하고 테스트해 본 후 다시 말씀드리겠습니다.

 

    [SerializeField] private ApplyDamageToPlayer _applyDamageDamageToPlayer;
    private Action<Transform, float> _handler;   
    
    private void OnEnable()
    {
        _handler = OnPlayerDamaged;
        _applyDamageDamageToPlayer.RegisterListener(_handler);
    }


    private void OnDisable()
    {
        _applyDamageDamageToPlayer.UnregisterListener(_handler);
    }

0

Rio Song

https://docs.unity3d.com/Packages/com.unity.behavior@1.0/manual/bind-c.html#c-binding-using-event-channel-asset

공식 문서에는 아직도 Event가 있어서 제가 잘못한 것인 줄 알았습니다.


일단 알려주신 대로 수정하고 실행하니 데미지가 들어오지 않습니다.

image.png

RegisterListener 메서드를 찍어보니, m_Event에 등록이 안되고 있는 것 같은데 저도 조금 더 해결책을 찾아보겠습니다.

1

이재현

우선 ApplyDamageToPlayer.cs 코드를 다음과 같이 수정하시면 Event += OnPlayerDamaged; 코드는 동작하실 겁니다. 네부적으로 handler를 등록하고 Event를 Invoke하도록 되어 있습니다. 이번에 변경되 방식을 좀 더 간단히 처리하는 부분은 좀 더 테스트 완료 후 말씀드리겠습니다.

 

public partial class ApplyDamageToPlayer : EventChannelBase
{
    public delegate void ApplyDamageToPlayerEventHandler(Transform Player, int Damage);
    public event ApplyDamageToPlayerEventHandler Event; 

    public void SendEventMessage(Transform Player, int Damage)
    {
        Event?.Invoke(Player, Damage);
    }

    public override void SendEventMessage(BlackboardVariable[] messageData)
    {
        BlackboardVariable<Transform> PlayerBlackboardVariable = messageData[0] as BlackboardVariable<Transform>;
        var Player = PlayerBlackboardVariable != null ? PlayerBlackboardVariable.Value : default(Transform);

        BlackboardVariable<int> DamageBlackboardVariable = messageData[1] as BlackboardVariable<int>;
        var Damage = DamageBlackboardVariable != null ? DamageBlackboardVariable.Value : default(int);

        Event?.Invoke(Player, Damage);
    }

    public override Delegate CreateEventHandler(BlackboardVariable[] vars, System.Action callback)
    {
        ApplyDamageToPlayerEventHandler del = (Player, Damage) =>
        {
            BlackboardVariable<Transform> var0 = vars[0] as BlackboardVariable<Transform>;
            if(var0 != null)
                var0.Value = Player;

            BlackboardVariable<int> var1 = vars[1] as BlackboardVariable<int>;
            if(var1 != null)
                var1.Value = Damage;

            callback();
        };
        return del;
    }

    public override void RegisterListener(Delegate del)
    {
        Event += del as ApplyDamageToPlayerEventHandler;
    }

    public override void UnregisterListener(Delegate del)
    {
        Event -= del as ApplyDamageToPlayerEventHandler;
    }
}

0

Rio Song

감사합니다.

override 하는 방법이 있었군요.

1

이재현

BehaviorGraph 이벤트의 Base 클래스가 EventChannel 로 변경되었기에 앞서 보내드린 코드 보다 좀 더 간결한 코드를 보내드립니다.

블랙보드변수를 인자로 전달 받기 때문에 따로 찾아오는 번거로움은 면할 것 같네요.

아직 자료가 별로 없어서 정확한 방법인지는 확신할 수는 없지만 또 다른 방식이 있다면 답글 드리겠습니다. 알려주셔서 감사합니다.

 

public sealed partial class ApplyDamageByPlayer : EventChannel<Transform, int>
{
    public delegate void EventHandler(Transform Player, int Damage);
    public event EventHandler Event;

    public void SendEventMessage(Transform Player, int Damage)
    {
        Event?.Invoke(Player, Damage);
    }

    public override void RegisterListener(Delegate del)
    {
        Event += del as EventHandler;
    }

    public override void UnregisterListener(Delegate del)
    {
        Event -= del as EventHandler;
    }    
}

 

0

Rio Song

앞에 알려주신 긴 코드는 정상 동작하지만, 뒤에 알려주신 코드는 Event가 정상적으로 등록이 된 것 같은데, 데미지가 안들어 오는 문제가 있습니다.

image.png

Debug로 짧은 코드의 public void SendEventMessage에 breakpoint를 걸어봤지만, 해당 메서드가 호출되지 않습니다.

 

아래와 같이 override void SendEventMessage를 추가해야 정상 동작하는 것을 확인하였습니다.

확인해보니 override된 SendEventMessage 메서드가 없으면, EventChannel의 SendEventMesage가 호출되면서 EventChannel의 m_Event?.Invke()가 실행되면서 발생한 문제인 것 같습니다.

 

public sealed partial class ApplyDamageToPlayer : EventChannel<Transform, float>
{
    public delegate void EventHandler(Transform Player, float Damage);
    public event EventHandler Event;

    public void SendEventMessage(Transform Player, float Damage)
    {
        Event?.Invoke(Player, Damage);
    }

    public override void SendEventMessage(BlackboardVariable[] messageData)
    {
        var PlayerBlackboardVariable = messageData[0] as BlackboardVariable<Transform>;
        var Player = PlayerBlackboardVariable != null ? PlayerBlackboardVariable.Value : default;

        var DamageBlackboardVariable = messageData[1] as BlackboardVariable<float>;
        float Damage = DamageBlackboardVariable != null ? DamageBlackboardVariable.Value : default;

        Event?.Invoke(Player, Damage);
    }

    public override void RegisterListener(Delegate del)
    {
        Event += del as EventHandler;
    }

    public override void UnregisterListener(Delegate del)
    {
        Event -= del as EventHandler;
    }
}

0

이재현

질문 주신 후 기존 코드에서 이벤트채널을 새로 만들어서 테스트를 했습니다. 확인해보니 처음 만든 이벤트채널은 EventChannelBase 클래스를 기반으로 제가 드렸던 긴 코드가 있는 상태여서 SendEventMessage가 override 된 상태여서 짧은 코드가 동작했었던 것으로 추축해봅니다. 기존의 긴 코드를 삭제한 후 에는 Rio Song 님과 같이 이벤트가 호출되지 않았습니다. 알려주셔서 감사합니다.

0

인프런 AI 인턴

안녕하세요, 인프런 AI 인턴입니다. Rio Song님.

질문해 주신 내용은 Unity에서 ScriptableObject를 활용하여 Event Channel을 만들고 이를 PlayerController와 연결하는 과정에서 발생한 문제에 대한 것입니다. Event 시스템을 제대로 설정하기 위해 몇 가지 확인해야 할 사항이 있습니다.

Event Channel 확인 사항

  1. ScriptableObject의 설정:

    • ScriptableObject가 올바르게 생성되고, 원하는 이벤트 타입(Event Channel)이 포함되어 있는지 확인하세요. ApplyDamageToPlayer를 제대로 설정하셨는지 파일 이름과 타입을 검토해 보세요.
  2. SerializeField 적용 여부:

    • PlayerController 스크립트에 [SerializeField]로 선언한 applyDamageToPlayer 변수가 에디터에서 올바르게 할당되어 있는지 확인합니다. 변수 이름이나 참조가 맞는지 살펴보세요.
  3. 이벤트 등록:

    • OnEnable()OnDisable() 메서드에서 이벤트를 올바르게 등록하고 해제하는지 확인해주세요. 일반적으로, Event 속성을 사용하여 이벤트를 구독 및 해제합니다. 아래와 같은 형태로 구현이 되어 있는지 확인해 보세요:
   private void OnEnable()
   {
       applyDamageToPlayer.Event += OnDamageEvent;
   }

   private void OnDisable()
   {
       applyDamageToPlayer.Event -= OnDamageEvent;
   }

   private void OnDamageEvent()
   {
       // Event 처리 로직
   }
  1. 타입 확인:
    • ApplyDamageToPlayer의 타입이 올바른지, 특히 Event 속성이 실제로 정의되어 있는지 살펴보세요. 타입에 적절한 이벤트 프로퍼티나 메서드가 포함되어 있는지 코드와 파일을 검토하는 것이 중요합니다.

유사한 질문 참조

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

Dictionary Key를 int에서 string으로 변경한 이유에 대한 문의

0

12

1

프로젝트 질문 문의

0

41

1

UI 기능 관련 질문이 있습니다!

0

31

2

03-01 (16. CharacterController)

0

27

2

TLS 질문드립니다.

0

39

2

prefab 관련 문의

0

66

1

Bullet이 방향 문제가 있어요.

0

108

3

딜레이를 주고 싶을 때 코루틴을 사용하는 이유

0

106

2

Spider 사망 시 두 번 폭발관련

0

101

2

Barrel에 IDamagable 적용 관련 질문

0

74

2

Stun 로직 관련해서 문제가 발생합니다.

0

189

2

Bullet, AimDot 코드 질문

1

135

2

안녕하세요 이벤트 버스 패턴에 대해서 궁금한게 있어서요

0

210

2

선생님 궁금한게 있는데요

0

166

2

비헤이비어 그래프 방식이요

1

136

2

콜백 함수, garbage colleection에 대해

0

119

1

스크립터블 오브젝트에 대해 질문이 있습니다

0

125

1

오디오 관련해서 질문 있습니다.

0

150

2

[질문] ScriptableObject 를 활용한 이벤트 버스 관련 질문이 있습니다.

0

279

1

[질문] Component 이름 관련해서 질문이 있습니다.

0

124

1

[질문] Custom NavMesh Link 관련해서 궁금한게 있습니다.

0

104

2

[질문] Scriptable Object르 이용한 메모리 최적화 관련 질문이 있습니다.

0

216

2

강사님~ 오디오 파일 관련해서 질문있습니다!

0

180

2

IDamagable 활용

0

167

1