在 Unity 中以编程方式创建动画?

Enr*_*ent 7 c# unity-game-engine

在我的游戏中,我有一个很大的装备目录:盔甲、武器和盾牌。这些之间的组合可能非常巨大。

在此输入图像描述

除此之外,玩家还可以选择在游戏中切换到不同的装甲武器组合。最后为了解决这个问题,我使用了以下对象结构。

在此输入图像描述

每当我切换武器时,我都会激活/停用必要的游戏对象。动画是这样设置的:

在此输入图像描述

现在,问题是创建动画。我首先考虑以编程方式预渲染所有组合,但我的目录非常庞大,它会创建 100 个(如果不是 1000 个)动画。所以我选择了不同的解决方案。一旦我知道玩家会选择什么装备,就可以在游戏时创建动画。为此,我创建了一个脚本来处理这个问题。问题是我一直在使用来自 的 API UnityEditor,现在我意识到构建将无法工作。具体来说是因为 2 个不同的类:EditorCurveBindingObjectReferenceKeyframe

这是我在创建动画时如何使用此类的几个片段:

static EditorCurveBinding GetEditorCurveBinding(string path = "")
{
    EditorCurveBinding spriteBinding = new EditorCurveBinding();
    spriteBinding.type = typeof(SpriteRenderer);
    spriteBinding.path = path;
    spriteBinding.propertyName = "m_Sprite";

    return spriteBinding;
}
Run Code Online (Sandbox Code Playgroud)
static ObjectReferenceKeyframe GetKeyframe(float time, Sprite sprite)
{
    ObjectReferenceKeyframe keyframe = new ObjectReferenceKeyframe();
    keyframe.time = time / FRAMERATE;
    keyframe.value = sprite;
    return keyframe;
}
Run Code Online (Sandbox Code Playgroud)

现在,曲线的问题,我想我设法解决了,用这段代码替换它,替换EditorCurveBindingAnimationCurve

AnimationClip clip = ...
AnimationCurve curve = new AnimationCurve();
clip.SetCurve(path, typeof(SpriteRenderer), "m_Sprite", curve);
Run Code Online (Sandbox Code Playgroud)

但我不知道如何为每个动画设置精灵。我认为使用curve.AddKey可能会有帮助,但我没有看到在那里添加精灵的方法。

我怎样才能重写该代码以避免使用UnityEditor

完整代码

Tom*_*zak 5

就我个人而言,我会完全避免内置动画器和动画,因为该工具的用途非常狭窄,即以预定义的方式对单个对象进行动画处理(例如:用于过场动画)。

题外话——表演

除此之外,玩家还可以选择在游戏中切换到不同的装甲武器组合。最后为了解决这个问题,我使用了以下对象结构。

您可能知道,这在内存方面效率非常低,并且会降低性能(禁用的对象仍然具有边际 CPU 开销)。并且会增加新对象的加载时间和实例化时间。

我可以使用 Animator 或 Animation 吗?

因为 Animator 没有 API 来访问它的内部结构和动画类型,总的来说,除了告诉它Play 或 Stop之外,你不能用它做任何事情。因为我知道你的动画是“基于精灵”而不是“基于变换”,所以任何理智的想法都是低效的!

我发誓反对的最佳解决方案如下:

  • 创建您要“动画化”的“触发点”
  • 基于触发点-改变精灵
    public class AnimationController : MonoBehaviour
    {
        public int AnimationIndex;
        public Sprite[] AnimationSprites;
        public SpriteRenderer SpriteRenderer;
        
        private void Update()
        {
            SpriteRenderer.sprite = AnimationSprites[AnimationIndex];
        }
    }
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

更好的解决方案?

由于我们已经需要具有管理精灵的自定义结构,因此我们可能想要优化整个事情,因为我们几乎没有使用 Animator 的任何功能,因此我们可以编写自定义控制器来替换本例中的 Animator。这应该会显着提高性能,因为 Animator 非常重!

    // MonoBehaviour is optional here
    public class SpriteRendererAnimationHandler
    {
        // More fields that would control the animation timing
        
        public Sprite[] AnimationSprites;
        public SpriteRenderer SpriteRenderer;
        
        public void OnAnimationUpdate(int index)
        {
            var resolvedIndex = ResolveIndex(index);
            SpriteRenderer.sprite = AnimationSprites[resolvedIndex];
        }

        private int ResolveIndex(int index)
        {
            // Resolve animation index to sprite array index
        }
    }

    // One controller per character - or global per game that synchronize all animations to locked FPS 12.
    public class AnimationController : MonoBehaviour
    {
        private List<SpriteRendererAnimationHandler> Handlers = new List<SpriteRendererAnimationHandler>();

        public void FixedUpdate()
        {
            foreach (var handler in Handlers)
            {
                // Calculate animation index
                int calculatedAnimationIndex = ...;
                handler.OnAnimationUpdate(calculatedAnimationIndex);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)