Messaging System In Unity

I am trying to create a messaging system in Unity in order to communicate things that happen in the game
with events. For now what I want to do is call an event when there is collision between the player’s bullets
and the enemies. While this actually works, the problem I am having is that since the script is using a messaging system, the exact same event is shared and so does the health for both enemies. So when I shoot on fore example, they all lose the same amount of health. Do you know any way to prevent that?


Code for Event Manager

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

[System.Serializable]
public class TypedEvent : UnityEvent<object> { }

public class EventManager : MonoBehaviour
{
    private Dictionary<string, UnityEvent> eventDictionary;

    private static EventManager eventManager; 
    // Start is called before the first frame update
    public static EventManager instance
    {
        get
        {
            if(!eventManager){
                eventManager = FindObjectOfType(typeof(EventManager)) as EventManager;
                if (!eventManager)
                {
                    Debug.LogError("There needs to be one active EventManager script on a GameObject in the scene");
                }
                else
                {
                    eventManager.Init();
                }
            }

            return eventManager;
        }
    }

    private void Init()
    {
        if(eventDictionary == null)
        {
            eventDictionary = new Dictionary<string, UnityEvent>();
        }
    }

    // Unity Action allows for dynamically calling multiple functions(they must have no arguments)
    public static void StartListening(string eventName,UnityAction listener)
    {
        UnityEvent thisEvent = null;
        if(instance.eventDictionary.TryGetValue(eventName,out thisEvent))
        {
            thisEvent.AddListener(listener);
        }
        else
        {
            thisEvent = new UnityEvent();
            thisEvent.AddListener(listener);
            instance.eventDictionary.Add(eventName, thisEvent);
        }
    }

    public static void StopListening(string eventName,UnityAction listener)
    {
        if (eventManager == null) 
            return;
        UnityEvent thisEvent = null;
        if(instance.eventDictionary.TryGetValue(eventName,out thisEvent))
        {
            thisEvent.RemoveListener(listener);
        }
    }

    public static void TriggerEvent(string eventName)
    {
        UnityEvent thisEvent = null;
        if(instance.eventDictionary.TryGetValue(eventName,out thisEvent))
        {
            thisEvent.Invoke();
        }
    }

}

Code for Enemy Health

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;

public class enemyDepleteHeatlh : MonoBehaviour
{
    private int enemyDamage;

    [SerializeField]
    private float maxHealth;

    [SerializeField]
    private float curHealth;

    private GameObject gun;

    [SerializeField]
    Slider healthBar;

    private UnityAction onTakeDamage;

    //public float damageToEnemy;

    // Start is called before the first frame update
    private void Awake()
    {
        gun = GameObject.FindGameObjectWithTag("gun");
        enemyDamage = gun.GetComponent<playerShooting>().damage;
        onTakeDamage = new UnityAction(OnTakeDamage);
        GameManager.enemyHealth = maxHealth;
        maxHealth = curHealth;
        curHealth = healthBar.value;
    }

    private void OnEnable()
    {
        EventManager.StartListening("TakeDamage", onTakeDamage);
    }

    private void OnDisable()
    {
        EventManager.StopListening("TakeDamage", onTakeDamage);
    }

    // Update is called once per frame
    void Update()
    {
        healthBar.value = this.curHealth;

        

        if(curHealth <= 0)
        {
            Destroy(this.gameObject);
        }

        if(curHealth > maxHealth)
        {
            this.curHealth = maxHealth;
        }

    }

    private void OnTakeDamage()
    {
        Debug.Log("Bullet has collided");
        this.curHealth -= enemyDamage;
    }

Enemy Health Emitter

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

public class enmyHeatlhdepleteEmitter : MonoBehaviour
{

    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.tag == "Enemy")
        {
            EventManager.TriggerEvent("TakeDamage");
        }
    }
}

Here is one quite simple way to do it:

You can make two different categories of events. For example Scene scoped and Local scoped events.
Difference would be that the Local scoped event have instance id number included int the event name. Then you can basically target that individual gameobject using the event name and instance number. So event could be “TakeDamage3123” where 3123 is the listening objects InstanceId. Instance id is not persistent but this will not matter because you are doing the registrations always when the objcet is instantiated. When you fire the event you need to get the targets instanceId to formulate the “fully qualified” event name.

There are other options to achieve this and also ready made frameworks available, but this one is quite simple to implement and use…