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

如何通过C#脚本使用Coroutine控制Unity Shader的Outline宽度

实现描边宽度循环往复自动变化的方案

没问题,咱们来给你的描边加上自动循环变化的效果!只需要修改你现有的Outline脚本,用协程来实现平滑的宽度过渡,同时避免和原来的逻辑冲突。

以下是修改后的完整代码,我会一步步解释关键改动:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Outline : MonoBehaviour
{
    // 可以自定义一次过渡的时长(比如从0到0.03需要几秒)
    public float transitionDuration = 2f;
    private Renderer rend;
    // 对应Shader里的Range范围
    private readonly float minWidth = 0.0f;
    private readonly float maxWidth = 0.03f;

    private void Start()
    {
        rend = GetComponent<Renderer>();
        // 启动自动循环的协程
        StartCoroutine(AnimateOutlineLoop());
    }

    // 核心协程:控制宽度在最小和最大值之间循环往复
    private IEnumerator AnimateOutlineLoop()
    {
        // 无限循环,直到物体被销毁或者协程被停止
        while (true)
        {
            // 从0过渡到0.03
            yield return StartCoroutine(LerpWidth(minWidth, maxWidth, transitionDuration));
            // 再从0.03过渡回0
            yield return StartCoroutine(LerpWidth(maxWidth, minWidth, transitionDuration));
        }
    }

    // 子协程:实现从起始宽度到目标宽度的平滑插值
    private IEnumerator LerpWidth(float startWidth, float targetWidth, float duration)
    {
        float timeElapsed = 0f;
        while (timeElapsed < duration)
        {
            // 计算当前进度(0到1)
            float progress = timeElapsed / duration;
            // 用Lerp实现平滑过渡,比直接改数值自然很多
            float currentWidth = Mathf.Lerp(startWidth, targetWidth, progress);
            // 设置Shader里的_Outline参数
            rend.material.SetFloat("_Outline", currentWidth);
            // 累加时间,每帧更新
            timeElapsed += Time.deltaTime;
            // 等待下一帧再继续
            yield return null;
        }
        // 最后确保宽度准确设置到目标值,避免因为浮点误差有偏差
        rend.material.SetFloat("_Outline", targetWidth);
    }

    // 保留手动设置宽度的方法,方便你需要手动控制时调用
    public void SetOutLineWidth(float width)
    {
        // 限制宽度在Shader允许的范围内,防止超出Range报错
        float clampedWidth = Mathf.Clamp(width, minWidth, maxWidth);
        rend.material.SetFloat("_Outline", clampedWidth);
    }
}

关键改动说明:

  • 移除了原有的Update方法:原来的Update每帧都设置宽度,会和协程的自动控制冲突,所以直接删掉就好。
  • 添加了过渡时长参数:你可以在Inspector面板调整transitionDuration,比如设为1就是1秒完成一次从0到0.03的过渡,数值越小动画越快。
  • 拆分协程逻辑:把循环控制和平滑过渡拆成两个协程,代码更清晰,以后要改逻辑也方便。
  • 用Mathf.Lerp做平滑插值:让宽度变化是渐变的,不会突然跳变,视觉效果更舒服。
  • 增加范围限制:手动设置宽度时用Mathf.Clamp确保不会超出Shader里Range(0.0, 0.03)的范围。

额外扩展(可选):

如果需要随时暂停或重启动画,可以加这两个方法:

private Coroutine _outlineAnimationCoroutine;

public void StartOutlineAnimation()
{
    if (_outlineAnimationCoroutine == null)
    {
        _outlineAnimationCoroutine = StartCoroutine(AnimateOutlineLoop());
    }
}

public void StopOutlineAnimation()
{
    if (_outlineAnimationCoroutine != null)
    {
        StopCoroutine(_outlineAnimationCoroutine);
        _outlineAnimationCoroutine = null;
    }
}

这样你就可以通过代码调用StartOutlineAnimation()和StopOutlineAnimation()来控制动画的启停了。

替换完脚本后,运行游戏就能看到描边宽度自动循环变化的效果啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:41:25