我需要将事件从一个UnityEvent复制到另一个UnityEvent,因为一旦我想到这一点,我将在运行时将目标切换到另一个对象,到目前为止我所拥有的是:
MethodInfo info = UnityEventBase.GetValidMethodInfo (event1.GetPersistentTarget (i), event1.GetPersistentMethodName (i), Type.EmptyTypes);
UnityAction action = Delegate.CreateDelegate (typeof (UnityAction), info) as UnityAction;
event2.AddListener (action);
我得到ArgumentNullException: Argument cannot be null.
,如果我将Type.EmptyTypes
更改为new Type[] { typeof (float) }
,我会得到ArgumentException: method argument length mismatch
。
问题在于我不知道该放什么,因为我不知道它是什么类型(因为Unity Events可以发送bool,float等)。
Unity Docs不会涵盖这一点,所以希望其他人在过去取得成功。
答案 0 :(得分:0)
对于任何在未来遇到这种情况的人来说,这都有效:
MethodInfo info = UnityEventBase.GetValidMethodInfo (event1.GetPersistentTarget (i), event1.GetPersistentMethodName (i), new Type[] { typeof (float) });
UnityAction execute = () => info.Invoke (event1.GetPersistentTarget (i), new object[] { 180f });
event2.AddListener (execute);
它只是不会在检查器中公开复制的侦听器,因此仍在寻找完美的解决方案。
答案 1 :(得分:0)
这可以通过反射并递归复制UnityEvent类的每个值字段来实现。由于性能下降,我不会在运行时使用它,但是对于编辑器来说非常有用。我使用一个静态帮助器类和一个扩展来克隆列表。
ReflectionHelper.cs
using System;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
namespace CEUtilities.Helpers
{
public static class ReflectionHelper
{
/// <summary>
/// Gets all fields from an object and its hierarchy inheritance.
/// </summary>
/// <param name="type">The type.</param>
/// <param name="flags">The flags.</param>
/// <returns>All fields of the type.</returns>
public static List<FieldInfo> GetAllFields(this Type type, BindingFlags flags)
{
// Early exit if Object type
if (type == typeof(System.Object))
{
return new List<FieldInfo>();
}
// Recursive call
var fields = type.BaseType.GetAllFields(flags);
fields.AddRange(type.GetFields(flags | BindingFlags.DeclaredOnly));
return fields;
}
/// <summary>
/// Perform a deep copy of the class.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj">The object.</param>
/// <returns>A deep copy of obj.</returns>
/// <exception cref="System.ArgumentNullException">Object cannot be null</exception>
public static T DeepCopy<T>(T obj)
{
if (obj == null)
{
throw new ArgumentNullException("Object cannot be null");
}
return (T)DoCopy(obj);
}
/// <summary>
/// Does the copy.
/// </summary>
/// <param name="obj">The object.</param>
/// <returns></returns>
/// <exception cref="System.ArgumentException">Unknown type</exception>
private static object DoCopy(object obj)
{
if (obj == null)
{
return null;
}
// Value type
var type = obj.GetType();
if (type.IsValueType || type == typeof(string))
{
return obj;
}
// Array
else if (type.IsArray)
{
Type elementType = type.GetElementType();
var array = obj as Array;
Array copied = Array.CreateInstance(elementType, array.Length);
for (int i = 0; i < array.Length; i++)
{
copied.SetValue(DoCopy(array.GetValue(i)), i);
}
return Convert.ChangeType(copied, obj.GetType());
}
// Unity Object
else if (typeof(UnityEngine.Object).IsAssignableFrom(type))
{
return obj;
}
// Class -> Recursion
else if (type.IsClass)
{
var copy = Activator.CreateInstance(obj.GetType());
var fields = type.GetAllFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (FieldInfo field in fields)
{
var fieldValue = field.GetValue(obj);
if (fieldValue != null)
{
field.SetValue(copy, DoCopy(fieldValue));
}
}
return copy;
}
// Fallback
else
{
throw new ArgumentException("Unknown type");
}
}
}
}
UnityEventExtension.cs
using UnityEngine.Events;
using CEUtilities.Helpers;
namespace UnityEngine
{
public static class UnityEventExtension
{
/// <summary>
/// Clones the specified unity event list.
/// </summary>
/// <param name="ev">The unity event.</param>
/// <returns>Cloned UnityEvent</returns>
public static T Clone<T>(this T ev) where T : UnityEventBase
{
return ReflectionHelper.DeepCopy(ev);
}
}
}
然后可以像这样使用
this.OnStart = target.OnStart.Clone();
答案 2 :(得分:0)
我知道这很老,但是我一天中的大部分时间都在上网搜索以帮助我写点东西。我最终想到了可以使用的这个简单功能。这仅在编辑器中有效(但是之后又会在何时以其他方式进行此操作?)。
只要这是一个UnityEvent,它就会将具有其参数值(对象,字符串,整数,浮点数,空隙和布尔值)的统一事件从一个目标UnityEvent复制到另一个目标上的另一个事件。 / p>
欢迎每个人下载并根据需要进行构建。在这里查看: https://gist.github.com/wesleywh/1c56d880c0289371ea2dc47661a0cdaf