Для контекста: я работаю над проектом Unity, где танки стреляют снарядами, используя систему объединения объектов для управления производительностью. Когда танки находятся близко друг к другу, они быстро стреляют, в результате чего объекты в луже активируются и быстро высвобождаются. Кажется, это быстрое взаимодействие вызывает исключение.
Вот моя реализация пула объектов:
Код: Выделить всё
using System.Collections;
using System.Collections.Generic;
using TMPro;
using Unity.VisualScripting;
using UnityEditor.EditorTools;
using UnityEngine;
public class GameManager : MonoBehaviour
{
private int poolSize;
//drag the object to pool in the game menu to this slot
public GameObject ObjectToPool;
public static GameManager manager;
public GameObject[] pools;
public short poolIndex;
public GameObject activePlayer;
public Camera activeCamera;
void Awake()
{
//if the static instance of the class does not exist, create one
if(manager==null){
manager=this;
}
//tag is hardcoded but i will change that later
poolSize=3*GetPooledObjectUserCount("Tank");
poolIndex=0;
InitializePool();
}
private int GetPooledObjectUserCount(string tag){
return GameObject.FindGameObjectsWithTag(tag).Length;
}
private void InitializePool(){
pools=new GameObject[poolSize];
GameObject tmp;
for(short i=0; i
tmp=Instantiate(ObjectToPool);
tmp.SetActive(false);
tmp.AddComponent().PoolIndex = i;
pools[i]=tmp;
}
}
public GameObject GetObjectFromPool(){
GameObject gameObject=pools[poolIndex];
poolIndex++;
return gameObject;
}
public void ReleaseObject(GameObject gameObject){
gameObject.SetActive(false);
GameObject latestActive=pools[poolIndex-1];
//getting release and lastest active object index in pool by getting their component
PooledObject releaseComponent=gameObject.GetComponent();
PooledObject activeComponent=latestActive.GetComponent();
int releaseIndex=releaseComponent.PoolIndex;
int activeIndex=activeComponent.PoolIndex;
//swap their index component value before swapping them in the array
releaseComponent.PoolIndex=activeIndex;
activeComponent.PoolIndex=releaseIndex;
//switch their place in the pool
pools[activeIndex]=gameObject;
pools[releaseIndex]=latestActive;
poolIndex--;
}
}
Код: Выделить всё
using UnityEngine;
public class PooledObject : MonoBehaviour
{
public int PoolIndex;
}
Код: Выделить всё
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Shell : MonoBehaviour
{
public float speed=40;
public Rigidbody rb;
public GameObject explosion;
public Transform shellTransform;
// Start is called before the first frame update
void Awake()
{
rb=gameObject.GetComponent();
shellTransform=gameObject.GetComponent();
}
// Update is called once per frame
void OnCollisionEnter(Collision collision)
{
GameManager.manager.ReleaseObject(gameObject);
GameObject shockwave=Instantiate(explosion, shellTransform.position, shellTransform.rotation);
Destroy(shockwave, 0.5f);
}
void Update()
{
shellTransform.forward=rb.velocity.normalized;
}
}
Код: Выделить всё
Exception caught: Index was outside the bounds of the array.
StackTrace: at GameManager.ReleaseObject (UnityEngine.GameObject gameObject) [0x0000a] in /Users/tripham/Desktop/Unity/AI Projects/AI Tank prototype/Assets/Scripts/GameManager.cs:56
UnityEngine.Debug:LogError (object)
GameManager:ReleaseObject (UnityEngine.GameObject) (at Assets/Scripts/GameManager.cs:73)
Shell:OnCollisionEnter (UnityEngine.Collision) (at Assets/Scripts/Shell.cs:23)
UnityEngine.Physics:OnSceneContact (UnityEngine.PhysicsScene,intptr,int) (at /Users/bokken/build/output/unity/unity/Modules/Physics/ScriptBindings/PhysicsContact.bindings.cs:49)
Я рассмотрел логику и действительно не могу найти крайних случаев. Это заставляет меня подозревать, что это может быть из-за состояния гонки в потоках, из-за которых несколько вызывающих ReleaseObject() одновременно получают доступ к PoolIndex.`
Подробнее здесь: https://stackoverflow.com/questions/792 ... -objects-s