Search code examples
c#unity-game-enginestatic-methodsscriptable-object

How to reference static functions in Unity inspector


I have a scriptable object class Attack and created some assets from it.

In the Attack asset inspector, I want to be able to reference static functions from other classes, so when something happens, I can grab this static function referenced in Attack and execute it.

Is that possible?


I tried an asset called UltEvents (which claims to get this task done) but it didn't seem work in the newest Unity LTS.


Solution

  • UnityEvent should work, here's an example.

    Add a UnityEvent property as usual. The static RunTest method is the callback, the TestCallback is used to invoke the event.

    [CreateAssetMenu(menuName = "Attack")]
    public class Attack : ScriptableObject
    {
        public UnityEvent callback;
    
        public static void RunTest()
        {
            Debug.Log("Run Test");
        }
    
        public void TestCallback()
        {
            callback?.Invoke();
            Debug.Log("TestCallback");
        }
    }
    

    To select the callback in the inspector, there are 2 situations:

    1. You have an asset/instance associated with the callback, in this example because I define it in the Attack class, the instantiated scriptable object is the asset, you can directly select the callback from the inspector.

      inspector mode

    2. You don't have an asset/instance, you need to switch the inspector to the debug mode and manually populate the callback, see the 2nd screenshot. Pay attention to these fields: Target Assembly, Method Name, Mode, Call State. If the callback needs an argument, you should also fill in one of the Arguments field.

      debug mode

    Now if everything is OK, you can see "Run Test" in the console when you call TestCallback.


    Alternative 1

    The 2nd solution seems like a trick, you can imitate it in a customized way:

    [Serializable]
    public class MyStaticCallback
    {
        public string TypeName, MethodName;
        private Action _callback;
    
        public void Invoke()
        {
            _callback ??= (Action)Delegate.CreateDelegate(typeof(Action),
                Type.GetType(TypeName), MethodName);
            _callback?.Invoke();
        }
    }
    
    public class Attack : ScriptableObject
    {
        public MyStaticCallback callback;
    }
    

    Alternative 2

    Since the callback is static, you can solve this problem in a static way by defining derived classes for each kind of callbacks.

    public class Attack1 : Attack
    {
        public override void RunCallback() => AnyType.AnyStaticMethod();
    }