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

按钮无法激活ObjectPool中Start()创建的子弹问题求助

问题描述
  • 按钮按下事件绑定了Shoot函数,初始化阶段创建子弹后,按下按钮无法激活子弹;
  • 若将初始化逻辑移至Shoot方法内,子弹可显示但每次按下都会重复生成新子弹;
  • 已使用Photon并加入PhotonNetwork相关代码,仍存在对象激活失败的问题。

相关代码

PlayerShooter.cs

using UnityEngine;

public class PlayerShooter : ObjectPool
{
    [SerializeField] 
    private GameObject _bullet;

    private void Start()
    {
        Initialize(_bullet);
    }

    public void Shoot()
    {
        // Initialize(_bullet);
        if (TryGetObject(out GameObject bullet))
        {
            bullet.SetActive(true);
        }
    }
}

ObjectPool.cs

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

public class ObjectPool : MonoBehaviour
{
    [SerializeField] 
    private int _amount;

    private List<GameObject> _pool = new();

    protected void Initialize(GameObject prefab)
    {
        for (int i = 0; i < _amount; i++)
        {
            GameObject spawned = PhotonNetwork.Instantiate(prefab.name, transform.position, Quaternion.identity);

            spawned.SetActive(false);
            _pool.Add(spawned);
        }
    }

    protected bool TryGetObject(out GameObject result)
    {
        result = _pool.FirstOrDefault(gameObject => gameObject.activeSelf == false);
        return result != null;
    }
}
问题排查与解决方案

1. 修复Photon网络对象权限问题

Photon实例化的对象仅由创建它的客户端拥有控制权,直接调用SetActive会因权限限制失效。需通过Photon的RPC实现跨客户端同步激活:

  • 给子弹预制体添加PhotonView组件;
  • 在子弹脚本中添加RPC方法:
    using Photon.Pun;
    
    public class Bullet : MonoBehaviourPunCallbacks
    {
        [PunRPC]
        public void ActivateBullet()
        {
            gameObject.SetActive(true);
        }
    }
    
  • 修改Shoot方法,通过RPC激活子弹:
    public void Shoot()
    {
        if (TryGetObject(out GameObject bullet))
        {
            bullet.GetComponent<PhotonView>().RPC("ActivateBullet", RpcTarget.All);
        }
    }
    

2. 修正对象池初始化与同步

初始化逻辑仅在本地执行时,其他客户端的对象池列表未同步,导致跨端找不到可用对象:

  • 确保初始化在Photon连接成功后执行,修改PlayerShooter的Start方法:
    private void Start()
    {
        if (PhotonNetwork.IsConnectedAndReady)
        {
            Initialize(_bullet);
        }
        else
        {
            PhotonNetwork.NetworkingClient.StateChanged += OnPhotonStateChanged;
        }
    }
    
    private void OnPhotonStateChanged(ClientState state)
    {
        if (state == ClientState.Joined)
        {
            Initialize(_bullet);
            PhotonNetwork.NetworkingClient.StateChanged -= OnPhotonStateChanged;
        }
    }
    

3. 优化TryGetObject方法

原方法使用FirstOrDefault可能因网络同步延迟导致状态判断错误,改为遍历检查对象有效性:

protected bool TryGetObject(out GameObject result)
{
    result = null;
    foreach (var obj in _pool)
    {
        if (obj != null && !obj.activeSelf)
        {
            result = obj;
            break;
        }
    }
    return result != null;
}

4. 避免重复初始化

确保Initialize方法仅执行一次,添加标记位:

private bool _isInitialized = false;

protected void Initialize(GameObject prefab)
{
    if (_isInitialized) return;
    
    for (int i = 0; i < _amount; i++)
    {
        GameObject spawned = PhotonNetwork.Instantiate(prefab.name, transform.position, Quaternion.identity);
        spawned.SetActive(false);
        _pool.Add(spawned);
    }
    _isInitialized = true;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 19:12:43