Unity项目运行卡顿无报错,求排查触发检测脚本问题
问题分析与修复
卡顿根源
Update()每帧调用AddScore(),当touching为true时,while (touching == true)是死循环:循环内没有任何修改touching的逻辑,CPU会被这个循环完全占用,直接导致卡顿。- 同时每次循环都会启动
wait()协程,短时间内会生成海量协程,进一步加剧性能问题。
其他逻辑问题
- 缺少
OnTriggerExit2D方法,玩家离开碰撞体后touching不会被重置为false,逻辑永远停留在触发状态。 - 分数增加逻辑错误:用
while循环+协程无法实现"每秒加1分"的效果,反而会瞬间刷爆分数。 - 销毁对象的逻辑错误:
else分支每帧都会启动waiter()协程,会同时运行上百个销毁倒计时协程,导致重复销毁或性能浪费。
修复后的代码
using System.Collections; using UnityEngine; public class Trigger : MonoBehaviour { public GameObject targetToDestroy; bool isTouching = false; int score = 0; Coroutine scoreCoroutine; Coroutine destroyCoroutine; private void OnTriggerStay2D(Collider2D other) { Debug.Log("Touching"); isTouching = true; // 启动分数增加协程(确保同一时间只有一个协程运行) if (scoreCoroutine == null) { scoreCoroutine = StartCoroutine(IncreaseScorePerSecond()); } // 如果有销毁倒计时协程,立即停止 if (destroyCoroutine != null) { StopCoroutine(destroyCoroutine); destroyCoroutine = null; } } private void OnTriggerExit2D(Collider2D other) { Debug.Log("Not Touching"); isTouching = false; // 停止分数增加协程 if (scoreCoroutine != null) { StopCoroutine(scoreCoroutine); scoreCoroutine = null; } // 启动销毁倒计时协程(确保同一时间只有一个) if (destroyCoroutine == null) { destroyCoroutine = StartCoroutine(DestroyAfterDelay()); } } IEnumerator IncreaseScorePerSecond() { while (isTouching) { score++; Debug.Log($"当前分数: {score}"); yield return new WaitForSecondsRealtime(1); } } IEnumerator DestroyAfterDelay() { yield return new WaitForSecondsRealtime(2); Destroy(targetToDestroy); } }
修改说明
- 重命名变量提高可读性(比如
other改为targetToDestroy,避免和碰撞参数重名;touching改为isTouching)。 - 新增
OnTriggerExit2D方法,在玩家离开碰撞体时重置触发状态。 - 用
Coroutine变量管理协程,确保同一时间只有一个分数增加/销毁倒计时协程运行,避免重复启动。 - 将分数逻辑移到独立协程
IncreaseScorePerSecond中,通过协程的yield实现每秒加1分的效果,替代原有的死循环。 - 优化销毁逻辑:只有当玩家离开时才启动一次销毁倒计时,且如果玩家再次触发碰撞体,会立即停止销毁协程。
内容的提问来源于stack exchange,提问作者Rohan
相关产品推荐
相关产品推荐

