Ten*_*lah 0 c# unity-game-engine
我注意到GameObject.BroadcastMessage当目标被停用时这不起作用。如何调整它以使其在这种情况下工作。
显然,此EventOnMonoCallback.cs脚本附加到TOOTHPANEL,它将触发,OnEnable()但_Food游戏对象本身处于非活动状态。
似乎, BroadcastMessage 不适用于停用的孩子?
出于某种原因,TOOTHPANEL直到其他脚本将TOOTHPANEL游戏对象设置为true.
public class EventOnMonoCallback : MonoBehaviour
{
public enum MonoCallbackType
{
Awake,
Start,
Update,
OnEnable,
OnDisable,
OnDestroy
}
public MonoCallbackType Type;
public UnityEvent Do;
void Awake()
{
if (Type == MonoCallbackType.Awake)
{
Do.Invoke();
}
}
void Start()
{
if (Type == MonoCallbackType.Start)
{
Do.Invoke();
}
}
void Update()
{
if (Type == MonoCallbackType.Update)
{
Do.Invoke();
}
}
void OnEnable()
{
if (Type == MonoCallbackType.OnEnable)
{
Do.Invoke();
}
}
void OnDisable()
{
if (Type == MonoCallbackType.OnDisable)
{
Do.Invoke();
}
}
void OnDestroy()
{
if (Type == MonoCallbackType.OnDestroy)
{
Do.Invoke();
}
}
}
Run Code Online (Sandbox Code Playgroud)
在 Unity 中激活/停用和启用/禁用之间存在差异。您可以激活和停用游戏对象。您可以启用和禁用脚本。不要混淆这两者。
该BroadcastMessage功能将一直工作即使与目标功能的脚本是禁用的,但它将不工作的时候游戏对象该脚本连接到被停用。
有两种简单的解决方法:
1Invoke .使用Unity的内置函数。使用GetComponentsInChildren获取所有MonoBehaviour然后调用Invoke每个。即使 GameObject 被停用,调用也将始终有效。使用该GetComponentsInChildrentakeList作为参数的重载版本,以便每次调用时都不会产生垃圾。
List<MonoBehaviour> monoList = new List<MonoBehaviour>();
void BroadcastMessageExt(string methodName)
{
targetObj.GetComponentsInChildren<MonoBehaviour>(true, monoList);
for (int i = 0; i < monoList.Count; i++)
{
monoList[i].Invoke(methodName, 0);
}
}
Run Code Online (Sandbox Code Playgroud)
唯一不好的是你不能向它传递参数。有关解决方法,请参阅#2。
2 .做与#1相同的事情,但使用C#MethodInfo.Invoke函数而不是Unity API的版本。这应该让您将参数传递给您正在调用的函数。
List<MonoBehaviour> monoList = new List<MonoBehaviour>();
void BroadcastMessageExt(string methodName, object value = null, SendMessageOptions options = SendMessageOptions.RequireReceiver)
{
targetObj.GetComponentsInChildren<MonoBehaviour>(true, monoList);
for (int i = 0; i < monoList.Count; i++)
{
try
{
Type type = monoList[i].GetType();
MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance |
BindingFlags.NonPublic |
BindingFlags.Public |
BindingFlags.Static);
method.Invoke(monoList[i], new object[] { value });
}
catch (Exception e)
{
//Re-create the Error thrown by the original SendMessage function
if (options == SendMessageOptions.RequireReceiver)
Debug.LogError("SendMessage " + methodName + " has no receiver!");
//Debug.LogError(e.Message);
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以将这些转换为扩展方法,使它们更易于使用。