我创建了一个自定义的PropertyDrawer,它为用我的属性修饰的某个字段显示同一脚本中引用的animator对象的参数。
这样,我就可以确保该字段的值在引用的动画制作器中是有效的参数。
这是我的代码:
public class AnimationParamAttribute : PropertyAttribute
{
public string AnimatorName { get; }
public AnimatorControllerParameterType[] AllowedParameters { get; }
public AnimationParamAttribute(string animatorName, params AnimatorControllerParameterType[] allowedParameters)
{
AnimatorName = animatorName;
this.AllowedParameters = allowedParameters;
}
}
public class AnimationController : MonoBehaviour
{
[SerializeField] private Animator animator;
[SerializeField, AnimationParam(nameof(animator), AnimatorControllerParameterType.Trigger)]
private string trigger;
[ContextMenu("Print value")]
private void PrintValue()
{
Debug.Log(trigger);
}
public void StartAnimation()
{
animator.SetTrigger(trigger);
}
}
我的PropertyDrawer
如下所示:
[CustomPropertyDrawer(typeof(AnimationParamAttribute))]
public class AnimationParamDrawer : PropertyDrawer
{
// Draw the property inside the given rect
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
AnimationParamAttribute a = (AnimationParamAttribute)attribute;
if (property.propertyType == SerializedPropertyType.String)
{
var targetObject = property.serializedObject.targetObject;
var field = targetObject.GetType().GetField(a.AnimatorName,
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
Animator animator = field?.GetValue(targetObject) as Animator;
if (animator == null)
{
EditorGUI.LabelField(position, label.text, "Select an animator.");
return;
}
var options = animator.parameters
.Where(parameter => a.AllowedParameters.Contains(parameter.type))
.Select(parameter => parameter.name)
.ToArray();
var s = string.Join(", ", options);
Debug.Log($"Options: {s}");
int selection = Array.IndexOf(options, property.stringValue);
Debug.Log($"{property.stringValue} is option {selection}");
if (selection < 0) selection = 0;
position = EditorGUI.PrefixLabel(position, label);
EditorGUI.BeginProperty(position, label, property);
EditorGUI.BeginChangeCheck();
selection = EditorGUI.Popup(position, selection, options);
if (EditorGUI.EndChangeCheck())
{
Debug.Log($"New selection: {selection}");
property.stringValue = options[selection];
}
EditorGUI.EndProperty();
}
else
EditorGUI.LabelField(position, label.text, "Use with string fields.");
}
}
代码运行良好,但由于某种原因,当我更改animator对象中的参数时,animator.parameters
返回一个空数组。
当我修改代码以强制Unity重新编译时,我得到了正确的值,代码再次工作。
这是什么原因,我该如何解决它?
2条答案
按热度按时间zmeyuzjn1#
在您的
AnimationPropertyDrawer
文件中,您希望“重新绑定”所有属性,以便我们看到最新的值。这是一个编辑器PropertyDrawer,所以我们开始期待一些神奇的功能是有代价的。幸运的是,这不会影响构建。试试看:
请注意额外的行
animator.Rebind ( );
。pgky5nke2#
Milan的答案解决了这个问题,但是如果
animator.parameters
所连接的gameobject是非活动的,它仍然会返回一个空数组。我已经找到了一个解决方案,似乎在this forum中一直有效。
基本上,我需要从
AnimatorController
而不是Animator
组件获取参数。这是我的更新代码: