如何在非挂载GameObject的脚本中按条件调用非静态方法?
解决方案:事件驱动实现无耦合的敌人生成触发
要实现敌人全灭时自动调用非静态的Spawning方法,同时避免脚本间的直接耦合,最合理的方式是使用事件驱动模式。这种方式下,敌人销毁时仅触发事件,敌人生成脚本监听事件并判断是否需要生成新敌人,完全不需要其他脚本(比如玩家移动脚本)知晓敌人生成脚本的存在。
步骤1:改造EnemySpawning脚本
首先将原脚本改为MonoBehaviour(必须挂载到场景中的GameObject上,比如GameManager对象),添加敌人计数逻辑和事件监听:
using UnityEngine; using UnityEngine.SceneManagement; using System; public class EnemySpawning : MonoBehaviour { public int level = 1; private int currentEnemyCount = 0; void Start() { // 初始生成第一波敌人 Spawning(); // 订阅敌人销毁事件 Enemy.OnEnemyDestroyed += OnEnemyDestroyed; } void OnDestroy() { // 取消订阅防止内存泄漏 Enemy.OnEnemyDestroyed -= OnEnemyDestroyed; } public void Spawning() { if (SceneManager.GetActiveScene().name != "Game") return; GameObject enemyObject = Resources.Load<GameObject>("BasicEnemy"); int enemyQuantity = 3 * level; int minSpawnX = -3; int maxSpawnX = 3; int minSpawnY = 2; int maxSpawnY = 5; for (int i = 0; i < enemyQuantity; i++) { float xPos = Mathf.Round(UnityEngine.Random.Range(minSpawnX, maxSpawnX)); float yPos = Mathf.Round(UnityEngine.Random.Range(minSpawnY, maxSpawnY)); GameObject enemy = Instantiate(enemyObject, new Vector3(xPos, yPos), Quaternion.identity); currentEnemyCount++; } level += 1; } private void OnEnemyDestroyed() { currentEnemyCount--; // 所有敌人消灭后触发新一轮生成 if (currentEnemyCount <= 0) { Spawning(); } } }
步骤2:给Enemy脚本添加事件触发
在敌人的脚本中定义静态事件,当敌人销毁时触发该事件:
using UnityEngine; public class Enemy : MonoBehaviour { // 定义静态事件,供外部订阅 public static event System.Action OnEnemyDestroyed; void OnDestroy() { // 触发事件,通知所有订阅者敌人已销毁 OnEnemyDestroyed?.Invoke(); } }
方案优势
- 完全解耦:Enemy脚本仅负责触发事件,无需知道EnemySpawning的存在;其他脚本(如玩家移动脚本)完全不需要参与敌人生成逻辑。
- 非静态方法可用:EnemySpawning的非静态方法可以正常访问
level变量。 - 自动触发:当所有敌人销毁后,会自动调用
Spawning方法生成下一波敌人,无需手动调用。
注意事项
- 确保EnemySpawning挂载的GameObject在场景加载时不会被销毁(如果需要跨场景保存,可添加
DontDestroyOnLoad(gameObject))。 - 必须在脚本销毁时取消事件订阅,避免内存泄漏。
内容的提问来源于stack exchange,提问作者luigi65536
相关产品推荐
相关产品推荐

