Unity开发FlappyBird如何实现开局1秒临时修改gravityScale后恢复
问题根因
你的计时器无法正常生效的核心原因是gravityTimer被声明为PlayerHalt方法的局部变量,每次方法被调用时(每帧都会执行一次),变量都会被重置为0f,永远无法累加到1秒阈值,因此重力始终被锁在0.2。
常见疑问解答
- 计时器是否可以在非Update的函数中正常运行?
可以,只需满足两个条件:- 存储计时累计值的变量必须是类级别的成员字段,不能是方法内的局部变量,否则每次调用方法都会重置计时值。
- 计时逻辑需要能逐帧推进:要么承载逻辑的方法被逐帧调用,要么使用Unity协程、
Invoke等原生延时调度接口,不需要依赖Update也能正常计时。比如完全可以把开局重力缓冲的逻辑全写在Start方法里通过协程实现。
- 是否可以对gravity scale执行Lerp插值操作?
完全可以。Rigidbody2D.gravityScale是可读写的float类型属性,只要传入合法浮点值就能正常生效,不存在引擎层面的限制,你注释里的Lerp写法逻辑本身是正确的。
修正后的实现代码
基于原有Update逻辑的修正版
先把计时器变量提为类成员,避免每帧重置:
// 类成员变量,不要声明在方法内部 private float gravityTimer = 0f; private Rigidbody2D rb; void Start() { rb = GetComponent<Rigidbody2D>(); // 开局初始化缓冲重力 rb.gravityScale = 0.2f; } void Update() { Jump(); Rotation(); PlayerHalt(); } private void PlayerHalt() { // 重力恢复完成后直接返回,减少不必要计算 if (gravityTimer >= 1f) { rb.gravityScale = 1f; return; } gravityTimer += Time.deltaTime; // 1秒后直接切换重力的写法 // if (gravityTimer < 1f) // { // rb.gravityScale = 0.2f; // } // else // { // rb.gravityScale = 1f; // } // 平滑过渡的Lerp写法,取消注释即可使用 rb.gravityScale = Mathf.Lerp(0.2f, 1f, gravityTimer / 1f); }
不依赖Update的协程实现(写在Start中即可正常运行)
如果不想把计时逻辑塞到Update里,可以用协程实现,逻辑更内聚:
void Start() { rb = GetComponent<Rigidbody2D>(); StartCoroutine(GravityRecover()); } private IEnumerator GravityRecover() { float duration = 1f; float timer = 0f; rb.gravityScale = 0.2f; while (timer < duration) { timer += Time.deltaTime; rb.gravityScale = Mathf.Lerp(0.2f, 1f, timer / duration); yield return null; // 等待下一帧继续执行 } rb.gravityScale = 1f; }
内容的提问来源于stack exchange,提问作者FratNightGaming
相关产品推荐
相关产品推荐

