Skip to Content

Implementing UnityEvents

November 16, 2018 • user

Unity has a custom implementation for delegates called Unity Events. Its features include serialization, an inspector element, and multiple delegates per object. When used properly, Unity Events provide a quick way to have game objects invoke methods from within the Unity Editor.

I discovered this feature while working on “Buff Master Status Effects.” I needed a fast and flexible way to have status effects run code through the inspector. Using Unity Events, I was able to develop an inspector window that could run compatible methods of any class attached to a game object. And thanks to the built in serialization, this component worked fabulously with prefabs.

Today we will look at a basic example that uses a UnityEvent object to define what happens on a physics collision. First we’ll set up the scene and build a simple script for the Unity Event. Then we’ll make a custom inspector to explore the default UI, prefabs, and serialization. By the end, we’ll be able to have our collision change anything in the scene with only a few clicks.

The scene
———

Lets start off with a blank scene. First add a large plane to act as the ground, then place a sphere 5 units above it. Both objects should have colliders, and the sphere needs a rigidbody. Finally add a Light to the sphere.  Your scene should look something like this:

If we play the scene, the sphere should fall and land on the plane.

Now Let’s add a script to the sphere called “EventCollision”. Add a public UnityEvent field, then invoke it when there’s a collision. Like so:

using UnityEngine;
using UnityEngine.Events;

public class EventCollision : MonoBehaviour {
  public UnityEvent unityEvent;
  void OnCollisionEnter(Collision other){
    unityEvent.Invoke();
  }
}

Now if we look at the sphere’s inspector, we see a field has been added for our UnityEvent.  Use the selectors to select the sphere, and change Light.intensity to 0. like so:

Now when we play the scene, the light turns off when the sphere collides with the plane!  We can change the UnityEvent inspector to invoke any method on any existing object in the scene. We can also add multiple calls to the same UnityEvent by clicking the plus button to add an entry. Try having the scene’s directional light turn off as well!

Custom Inspectors
—————–

Adding the default UnityEvent field to a custom inspector works the same as most other fields. Here is a basic custom inspector for the script we just made:

using UnityEditor;
using UnityEngine;
using UnityEngine.Events;

[CustomEditor(typeof(EventCollision), true)]
[CanEditMultipleObjects]
public class SphereEditor : Editor {
  SerializedProperty ue;
  void OnEnable(){
    ue = serializedObject.FindProperty("unityEvent");
  }

  public override void OnInspectorGUI(){
    serializedObject.Update();
    EditorGUILayout.HelpBox("Your UnityEvent", MessageType.Info);
    EditorGUILayout.PropertyField(ue,null);
    serializedObject.ApplyModifiedProperties();
  }
}

 

Now when the sphere is selected, there should be a “your UnityEvent” tip box, in addition to a UnityEvent editor like we saw before. This links the inspector to the UnityEvent object in the code. If we want to capture this information as it is passed to the object, we need to use reflection. In this example, we’ll change the tip box to show the parameter type for the selected method. Change OnInspectorGUI() by adding the three lines here:

public override void OnInspectorGUI(){
  serializedObject.Update();
  
  SerializedProperty list = ue.FindPropertyRelative("m_PersistentCalls.m_Calls");
  SerializedProperty spmode = list.GetArrayElementAtIndex(0).FindPropertyRelative("m_Mode");
  PersistentListenerMode mode = (PersistentListenerMode)spmode.enumValueIndex;

  EditorGUILayout.HelpBox(mode.ToString(), MessageType.Info);
  EditorGUILayout.PropertyField(ue,null);
  serializedObject.ApplyModifiedProperties();
}

 

The tip box in the inspector should now say “float” (if you’re still using our example event). We caught the “m_mode” property from the serialization of the UnityEvent. Since this is serialized data, we cast it back to its type to recreate the enum object. This same technique can be used to catch any serialized data in the UnityEvent.

 

With these simple tools we can dynamically run code with simple point and click editor settings. We also have learned UnityEvents are a powerful feature for quickly executing methods on demand.

Categories: Uncategorized

Leave a Reply

Your email address will not be published.

Bitnami