Unity C#如何不阻塞程序每秒给meters变量加1 Task.Delay不生效如何解决
问题根因
你在Unity里用Task.Delay不生效主要是两个原因:
- Unity逻辑默认跑在单主线程,如果你没有正确写await语法,Task.Delay不会阻塞当前逻辑,也不会触发后续的变量修改操作
- 就算写对了await,Task默认的调度器不一定在Unity主线程执行后续代码,直接修改绑定到MonoBehaviour的变量会有线程安全问题,甚至直接崩溃,Unity里做秒级定时优先用官方提供的协程或者Invoke方法,不要用Task.Delay
实现1秒给meters加1的两种方案
方案1:用InvokeRepeating(最简单,适合固定间隔执行的逻辑)
直接在Start方法里加一行代码即可:
void Start() { rb = GetComponent<Rigidbody2D>(); // 第一个参数是要执行的方法名,第二个是启动延迟(这里0表示启动就开始算),第三个是执行间隔(单位秒) InvokeRepeating(nameof(AddMeters), 0f, 1f); } // 单独抽出来的加1方法 void AddMeters() { meters += 1; }
如果后续要停止这个定时,调用CancelInvoke(nameof(AddMeters))即可。
方案2:用协程(更灵活,支持中途修改间隔、暂停等逻辑)
代码如下:
void Start() { rb = GetComponent<Rigidbody2D>(); // 启动协程 StartCoroutine(AddMetersCoroutine()); } IEnumerator AddMetersCoroutine() { // 死循环,只要组件激活就会一直执行 while(true) { meters += 1; // 等待1秒再执行下一次,不会阻塞主线程 yield return new WaitForSeconds(1f); } }
代码优化建议
- 不要把
Ymovement局部函数定义在Update里,挪到类级别,避免每次Update都创建新的委托对象,可读性也更高 - 你已经挂载了
Rigidbody2D,不要直接修改transform.position,会跳过重物理碰撞、重力计算,应该用rb.MovePosition方法,符合Unity物理框架的规范 - 遵循C#命名规范:类名、公共字段首字母大写,比如类名
movement改成Movement,movementSpeed改成MovementSpeed,方便后续维护 - 可以给公共数值字段加
[Range]特性,在Inspector面板直接拖动调整参数,比如[Range(1, 20)] public int MovementSpeed = 6;
优化后的完整代码
using UnityEngine; public class Movement : MonoBehaviour { [Range(1, 20)] public int MovementSpeed = 6; public int Meters; public double Speeding = 5; private Rigidbody2D _rb; void Start() { _rb = GetComponent<Rigidbody2D>(); InvokeRepeating(nameof(AddMeters), 0f, 1f); } void Update() { YMovement(); } void YMovement() { var verticalInput = Input.GetAxis("Vertical"); var newPosition = transform.position + new Vector3(0, verticalInput, 0) * Time.deltaTime * MovementSpeed; _rb.MovePosition(newPosition); } void AddMeters() { Meters += 1; } }
内容的提问来源于stack exchange,提问作者Isso
相关产品推荐
相关产品推荐

