- Home /
Adding callbacks/events to an instantiated prefab
I am having a heck of a time with this one. I am using a "Spawner" which is not a Prefab to Instantiate a bunch of prefab bombs in my scene. When each bomb is diffused I need it to contact the spawner to let it know, Destroy it, and tell the player "You have one more left". Anyway, I was hoping this post would help (http://answers.unity3d.com/questions/421893/can-one-add-events-to-an-instantiated-object.html) but I receive the error
"Operator += cannot be applied to operand of type `UnityEngine.Events.UnityAction` and `void`"
Spawner.cs
void Spawn() {
...
aBomb = Instantiate (bomb, b[point].transform.position, b[point].transform.rotation);
aBomb.GetComponent<Disarm> ().BombDisarmed += this.BombDisarmed ();
...
}
void BombDisarmed() {
// Do Disarm Stuff
}
Attached to my bomb Prefab I have the Disarm.cs script.
Disarm.cs
public class Disarm : MonoBehaviour {
public event Action BombDisarmed;
public void DisarmBomb() {
if (BombDisarmed != null)
BombDisarmed ();
}
Obviously it's been trimmed but the basics are there. The gist is the same. Disarm.DisarmBomb() is getting called because the Audio and Particles are playing but now I just need it to call Spawner.BombDisarmed().
I've tried delegate's, UnityEvent's, and SendMessage, no luck. At this point I'm convinced I have no idea what I'm doing :)
I have NO IDEA why I can't get this working!! PLZ. HELP.
Answer by King-Klong · Oct 18, 2017 at 01:46 AM
I would stick with UnityEvent's with this. I'm not sure how you were using them before resorting to Actions, but I set up a small scene with a "spawner" that spawns one bomb and adds a listener to the UnityEvent that the Bomb controller has. The bomb controller will destroy itself after 3 seconds, then its OnDestroy() will trigger, invoking the BombDisarmed UnityEvent.
The was UnityEvents work is that you need to add listeners (which are your methods you want triggered), and then invoke the UnityEvent when you want it to.
In the spawner, i add my listener once I instantiate the bomb. Then in the bomb's OnDestroy, I invoke the UnityEvent, which the triggers HandleBombDisarmed() from the spawner.
If you want to go one step further, you can include the BombController in the listener by implementing your own UnityEvent class. Then you can access information about each bomb when they are disarmed. Here is the documentation on UnityEvent https://docs.unity3d.com/ScriptReference/Events.UnityEvent_1.html
Basically, you create a class that extends UnityEvent, and you do nothing else with it! You can see at the bottom of BombController that I created one (I added System.Serializable on it so that it shows up in the inspector, check it out!).
Then to use this new UnityEvent type, use it just like a normal UnityEvent, the only catch is, the listener you give it must have the same parameter type at , and when you call invoke(), it needs an argument with the same type as well.
I implemented both types of UnityEvents in the code. "BombDisarmed" is the normal way you asked for. And "CoolBombDisarmed" is the the going a step further and letting you pass the bomb object to the method.
(Sorry for the novel, I don't answer these much!)
SpawnerController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnerController : MonoBehaviour {
public GameObject BombPrefab;
// Use this for initialization
void Start () {
GameObject bomb = Instantiate(BombPrefab);
BombController bombController = bomb.GetComponent<BombController>();
bombController.BombDisarmed.AddListener(HandleBombDisarmed);
bombController.CoolBombDisarmed.AddListener(HandleCoolBombDisarmed);
}
public void HandleBombDisarmed()
{
Debug.Log("Bomb disarmed");
}
public void HandleCoolBombDisarmed(BombController bomb)
{
Debug.Log("Bomb disarmed. Its name was " + bomb.gameObject.name);
}
}
BombController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class BombController : MonoBehaviour {
public UnityEvent BombDisarmed;
public BombDisarmedEvent CoolBombDisarmed;
// Use this for initialization
void Start ()
{
StartCoroutine(BlowUp());
}
private void OnDestroy()
{
BombDisarmed.Invoke();
CoolBombDisarmed.Invoke(this);
}
private IEnumerator BlowUp()
{
yield return new WaitForSeconds(3.0f);
Destroy(this.gameObject);
}
}
[System.Serializable]
public class BombDisarmedEvent : UnityEvent<BombController>
{
}
SWEEET! Thanks for taking the time. I like putting it in the OnDestroy() also.
Answer by mo_hamid · Aug 30, 2020 at 08:00 PM
usually you don't need parentheses"()" when assigning delegates aBomb.GetComponent ().BombDisarmed += this.BombDisarmed; // and not += this.BombDisarmed()
Your answer
Follow this Question
Related Questions
How to reduce my script ? 0 Answers
Trying to find the highest number than add it to itself. 2 Answers
Point Counter Works Only Once! 1 Answer
How do I make do I make a variable go back to its original value for a spell system 1 Answer
How would i make it transform player.position =target.position? 2 Answers