Unity C#生成物体移速提升异常:仅首个物体速度生效
问题分析与解决方案
你遇到的核心问题是每个管道实例都维护着独立的计时器和移动速度变量:第一个生成的管道从游戏启动就开始计时,10秒后触发自身提速;但后续生成的管道在创建时timer才从零开始,要等各自生成后的10秒才会执行提速逻辑——这就导致你看起来只有第一个管道在提速,其他管道还没到自己的触发节点。
如果你的需求是所有管道按全局时间周期性同步提速(比如游戏开始后每10秒,所有管道一起加快速度),可以参考以下两种修改方案:
方案一:全局控制器统一管理提速逻辑
把计时逻辑移到PipeSpawnerScript中,统一跟踪全局时间,然后通知所有已生成的管道更新速度:
修改PipeSpawnerScript
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PipeSpawnerScript : MonoBehaviour { public GameObject pipe; public float spawnRate = 2; public float timer = 0; public float hightOffset = 10; public Birdscript Bird; // 新增全局提速相关变量 public float globalSpeedInterval = 10f; public int speedAddAmount = 5; private float globalSpeedTimer = 0f; private List<pipeMoveScript> allPipes = new List<pipeMoveScript>(); void Start() { spawnPipe(); Bird = GameObject.FindGameObjectWithTag("Bird").GetComponent<Birdscript>(); } void Update() { // 原有管道生成逻辑 if (timer < spawnRate) { timer += Time.deltaTime; } else { if (Bird.birdIsAlive) { spawnPipe(); timer = 0; } } // 新增全局提速计时逻辑 if (Bird.birdIsAlive) { if (globalSpeedTimer < globalSpeedInterval) { globalSpeedTimer += Time.deltaTime; } else { // 遍历所有管道触发提速 foreach (var pipe in allPipes) { if (pipe != null) // 跳过已销毁的管道 { pipe.Speedup(speedAddAmount); } } globalSpeedTimer = 0f; Debug.Log("所有管道已提速"); } } } void spawnPipe() { float lowestPoint = transform.position.y - hightOffset; float highestPoint = transform.position.y + hightOffset; GameObject newPipe = Instantiate(pipe, new Vector3(transform.position.x, Random.Range(lowestPoint, highestPoint), 0), transform.rotation); // 将新管道加入管理列表 allPipes.Add(newPipe.GetComponent<pipeMoveScript>()); } }
修改pipeMoveScript
移除自身的计时逻辑,只保留速度更新和移动逻辑:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class pipeMoveScript : MonoBehaviour { public float moveSpeed = 5; public float deadZone = -40; public Birdscript Bird; void Start() { Bird = GameObject.FindGameObjectWithTag("Bird").GetComponent<Birdscript>(); } public void Speedup(int speedToadd) { moveSpeed += speedToadd; } void Update() { if (Bird.birdIsAlive) { transform.position += Vector3.left * moveSpeed * Time.deltaTime; } if (transform.position.x < deadZone) { Debug.Log("pipe Deleted"); // 从Spawner的管理列表中移除自己,避免空引用 PipeSpawnerScript spawner = FindObjectOfType<PipeSpawnerScript>(); if (spawner != null) { spawner.allPipes.Remove(this); } Destroy(gameObject); } } }
方案二:静态变量共享全局速度(更简洁)
如果不需要单独控制某个管道的速度,可以用静态变量存储全局速度,所有管道直接读取这个值移动:
修改pipeMoveScript
using System.Collections; using System.Collections.Generic; using UnityEngine; public class pipeMoveScript : MonoBehaviour { // 改为静态变量,所有管道共享同一速度值 public static float globalMoveSpeed = 5; public float deadZone = -40; public Birdscript Bird; void Start() { Bird = GameObject.FindGameObjectWithTag("Bird").GetComponent<Birdscript>(); } // 静态方法:全局提速 public static void GlobalSpeedup(int speedToadd) { globalMoveSpeed += speedToadd; } void Update() { if (Bird.birdIsAlive) { // 使用全局速度移动 transform.position += Vector3.left * globalMoveSpeed * Time.deltaTime; } if (transform.position.x < deadZone) { Debug.Log("pipe Deleted"); Destroy(gameObject); } } }
修改PipeSpawnerScript
添加全局提速计时逻辑:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PipeSpawnerScript : MonoBehaviour { public GameObject pipe; public float spawnRate = 2; public float timer = 0; public float hightOffset = 10; public Birdscript Bird; public float globalSpeedInterval = 10f; public int speedAddAmount = 5; private float globalSpeedTimer = 0f; void Start() { spawnPipe(); Bird = GameObject.FindGameObjectWithTag("Bird").GetComponent<Birdscript>(); } void Update() { // 原有管道生成逻辑 if (timer < spawnRate) { timer += Time.deltaTime; } else { if (Bird.birdIsAlive) { spawnPipe(); timer = 0; } } // 全局提速计时 if (Bird.birdIsAlive) { if (globalSpeedTimer < globalSpeedInterval) { globalSpeedTimer += Time.deltaTime; } else { pipeMoveScript.GlobalSpeedup(speedAddAmount); globalSpeedTimer = 0f; Debug.Log("全局管道速度已提升"); } } } void spawnPipe() { float lowestPoint = transform.position.y - hightOffset; float highestPoint = transform.position.y + hightOffset; Instantiate(pipe, new Vector3(transform.position.x, Random.Range(lowestPoint, highestPoint), 0), transform.rotation); } }
两种方案都能实现所有管道同步提速的效果:方案一更灵活,支持后续单独调整单个管道的速度;方案二更简洁,适合所有管道速度完全同步的场景。
内容的提问来源于stack exchange,提问作者Jaden Hill
相关产品推荐
相关产品推荐

