如何通过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
相关产品推荐
相关产品推荐

