我注意到目标停用时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();
}
}
}
答案 0 :(得分:3)
在Unity中激活/停用和启用/禁用之间存在差异。您可以激活和停用GameObjects。您可以启用和禁用脚本。不要混淆这两个。
即使具有目标功能的脚本已停用,BroadcastMessage
功能也始终可以,但 时 工作脚本附加到的GameObject是已停用。
有两种简单的解决方法:
1 。使用Unity的内置Invoke
功能。使用GetComponentsInChildren
获取所有MonoBehaviour
,然后在每个Invoke
上调用GetComponentsInChildren
。即使游戏对象已停用,调用也将始终有效。使用以List
为参数的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);
}
}
重载版本,以便每次调用时都不会产生垃圾。
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);
}
}
}
唯一不好的是你无法传递参数。有关解决方法,请参阅#2 。
2 。与#1 相同,但使用C#MethodInfo.Invoke
函数代替Unity API中的版本。这应该允许您将参数传递给您正在调用的函数。
<label>
您可以将这些转换为extension methods,以使其更易于使用。
答案 1 :(得分:1)
你是对的,BroadcastMessage不适用于非活动对象。除了BroadcastMessage或SendMessage之外,您必须以某种方式启用它 如果您有对该对象的引用,则可以使用该对象启用。
如果你的目标只是在所有适用的孩子中调用一个函数,你可以尝试类似:
void Call_YOURFUNCTION_OnChildren(){
Transform[] transforms = GetComponentsInChildren<Transform>(true);
foreach (Transform t in transforms){
if (t.GetComponent<YOURCLASS>()){
t.GetComponent<YOURCLASS>().YOURFUNCTION();
}
}
}
注意:这假设您的所有对象都已转换