如何获取AnimationClip指定帧下GameObject自定义组件属性值?
解决方案:提取动画帧中自定义组件的字段值
问题背景
我有个名为HitboxObject的GameObject,挂载了Hitbox组件,该组件包含公开的Vector2变量offset。某段AnimationClip会修改这个offset的值,我需要在非运行时、动画未播放的状态下,通过脚本获取不同帧对应的offset值。尝试用AnimationClip.SampleAnimation()方法失败,因为该方法仅支持Transform的位置、旋转等内置属性,无法读取自定义脚本字段。
原测试代码
[SerializeField] private AnimationClip attackBoxAnimaiton; [SerializeField] private GameObject hitbox; [SerializeField] private int frameIndex; void Start() { // 采样指定帧的动画 attackBoxAnimaiton.SampleAnimation(hitbox, GetTimeFromFrame(frameIndex)); // 提取目标对象数据 Hitbox hitboxComponent = hitbox.GetComponent<Hitbox>(); Vector2 offset = hitboxComponent.m_offset; Vector3 position = hitbox.transform.position; Quaternion rotation = hitbox.transform.rotation; // 输出数据 Debug.Log("Name: " + hitbox.transform.name); Debug.Log("Offset at frame " + frameIndex + ": " + offset); Debug.Log("Position at frame " + frameIndex + ": " + position); Debug.Log("Rotation at frame " + frameIndex + ": " + rotation); } private float GetTimeFromFrame(int frame) { float frameRate = attackBoxAnimaiton.frameRate; Debug.Log(frameRate); return frame / frameRate; }
Inspector面板截图

可行方案:直接解析动画曲线数据
要获取自定义字段的动画数据,不需要采样对象,直接解析AnimationClip中的动画曲线即可:
- 遍历动画剪辑的绑定曲线:找到对应Hitbox组件
offset字段的动画曲线 - 根据帧索引计算对应时间点:用帧索引除以帧率得到时间
- 从曲线中读取对应时间点的值:分别获取x和y轴的曲线值,组合成Vector2
实现代码
using UnityEngine; public class AnimationCurveReader : MonoBehaviour { [SerializeField] private AnimationClip attackBoxAnimation; [SerializeField] private int frameIndex; void Start() { Vector2 offsetAtFrame = GetOffsetAtFrame(attackBoxAnimation, frameIndex); Debug.Log($"Frame {frameIndex} offset value: {offsetAtFrame}"); } private Vector2 GetOffsetAtFrame(AnimationClip clip, int frame) { float time = frame / clip.frameRate; Vector2 result = Vector2.zero; // 遍历所有绑定的动画曲线 foreach (EditorCurveBinding binding in AnimationUtility.GetCurveBindings(clip)) { // 匹配Hitbox组件的offset字段(注意字段名要和动画里的路径一致) if (binding.type == typeof(Hitbox)) { // 获取x和y轴的曲线 AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, binding); if (binding.propertyName.EndsWith(".x")) { result.x = curve.Evaluate(time); } else if (binding.propertyName.EndsWith(".y")) { result.y = curve.Evaluate(time); } } } return result; } }
注意事项
- 确保动画剪辑中确实绑定了Hitbox组件的
offset字段,字段名要完全匹配(包括大小写) - 该方法无需运行时播放动画,在编辑模式下也能执行(可以把Start方法换成
[ContextMenu("Get Offset At Frame")]标签,直接在Inspector中调用) - 如果是在编辑模式下使用,需要引入
UnityEditor命名空间,发布时用条件编译包裹:#if UNITY_EDITOR ... #endif
内容的提问来源于stack exchange,提问作者GEM
相关产品推荐
相关产品推荐

