Home > Mobile >  How do I pass a function to be added to an event in Unity/C#?
How do I pass a function to be added to an event in Unity/C#?

Time:09-26

I am trying to create some inheritance class structures. After learning about events, I wanted to use them in some way. My intent is to have an abstract class that requires child classes to implement an OnDeath UnityEvent. I have tried using System.Func and Delegates, but neither have worked for me. I have included what I have tried, and the errors I received from trying those. Is there a way to have an abstracted function that lets me add a function to the event invoker? Am I just overcomplicating the process?

Using Delegates

EntityManager.cs with delegate

using UnityEngine;
using UnityEngine.Events;
using System;

public abstract class EntityManager : MonoBehaviour
{
    public EntityManager()
    {
        if (OnDeathEvent == null)
        {
            OnDeathEvent = new UnityEvent();
        }
        OnDeathEvent.AddListener(OnDeath);
    }
    public abstract bool IsAlive();
    public delegate void Function();
    public abstract void AddOnDeathListener(Function f);
    public abstract void OnDeath();
    public UnityEvent OnDeathEvent;
}
EnemyManager.cs with delegate

using System;

public class EnemyManager : EntityManager
{
    private Enemy _enemy;
    public Enemy Enemy { get => _enemy; set => _enemy = value; }

    private void Awake()
    {
        _enemy = new Enemy();

    }

    public override bool IsAlive()
    {
        return Enemy.IsAlive();
    }

    public void NextEnemy()
    {
        Enemy = new Enemy();
    }

    public override void OnDeath()
    {
        NextEnemy();
    }

    public override void AddOnDeathListener(Function f)
    {
        OnDeathEvent.AddListener(f);
        // cannot convert from 'EntityManager.Function' to 'UnityEngine.Events.UnityAction'
    }
}

Using Func

EntityManager.cs with Func

    public abstract void AddOnDeathListener(Func<object> f);

EnemyManager.cs with Func

    public override void AddOnDeathListener(Func<object> f)
    {
        OnDeathEvent.AddListener(f);
        // cannot convert from 'System.Func<object>' to 'UnityEngine.Events.UnityAction'
    }

CodePudding user response:

You should change the AddOnDeathListener method to take a UnityAction instead of a Func or anything else, because the AddListener method of the UnityEvent class takes a UnityAction delegate as an argument.

Your code in the abstract class should look like this:

 public abstract void AddOnDeathListener(UnityAction f);

   

CodePudding user response:

UnityEvents are not the same thing as C# Events in the System namespace, and UnityAction are not the same thing as C# Actions in the System namespace. But in your code you are mixing the two, with OnDeathEvent being in the UnityEngine.Events namespace and Func being in System. The reason you're having a compiler issue is that the UnityEvent.AddListener method takes a UnityAction argument, not a System.Func.

To fix, you will either need to switch your OnDeathEvent to being a C# event, or change your AddOnDeathListener to take UnityAction as an argument.

References:

https://docs.unity3d.com/ScriptReference/Events.UnityEvent.AddListener.html https://www.jacksondunstan.com/articles/3335

Code Sample:

public class CoolAbstract : TestMeAbstract
{
    UnityEvent SomeKindOfEvent;

    private void Start()
    {
        SomeKindOfEvent = new UnityEvent();

        AddOnDeathListener(() => { Debug.Log("Cool Abstraction"); });
    }

    private void Update()
    {
        if(Input.GetKeyDown(KeyCode.A))
        {
            SomeKindOfEvent.Invoke();
        }
    }

    public override void AddOnDeathListener(UnityAction ua)
    {
        SomeKindOfEvent.AddListener(ua);
    }
}
public abstract class TestMeAbstract : MonoBehaviour
{
    public abstract void AddOnDeathListener(UnityAction ua);
}
  • Related