You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity 2D对象池改造:实现屏幕EnemyCount数量恒定需求

基于对象池维持固定敌人数量的实现方案

需求说明

已实现对象池系统,通过复用对象避免重复实例化/销毁开销。需要修改脚本,使屏幕上始终保持Controller.data.enemy1Info.count定义的敌人数量:

  • 当前EnemySpawner.cs按固定间隔持续生成敌人
  • 敌人触发触发器时,会调用ObjectPoolManager.ReturnObjectToPool(gameObject)回收至对象池

修改方案

1. 重构EnemySpawner脚本

核心思路:移除无限循环生成逻辑,改为监控活跃敌人数量,自动补充至目标值,同时通过敌人回收事件同步计数。

修改后的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemySpawner : MonoBehaviour
{
    [SerializeField]
    private GameObject enemy1;
    [SerializeField]
    private GameObject enemy2;
    [SerializeField]
    private GameObject enemy3;
    [SerializeField]
    private GameObject enemy4;
    [SerializeField]
    private GameObject enemy5;

    [SerializeField]
    public GameObject spawnCircle;

    // 当前活跃的enemy1数量
    private int _activeEnemy1Count = 0;
    // 数量检查间隔(可根据需求调整)
    [SerializeField]
    private float countCheckInterval = 1f;

    void Start()
    {
        // 启动enemy1的数量维护协程
        StartCoroutine(MaintainEnemy1Count());
        // 如需维护其他敌人,可复制上述逻辑,替换对应参数
        // StartCoroutine(MaintainEnemyCount(enemy2, () => Controller.data.enemy2Info.count, enemy2Interval));
    }

    /// <summary>
    /// 持续维护enemy1的数量至目标值
    /// </summary>
    private IEnumerator MaintainEnemy1Count()
    {
        while (true)
        {
            yield return new WaitForSeconds(countCheckInterval);
            
            int targetCount = Controller.data.enemy1Info.count;
            int needSpawn = targetCount - _activeEnemy1Count;

            // 批量补充不足的敌人
            for (int i = 0; i < needSpawn; i++)
            {
                SpawnEnemy(enemy1);
            }
        }
    }

    /// <summary>
    /// 生成单个敌人并绑定回收回调
    /// </summary>
    private void SpawnEnemy(GameObject enemyPrefab)
    {
        GameObject newEnemy = ObjectPoolManager.SpawnObject(
            enemyPrefab, 
            getRandomSpawnPoint(), 
            Quaternion.identity, 
            ObjectPoolManager.PoolType.Gameobject
        );

        // 添加回收监听,敌人被回收时更新计数
        EnemyDespawnListener listener = newEnemy.GetComponent<EnemyDespawnListener>();
        if (listener == null)
        {
            listener = newEnemy.AddComponent<EnemyDespawnListener>();
        }
        listener.OnDespawn += () => _activeEnemy1Count--;

        _activeEnemy1Count++;
    }

    /// <summary>
    /// 外部调用:增加enemy1的目标数量
    /// </summary>
    public void IncreaseEnemySpawnCount()
    {
        Controller.data.enemy1Info.count++;
    }

    // 获取随机生成点
    private Vector3 getRandomSpawnPoint()
    {
        int childIndex = Random.Range(0, spawnCircle.transform.childCount);
        return spawnCircle.transform.GetChild(childIndex).position;
    }
}

2. 添加EnemyDespawnListener辅助脚本

用于监听敌人被回收时的禁用事件,同步更新Spawner的计数:

using UnityEngine;
using UnityEngine.Events;

public class EnemyDespawnListener : MonoBehaviour
{
    public UnityEvent OnDespawn;

    private void OnDisable()
    {
        // 敌人被回收时触发回调
        OnDespawn?.Invoke();
    }
}

3. ObjectPoolManager无需修改

当前的对象池逻辑已经支持对象的复用与回收,无需额外调整。

关键逻辑说明

  • 数量监控:通过协程定期检查活跃敌人数量与目标数量的差值,自动补充不足的敌人
  • 计数同步:利用敌人被回收时的OnDisable事件(ReturnObjectToPool中会调用SetActive(false)),实时减少活跃计数
  • 性能优化:避免了无限循环生成的冗余逻辑,仅在数量不足时生成对象,充分利用对象池的复用能力

注意事项

  • 确保所有敌人最终都会调用ObjectPoolManager.ReturnObjectToPool(gameObject),否则计数会出现偏差
  • 可调整countCheckInterval参数:值越小,数量响应越快,性能消耗略高;值越大,性能越好,数量同步延迟越长
  • 如需支持多种敌人类型,可将MaintainEnemy1Count重构为通用方法,传入敌人预制体、目标数量委托等参数

内容的提问来源于stack exchange,提问作者shane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 03:35:00