- Home /
SendMessage() to inactive object?
how do I gameObject.SendMessage() to an inactive game object?
Answer by Bunny83 · Jan 02, 2013 at 01:50 AM
Simple answer: You can't.
A deactivated gameobject does not receive any messages from Unity. Deactivated equals "not there" for the engine.
Which is unfortunate -- there really ought to be Send$$anonymous$$essageOptions.IncludeInactive.
You can still call methods on a script, inactive means that the Update/FixedUpdate and other $$anonymous$$onoBehaviour methods and callbacks are not run but if you have the reference to the script then you can call any method since the object is in memory.
Right, you can for example use an interface on the target class and use GetComponent with the interface. Of course you can't use the default generic GetComponent as it has a constraint to "Component". However, you can add an extension method that does the same but also works with interfaces:
public static T GetInterface<T>(this GameObject aObj)
{
return (T)aObj.GetComponent(typeof(T));
}
public static T GetInterface<T>(this Component aObj)
{
return (T)aObj.GetComponent(typeof(T));
}
With those in a static class you can do this:
public interface I$$anonymous$$yInterface
{
void $$anonymous$$yInterface$$anonymous$$ethod();
}
// [...]
public class Some$$anonymous$$onoBehaviour : $$anonymous$$onoBehaviour, I$$anonymous$$yInterface
{
// [...]
public void $$anonymous$$yInterface$$anonymous$$ethod()
{
Debug.Log("Yay");
}
}
// [...]
// Somewhere else:
I$$anonymous$$yInterface mi = someGameObject.GetInterface<I$$anonymous$$yInterface>();
if (mi != null)
mi.$$anonymous$$yInterface$$anonymous$$ethod();
Another alternative is to use reflection on your own ;) Iterate through all components inherited from $$anonymous$$onoBehaviour and check if they contain a method with the given name.
Answer by gsabran · Dec 03, 2015 at 08:29 AM
Here is how I solved it, inspired by @Bunny83:
using UnityEngine;
using System;
using System.Reflection;
namespace MessengerExtensions {
/// <summary>
/// Broadcast messages between objects and components, including inactive ones (which Unity doesn't do)
/// </summary>
public static class MessengerThatIncludesInactiveElements {
/// <summary>
/// Determine if the object has the given method
/// </summary>
private static void InvokeIfExists(this object objectToCheck, string methodName, params object[] parameters)
{
Type type = objectToCheck.GetType();
MethodInfo methodInfo = type.GetMethod (methodName);
if (type.GetMethod (methodName) != null) {
methodInfo.Invoke(objectToCheck, parameters);
}
}
/// <summary>
/// Invoke the method if it exists in any component of the game object, even if they are inactive
/// </summary>
public static void BroadcastToAll(this GameObject gameobject, string methodName, params object[] parameters) {
MonoBehaviour[] components = gameobject.GetComponents<MonoBehaviour> ();
foreach (MonoBehaviour m in components) {
m.InvokeIfExists(methodName, parameters);
}
}
/// <summary>
/// Invoke the method if it exists in any component of the component's game object, even if they are inactive
/// </summary>
public static void BroadcastToAll(this Component component, string methodName, params object[] parameters) {
component.gameObject.BroadcastToAll (methodName, parameters);
}
/// <summary>
/// Invoke the method if it exists in any component of the game object and its children, even if they are inactive
/// </summary>
public static void SendMessageToAll(this GameObject gameobject, string methodName, params object[] parameters) {
MonoBehaviour[] components = gameobject.GetComponentsInChildren<MonoBehaviour> (true);
foreach (MonoBehaviour m in components) {
m.InvokeIfExists(methodName, parameters);
}
}
/// <summary>
/// Invoke the method if it exists in any component of the component's game object and its children, even if they are inactive
/// </summary>
public static void SendMessageToAll(this Component component, string methodName, params object[] parameters) {
component.gameObject.SendMessageToAll (methodName, parameters);
}
/// <summary>
/// Invoke the method if it exists in any component of the game object and its ancestors, even if they are inactive
/// </summary>
public static void SendMessageUpwardsToAll(this GameObject gameobject, string methodName, params object[] parameters) {
Transform tranform = gameobject.transform;
while (tranform != null) {
tranform.gameObject.BroadcastToAll(methodName, parameters);
tranform = tranform.parent;
}
}
/// <summary>
/// Invoke the method if it exists in any component of the component's game object and its ancestors, even if they are inactive
/// </summary>
public static void SendMessageUpwardsToAll(this Component component, string methodName, params object[] parameters) {
component.gameObject.SendMessageUpwardsToAll (methodName, parameters);
}
}
}
Then, provided that I have using MessengerExtensions;
included at the top of my file, I can call BroadcastToAll
, SendMessageToAll
and SendMessageUpwardsToAll
on game objects and components. They work as their sibling methods, but should trigger inactive components and objects.
I tried running this. It didn't work at all and I don't know why. One invocation just crashed Unity. It's a really cool idea and it would have been awesome if it had worked.
Answer by aphenine · Aug 18, 2016 at 02:05 PM
Another way to do this is:
https://unity3d.com/learn/tutorials/topics/scripting/events-creating-simple-messaging-system
Because you register to use an event, it's bulkier and has more code, but it works beautifully even when the item is disabled.
Unfortunately, you can't send any arguments in (although there are templated versions of UnityEvents, so it probably could be modified).
Your answer
