Unity游戏开发:实现生成点激活/停用,解决重复碰撞问题
解决方案
核心修改点
- 新增变量记录当前激活的SpawnPoint,避免重复触发
- 碰撞时禁用当前SpawnPoint的碰撞器,切换到其他点时重新启用旧点的碰撞器
- 调整生成逻辑,只在当前选中的SpawnPoint生成对象,匹配需求
修改后的完整代码
public class NewSpawnScript : MonoBehaviour { public GameObject[] SpawnPoints; public float spawnTime = 2.5f; public GameObject[] threeD; public List<GameObject> possibleThreeD = new List<GameObject>(); // 记录当前激活的SpawnPoint,用于切换时重新启用旧点 private GameObject currentActiveSpawnPoint; // 标记是否已开启生成循环,避免重复调用InvokeRepeating private bool isSpawning = false; void Start() { // 初始化可生成对象列表 foreach (var obj in threeD) { possibleThreeD.Add(obj); } } private void OnTriggerEnter(Collider other) { // 只响应玩家对象(你的标记为"Obj") if (other.CompareTag("Obj")) { GameObject hitSpawnPoint = gameObject; // 若之前有激活的SpawnPoint,重新启用它的碰撞器 if (currentActiveSpawnPoint != null && currentActiveSpawnPoint != hitSpawnPoint) { currentActiveSpawnPoint.GetComponent<Collider>().enabled = true; } // 禁用当前SpawnPoint的碰撞器,防止持续触发 GetComponent<Collider>().enabled = false; currentActiveSpawnPoint = hitSpawnPoint; // 重置可生成对象列表(若允许重复生成相同对象可注释此段) possibleThreeD.Clear(); foreach (var obj in threeD) { possibleThreeD.Add(obj); } // 控制生成循环:未开启则启动,已开启则重置定时器 if (!isSpawning) { InvokeRepeating(nameof(SpawnItems), spawnTime, spawnTime); isSpawning = true; } else { CancelInvoke(nameof(SpawnItems)); InvokeRepeating(nameof(SpawnItems), spawnTime, spawnTime); } } } void SpawnItems() { if (currentActiveSpawnPoint != null && possibleThreeD.Count > 0) { // 随机选择要生成的对象 int spawnObjectIndex = Random.Range(0, possibleThreeD.Count); GameObject spawnObj = possibleThreeD[spawnObjectIndex]; // 在当前激活的SpawnPoint位置生成对象 GameObject newObj = Instantiate(spawnObj, currentActiveSpawnPoint.transform.position, currentActiveSpawnPoint.transform.rotation); // 关联SpawnPoint到Destroyer脚本(保留原有逻辑) Destroyer destroyer = newObj.GetComponent<Destroyer>(); if (destroyer != null) { destroyer.mySpawnPoint = currentActiveSpawnPoint; newObj.transform.parent = currentActiveSpawnPoint.transform; } // 若需避免重复生成相同对象,移除该对象;否则注释此行 possibleThreeD.RemoveAt(spawnObjectIndex); // 对象列表为空时重置(可选,根据需求调整) if (possibleThreeD.Count == 0) { foreach (var obj in threeD) { possibleThreeD.Add(obj); } } } } }
关键逻辑说明
- 禁用碰撞器:玩家碰撞SpawnPoint后,立即禁用该点的
Collider,阻止后续重复触发OnTriggerEnter,直到切换到其他点时重新启用。 - SpawnPoint切换:碰撞新的SpawnPoint时,先重新开启旧点的碰撞器,再禁用当前点,保证同一时间只有一个SpawnPoint处于“不可触发”状态。
- 生成逻辑修正:将原随机多点生成改为仅在当前激活的SpawnPoint生成,匹配“碰撞哪个点就从哪个点生成”的需求。
- 避免重复循环:用
isSpawning标记控制生成循环,防止多次触发导致生成频率异常。
额外注意事项
- 确保每个SpawnPoint对象都挂载此脚本,且碰撞器的
Is Trigger选项已勾选。 - 若
Destroyer脚本负责对象重生,无需额外处理SpawnPoint状态,状态切换仅由玩家碰撞触发。
内容的提问来源于stack exchange,提问作者Coo
相关产品推荐
相关产品推荐

