You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中DoTween多对象Tween动画优化:大量浮动文本性能提升技巧

优化Unity中DoTween浮动文本的性能技巧

针对你每秒生成50个浮动文本的场景,结合现有对象池+DoTween的实现,以下是具体的性能优化方案:

  • 缓存TextMeshProUGUI组件,避免重复GetComponent
    现有代码每次从对象池取出物体都调用GetComponent<TextMeshProUGUI>(),高频调用下会产生不必要的性能开销。建议给浮动文本物体添加一个自定义脚本,在初始化时缓存组件引用:

    public class FloatTextElement : MonoBehaviour
    {
        public TextMeshProUGUI TextComp;
    
        void Awake()
        {
            TextComp = GetComponent<TextMeshProUGUI>();
        }
    }
    

    后续调用时直接使用缓存的引用:

    public void FloatText(Vector3 pos, int value)
    {
        var obj = textObjQueue.Dequeue();
        obj.SetActive(true);
        obj.transform.position = pos;
        obj.GetComponent<FloatTextElement>().TextComp.text = value.ToString();
        TweenText(obj);
    }
    

    更极致的方式是在对象池初始化时,把组件引用和GameObject一起存储(比如用Tuple<GameObject, FloatTextElement>),彻底避免GetComponent调用。

  • 复用DoTween Tween实例,减少对象创建与GC
    每次调用DOMoveY都会生成新的Tween对象,高频场景下会累积GC开销。可以提前创建Tween并设置为不自动销毁,需要时重置参数复用:
    修改FloatTextElement脚本,内置复用的Tween:

    public class FloatTextElement : MonoBehaviour
    {
        public TextMeshProUGUI TextComp;
        private Tween _floatTween;
        private Action _onCompleteAction;
    
        void Awake()
        {
            TextComp = GetComponent<TextMeshProUGUI>();
            // 预创建Tween,关闭自动销毁并暂停
            _floatTween = transform.DOMoveY(0, 0.2f)
                .SetAutoKill(false)
                .Pause()
                .OnComplete(() => _onCompleteAction?.Invoke());
        }
    
        public void PlayAnimation(Vector3 startPos, float targetY, Action onComplete)
        {
            transform.position = startPos;
            _onCompleteAction = onComplete;
            // 重置Tween的起始与目标值,重启动画
            _floatTween.ChangeStartValue(startPos.y);
            _floatTween.ChangeEndValue(targetY);
            _floatTween.Restart();
        }
    }
    

    调用逻辑修改为:

    public void FloatText(Vector3 pos, int value)
    {
        var obj = textObjQueue.Dequeue();
        obj.SetActive(true);
        var element = obj.GetComponent<FloatTextElement>();
        element.TextComp.text = value.ToString();
        element.PlayAnimation(pos, pos.y + 1f, () => PoolObj(obj));
    }
    
  • 优化对象池实现,避免动态扩容开销
    确保对象池的初始容量足够覆盖峰值需求(比如预设100个实例),避免Queue动态扩容时的内存分配与移动。如果场景允许,用循环数组实现对象池,进一步降低队列操作的开销。

  • 关闭TextMeshProUGUI的冗余功能
    浮动文本通常不需要交互,关闭以下选项减少性能消耗:

    • 取消勾选Raycast Target(默认开启,会参与UI射线检测)
    • 关闭Rich Text(如果不需要富文本格式)
    • 确保Font Asset是静态引用,避免动态加载
  • 减少GC分配

    • value.ToString()会产生临时字符串,可缓存常用数字的字符串(比如用Dictionary<int, string>存储已转换的数值),或者使用StringBuilder复用(针对连续的数值转换场景)。
    • 避免在动画回调中创建匿名函数,上面的复用Tween方案已经把回调逻辑提前绑定,不会每次生成新的委托实例。
  • 简化动画计算

    • 使用线性缓动SetEase(Ease.Linear),比曲线缓动的计算开销更低。
    • 统一动画更新时机,比如用SetUpdate(UpdateType.Fixed)或SetUpdate(UpdateType.Late, true),让所有浮动文本的动画在同一帧更新,减少每帧的计算次数。

内容的提问来源于stack exchange,提问作者user18818953

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 14:36:19