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

Unity中能否在协程内修改按引用传递的数值?

Unity协程实现Float平滑过渡的简洁方案

针对你遇到的ref参数在协程和Lambda中受限、C#版本不支持ref字段的问题,这里提供一个无需繁琐委托的解决方案——用轻量引用包装类间接持有需要修改的float值,完美兼容Unity主流C#版本。

1. 定义Float引用包装类

先写一个极简的引用类型,用来包裹要动画的float值:

public class FloatRef
{
    public float Value;

    public FloatRef(float initialValue = 0f)
    {
        Value = initialValue;
    }
}

2. 实现MonoBehaviour扩展协程方法

写一个通用的扩展方法,处理平滑过渡逻辑:

using UnityEngine;
using System.Collections;

public static class CoroutineExtensions
{
    // 基础线性过渡
    public static IEnumerator LerpFloat(this MonoBehaviour mono, FloatRef targetRef, float targetValue, float duration)
    {
        float startValue = targetRef.Value;
        float elapsed = 0f;

        while (elapsed < duration)
        {
            elapsed += Time.deltaTime;
            float t = Mathf.Clamp01(elapsed / duration);
            targetRef.Value = Mathf.Lerp(startValue, targetValue, t);
            yield return null;
        }

        // 确保最终值精确到位
        targetRef.Value = targetValue;
    }

    // 可选:支持自定义缓动曲线的重载
    public static IEnumerator LerpFloat(this MonoBehaviour mono, FloatRef targetRef, float targetValue, float duration, AnimationCurve easeCurve)
    {
        float startValue = targetRef.Value;
        float elapsed = 0f;
        easeCurve ??= AnimationCurve.Linear(0, 0, 1, 1);

        while (elapsed < duration)
        {
            elapsed += Time.deltaTime;
            float t = Mathf.Clamp01(elapsed / duration);
            targetRef.Value = Mathf.Lerp(startValue, targetValue, easeCurve.Evaluate(t));
            yield return null;
        }

        targetRef.Value = targetValue;
    }
}

3. 实际使用示例

在你的业务脚本中直接调用:

public class Example : MonoBehaviour
{
    // 用FloatRef包裹需要动画的float
    private FloatRef _moveSpeed = new FloatRef(2f);

    void Start()
    {
        // 启动协程:2秒内把_moveSpeed从2过渡到8
        StartCoroutine(this.LerpFloat(_moveSpeed, 8f, 2f));

        // 可选:用缓动曲线实现非线性过渡
        // AnimationCurve ease = AnimationCurve.EaseInOut(0, 0, 1, 1);
        // StartCoroutine(this.LerpFloat(_moveSpeed, 8f, 2f, ease));
    }

    void Update()
    {
        // 直接使用_moveSpeed.Value即可拿到实时动画后的值
        transform.Translate(Vector3.forward * _moveSpeed.Value * Time.deltaTime);
    }
}

方案优势

  • 避开了Unity协程不支持ref参数的限制,也不需要依赖高版本C#的ref字段特性
  • 使用方式简洁,仅需用FloatRef包装目标float,无需每次写繁琐的委托逻辑
  • 支持扩展缓动曲线,满足不同动画需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 06:52:16