Përdorimi i API-së së re Unity Pooling për të optimizuar performancën

Në Unity, ne e dimë se mund të krijojmë një shembull të ri të një GameObject nga një Prefab duke thirrurInstantiate() dhe ta shkatërrojmë më vonë duke thirrur, surprizë, Destroy(). Kjo është mirë, nuk ka asgjë të keqe me këtë. Kjo është rruga.

Por nëse na duhet të ndajmë një numër të madh objektesh dhe t'i shkatërrojmë ato në një periudhë të shkurtër kohore, kjo do të kishte ndikim në performancën. Pra, këtu vjen "Object Pooling" për të shpëtuar ditën.

Grumbullimi i objekteve është një model krijimi që na lejon të instantojmë paraprakisht një grup objektesh dhe t'i ripërdorim ato në vend që t'i shpërndajmë dhe shkatërrojmë sipas kërkesës

Ne do të përdorim API-në e re të Unity Pooling, veçanërisht klasën ObjectPool, e cila përdor një pirg për të mbajtur një koleksion shembujsh objektesh. Meqenëse është një klasë gjenerike, qëllimi ynë është gjithashtu të krijojmë një klasë për ta menaxhuar atë që mund ta ripërdorim.

Problemi është se lloji që do të përdorim ka nevojë për një referencë për grupin, në mënyrë që të mund ta lëshojmë objektin kur të mbarojmë me të duke thirrur metodën Release() të ObjectPool.

Ne nuk duam që çdo klasë të ripërcaktojë të njëjtën metodë. Ideja është që të krijohet një klasë bazë që rrjedh nga MonoBehaviour, mban një referencë për grupin dhe ka një zbatim bazë për metodën që do të përdorim për të lëshuar objektin.

Meqenëse ObjectPool është një zbatim i ndërfaqes IObjectPool, ne do ta përdorim këtë lloj për të mbajtur referencën.

Programoni në një ndërfaqe, jo në një zbatim

Më pas, ne do të krijojmë një klasë për të menaxhuar grupin.

Ne do të punojmë me llojin GameObject sepse është klasa bazë për të gjitha entitetet, por klasa jonë do të mbajmë një referencë për një Prefab që trashëgon nga klasa Poolable që përcaktuam më herët.

Për të krijuar një shembull të ri ObjectPool, ne duhet të përcaktojmë disa thirrje kthyese për t'i kaluar te konstruktori i tij:

  • CreatePooledItem, përdoret për të krijuar një shembull të ri kur grupi është bosh
  • OnTakeFromPool, thirret kur shembulli merret nga pishina
  • OnReturnedToPool, thirret kur instanca kthehet në pishinë
  • OnDestroyPoolObject, thirret kur elementi nuk mund të kthehej në pishinë për shkak se pishina arrin madhësinë maksimale

Ne gjithashtu duhet të përcaktojmë një kapacitet të paracaktuar dhe një madhësi maksimale për pishinën. Vlera boolean është për aktivizimin e kontrolleve të mbledhjes.

Disa gjëra për të vënë re këtu. Kur objekti krijohet, ne ia caktojmë referencën grupit duke marrë komponentin e tij Poolable. Ne mund të kryejmë disa pastrime dhe rivendosje të gjendjes kur objekti merret ose kthehet në pishinë, gjatë ciklit të jetës së objektit brenda OnEnable() ose OnDisable(), ose t'ia delegojmë detyrën klasës përgjegjëse për pjelljen e objektit.

Tani, le të krijojmë një klasë që rrjedh nga Poolable dhe përcakton një predhë.

Le të krijojmë një Prefab për të bashkangjitur këtë skript, së bashku me një përplasës të këmbëzës.

Update, ne e lëshojmë objektin kur është jashtë kameras (Boundaries është vetëm një numër që bëra që mban këtë pikë) duke thirrur funksionin që trashëgojmë nga klasa Poolable. E njëjta gjë kur predha godet një tjetër GameObject të etiketuar si “Armik”.

Tani do të zbatojmë një vezullues të thjeshtë për të ndezur predhën. Së pari, na duhet një referencë për grupin tonë, më pas përcaktojmë një GameObject bosh si një transformim prind për të mbajtur të gjitha rastet që do të shkarkojmë, duke e mbajtur hierarkinë të pastër. Ne vendosim pozicionin fillestar dhe rrotullimin brenda funksionit Spawn.

Gjithçka që na mbetet tani është të marrim një referencë për komponentin SimpleSpawner dhe të thërrasim funksionin Spawn() sa herë që duam të ndezim me luajtësin tonë.

Mos ngurroni të luani