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");
}
}
}