Unity进入Play Mode时冻结:WaveManager激活导致无响应问题排查
僵尸射击游戏Unity冻结无响应问题排查与解决
问题现象
- 开发首款僵尸射击游戏,WaveManager脚本负责波次切换、每轮僵尸数量递增
- 激活WaveManager组件后进入游戏,Unity直接冻结无响应;停用组件则恢复正常,且无任何报错信息
- 设备配置:16GB内存 + M1芯片
初始代码与问题根源
WaveManager脚本(注:脚本实际名为TargetSpawner,代码中存在笔误)
using System.Collections; using System.Collections.Generic; using UnityEngine; public class WaveManager : MonoBehaviour { public int targetsSpawned; public int targetsLeft; public int wave; public int firstWaveTargets; ZombieSoawner spawner; void Awake() { spawner = GameObject.FindGameObjectWithTag("TargetSpawner").GetComponent<ZombieSoawner>(); wave = 1; targetsSpawned = firstWaveTargets; targetsLeft = targetsSpawned; spawner.SpawnZombies(); } void Update() { if (targetsLeft <= 0) { nextWave(); } } void nextWave() { wave += 1; targetsSpawned += 2; targetsLeft = targetsSpawned; spawner.SpawnZombies(); } }
ZombieSpawner脚本(问题核心所在)
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ZombieSoawner : MonoBehaviour { public WaveManager manager; int targetsPlaced; public GameObject target; public void SpawnZombies() { while (manager.targetsSpawned > targetsPlaced) { PlaceTargets(); targetsPlaced += 1; } } public void PlaceTargets() { targetsPlaced = 0; // 此处是无限循环的根源 Vector3 originalPos = transform.localPosition; transform.localPosition = originalPos; float randomOffset = Random.Range(-20f, 20f); Vector3 randomPos = new Vector3(originalPos.x + randomOffset, originalPos.y + 5f, originalPos.z + randomOffset); Instantiate(target, randomPos, Quaternion.identity); } }
Target脚本(无问题)
using UnityEngine; using UnityEngine.AI; public class Target : MonoBehaviour { public float health = 50f; public float lookRadius = 20f; Transform target; NavMeshAgent agent; WaveManager manager; private void Awake() { manager = GameObject.FindGameObjectWithTag("WaveManager").GetComponent<WaveManager>(); target = PlayerManager.instance.player.transform; agent = GetComponent<NavMeshAgent>(); } private void Update() { float distance = Vector3.Distance(target.position, transform.position); if ( distance <= lookRadius) { agent.SetDestination(target.position); if (distance <= agent.stoppingDistance) { FaceTarget(); } } } void FaceTarget() { Vector3 direction = (target.position - transform.position).normalized; Quaternion lookRotation = Quaternion.LookRotation(new Vector3(direction.x, 0, direction.z)); transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * 5f); } public void TakeDamage(float amount) { health -= amount; if (health <= 0f) { manager.targetsLeft -= 1; Destroy(gameObject); } } private void OnDrawGizmosSelected() { Gizmos.color = Color.red; Gizmos.DrawWireSphere(transform.position, lookRadius); } }
问题分析
SpawnZombies方法中的while循环本意是生成指定数量的僵尸,但每次调用PlaceTargets时,都会将targetsPlaced重置为0。这导致循环条件manager.targetsSpawned > targetsPlaced永远成立,进入无限循环,Unity主线程被阻塞,最终表现为冻结无响应。
解决方案
将targetsPlaced = 0;从PlaceTargets方法中移至SpawnZombies方法的开头,确保每轮生成僵尸前先重置计数,循环可以正常终止:
修正后的ZombieSpawner脚本
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ZombieSoawner : MonoBehaviour { public WaveManager manager; int targetsPlaced; public GameObject target; public void SpawnZombies() { targetsPlaced = 0; // 移至此处,每轮生成前重置计数 while (manager.targetsSpawned > targetsPlaced) { PlaceTargets(); targetsPlaced += 1; } } public void PlaceTargets() { Vector3 originalPos = transform.localPosition; transform.localPosition = originalPos; float randomOffset = Random.Range(-20f, 20f); Vector3 randomPos = new Vector3(originalPos.x + randomOffset, originalPos.y + 5f, originalPos.z + randomOffset); Instantiate(target, randomPos, Quaternion.identity); } }
内容的提问来源于stack exchange,提问作者MrMcgrizz
相关产品推荐
相关产品推荐

