帧同步的方案下,逻辑层需要与渲染帧解耦,比如一秒固定30帧。这个还算比较容易实现的,重点是动画的表现也需要同步。
如果需要动画同步,则不能使用unity动画自驱,而是需要用进度控制。
unity开放了这种功能的接口,使用animator.Play(AnimName, AnimLayerIndex, progress);来调用。
实现功能的脚本如下:
cs
using UnityEngine;
public class MoveAnimationController : MonoBehaviour
{
[Tooltip("角色的Animator组件")]
public Animator animator;
[Tooltip("当前动画进度(0~1,可手动拖曳测试)")]
[Range(0f, 1f)] public float moveProgress = 0f;
// 动画状态的层索引(默认是0,只有一个层时不用改)
public int AnimLayerIndex = 0;
// 动画名称(要和Animator中的状态名一致)
public string AnimName = "Move";
private void Start()
{
// 初始化:如果没赋值Animator,自动获取
if (animator == null)
{
animator = GetComponent<Animator>();
}
// 冻结动画速度(关键:禁止Animator自动播放)
animator.speed = 0f;
}
private void Update()
{
// 实时更新动画进度(你可以在任何地方修改moveProgress,比如逻辑层计算后赋值)
UpdateMoveAnimationProgress(moveProgress);
}
/// <summary>
/// 控制Move动画的进度
/// </summary>
/// <param name="progress">0~1的进度值</param>
public void UpdateMoveAnimationProgress(float progress)
{
// 钳制进度在0~1之间,防止异常
progress = Mathf.Clamp01(progress);
// 核心API:播放指定动画,并设置归一化时间(进度)
// 参数1:动画名称;参数2:层索引;参数3:归一化时间(0=开头,1=结尾)
animator.Play(AnimName, AnimLayerIndex, progress);
// 再次确认冻结速度(防止其他逻辑修改了speed)
animator.speed = 0f;
}
}
实现效果如下:

通过拖动可以看到动画的变化。