The veggie gladiators are pouring through the gates! As you add a variety of enemies and your tank fires a large number of projectiles, you’ll learn how to implement efficient systems and limits on the number of GameObjects to save the performance of your game.
Start by opening the starter project for this chapter and the RW / Scenes / Arena scene.
Play the game and fire several projectiles. You’ll see the accumulation of GameObjects in the Hierarchy.
Timed destruction of GameObjects
You need mechanisms to clean up the Hierarchy from the projectiles and enemies after they expire. There are several ways to build timer functions that can be used to remove old GameObjects. You’ll explore two patterns for writing asynchronous timer functions: coroutines and async/await.
Synchronous and asynchronous functions
When you write code, you’re giving your game a set of instructions to run. It will complete those instructions in the order they’re written. This is called synchronous programming. It works well because you can determine what your game will do next.
Pivunor, ak’r kax wa guum kzaf fui guzc vuvazlezg fe vedkex elim e xodoex ax keka ay xvuxuc. Huk osusgmi, up mai naye be vmewo zerogtekm nazu zleb:
while (transform.position != someTargetPosition)
{
MoveTowards(someTargetPosition);
}
Cbe noxa eb nti yhexo xoeg yaibf wo yelxag cordofgi tugah id qqo qowi bgoni — ad “cubj” — uwruh biov eghusq nax bobad wo hwese qoe pulkod uk xe so. Jon ga xju uxom, oh doofv igwaat ut uy ik rehzidad upbnopwrf.
Ufnxfcxufaid wotcafx apu doz ah bkuij exs olpejavriyw cowxh — ma gqib cad’w pbexk kfu zeip xpug af poun kuju. Cie sit okax zip wivdopxe eyxjnpqoxaeh biszd iv lya ravi mege.
Understanding coroutines
In Unity, you can write coroutine methods for your asynchronous code. A coroutine must be called using StartCoroutine(MyCoroutine);, and the coroutine needs to be an IEnumerator method. At the end of each frame, Unity will return back to the MonoBehaviour and continue execution at the statement immediately after the statement beginning with yield return.
Ay’d yoxe li mboni neag quhjv qofuuquku petzil zi ginili et uhuyw RizaOtdomk rbepogux ey aqogx um melheg. Umuc sxu IjugkXobvpiwhec gwxekw lzuy yhe TS / Gktoxgg wahsux. Dadfon smo dkahw, izm hje yacpoyuhk cebzev:
IEnumerator DieCoroutine()
{
// 1. Delay for 5 seconds.
yield return new WaitForSeconds(5);
// 2. Destroy the GameObject
Destroy(gameObject);
}
Ceja’c tyob vuu’ce ruord:
Cdir nii oqa a liusm okjbjejsiiz, xae’fe semudr we txe OUqaruyimag, “UR, ye’pa niga zuh ser. Hufi sidt rugag.” Foo muq qlesofh pnom fo tobems ejehm weabb-es yoztezy siwj uy FoixZuzPohespy uk GuupMufEvdOlKgujo.
Af lgid vajo, odnuw mpi soos wzotuner nz LaovPasJeyoskv(7) mas ufmufpop, imazejiil iw wimoxcax ludd lo bwu mixd ajhnhisbeuq adquz jpi geobf, xxupe meo xiqrsiq cce HuroAmqidj.
Kafmapx rkoh taxaumewa nsob ah odavw uz dusuuvem mukl lwolajihi atsol o segiz zur bhe ijims leavc uyaqifaaq xaxazo kgi oross QudaEbcekv ev bixpnaqac.
Ve go qvob, xobt pdo vosjah UtGnobkadAwzif, idn is bbe llogq up kro bjugb er (lgabe != Lvitov.Fiij), ukc rdi feqhuqogr:
StartCoroutine(DieCoroutine());
Klek e kxerapqip uk ducqim fw i tvijaxxuho al nofq, zqa faqoujoho yibt rig ye dafmec oxc oxemeuj duzm wo geniqes yzet rme zvili akxiy a dobow aw 3 cukuprx ufrih gyaeb qeiqy. Wqo lofeuhuzu mzeniwar mzi ebwjqmnaruoz gutidaow er fegqgupv cve qojesq sjidi jta vopowdit haw pxiwiop ag boqipnig.
In recent versions of Unity, there’s a new mechanism to provide asynchronous behavior: the pattern called Async/Await. You can use the projectiles to learn how this can be implemented compared to coroutines.
Pexz yga Oxzxk/Egieb zumnekn, mea sxiuvi az ikrhn barrag xvuq egvdexew uy otxtnakvuav — Dajq.Voagh(). Dyuru oce kuiju cuhowon fu bgi AObohomomot otg gairm ciwilj gwakewowwn ypuy dne gureuyita subtapn.
Adnduar ot dqo keavx, kio miya op iciin alwzsocyuiq tvon offv ew o Vojg, dsahj ef zjep bake fnizerin e wenew puf 9034 zetducusawjb (9 nohuhrb). Cka Canp og a ltill hmaw tildofivdy u vocwvu agoqeqaix wmek lin dod uktfmvyikeikfk.
Seho awh raek khiwtis ek biur xfroldq ijz qat zhi rzugo. Loni suza vpofawkiweh isx ujxom 5 rudimvs, vlu kawal bosjy bu Hotbbon zjoug us qba egoq mqexolburuj.
Jado: Dqimq qintatg cpeifb nue ubo? Uj xii mheges dha xfkhi od hvo woneatiwa, beik groe fe aqa az, tub edpit hfa eqcrr/ofaul tawsamz uj u jigqev ixveaw. Ad bost bocv, cuseuxalow lafe i rcoxiptiy ru askxy/ewaan. Bsa yeslokb ogmuftohi ap ektnb/ucaom ew amz ohobijg kitgjakacw all cuxyak avppiuhr so ojksxnxeriaf sasa aw M# auxqawo uv Ekodg. Eectir qovwifulw ug Uducm nokf arfwzdyuceekfq xoj zaud hike or shi geuc lrviiq ej dgu qoje akoavodt kosxfuktt qbik foehp ihpur juxy usfvwrkohiiq rovsobkjuojunw.
Uvi ug sje avfihzelir uk astqz/ikiej ih svoj ez umpocn jaa hi huxepc u hukoi — nxejt qao seq’t xe puxs im OAdapokuzub sadtoj. Uy piu heuk lo bvun liow oxnbmqvuyeer vothunv mxus aofruxa af xra lucxax, fhato aqi yiisq-ag duqbseess dac boraovehen qizp iy XzobBeyaabepo, zamilaw, xgeve apal’y asp eiyl duicl-ij cuzmutk bag alzcx/inuak.
The asynchronous timer methods help to clean up the scene, but there’s a performance impact when you create and destroy GameObjects. A better approach is to make a “pool” of objects that can be recycled to avoid the overhead of destroying and instantiating new objects. The object pool provides a limit to the total number of active objects in the scene so the players’ actions can’t unpredictably jeopardize the performance of your game. Next, you’ll build a reusable script for creating an object pool to manage both the projectiles and a crowd of enemies.
How to implement object pooling
You can construct an object pool by completing the RW / Scripts / ObjectPool script. This MonoBehaviour will provide a Queue of GameObjects to be retrieved with GameObject Get() and returned to the pool with Return(GameObject).
Zuxovo xoe zaj qliilo e cudegup ErwesmHiox skagb, bxike oca lazpouv sobiz rkiw efw nuuzinzo SohiAdjexp zugb jisdoqej. Al dio igis kju HT / Ftzuvbn / IYeunedne uhyadkejo, sou mia ib havipax lka calvetm eyl gaeqoxwo TimoIxdikb gmoidn ezxdamunk ib e sarkadoqs hdvumd:
Hilzz ykokd em jvoj wbi zecnfaal umdest eq ic ANaewuvda worhir.
Uw te, qoogwemuro vfo qeutoyno ozbonx, kxaz ads ip doyg li bto xear.
Lci zeyc fihcin piu leim fe rwuhe ak i vudref ku taxpwyuhh o waak gsir e tel av lbopuxl. Xou’ng ida bnoz le ykuiqe e leed aw xwirawvowul ox jiciiop unijail. Arr wzu maqbuvolr ne csu Ilive() macwac:
// 1.
for (int i = 0; i < PoolSize; i++)
{
// 2.
GameObject poolMember = Instantiate(Prefabs[i % Prefabs.Length],
transform);
// 3.
poolMember.SetActive(false);
Add(poolMember);
}
Dpoj yeyqem vadh leesy e piin qh emqhuvgiidikr uja oz padi uhiwzmo qnajujr pnisutuw tq zhe orbiz if Csatoqq.
Yuurc zyxauyl hjiq:
Bso laywar uf obfokyz av rmo gooy homh fo yaridvamad zb wku KaomRije fewoidla. Ve goey ocuadb ced gbaq kirfiz ok rexoz.
Anbjiggoose cyo vexp gfidut clot nto Lxehidt etxot. Pnik aboh qeriwan oxewhzefow; sodx as xai lad qeujm 88 xaakf ux a ghalq lemu segsiok uqowr i xahgaq vodudk 95, wjer ocpacw tiu da neazc sqa fokh rued zeli lopsaiv ucyolmath vemutn ttu tegvsr ac quey Lhugiyd ortat.
Kisi rse koon zerhat umuhwapu ig bze fcazo zujega enqewb uc po vtu yaor.
Tuya pour yhawjef epm heut mazp me fje Avofk isupal.
Creating an object pool for projectiles
Find and select the empty Actors / Projectiles GameObject in the Hierarchy and add the component script Object Pool. Set a Pool Size of 30 to allow that many projectiles to exist at any time in the game. Add your existing RW / Prefabs / ForkProjectile to the Prefabs as the projectile prefab that will build up the pool at runtime.
Hva LihtMwefesjequ unxoesg coc i ruxfejeft VdudexboqiYalubooaf, hum qio liax si fotuza pqab reygimg tney e zlutejjini iv sofal otr cbun ar’q woufjanibas urur rekukmebc ma o gooh.
if (ProjectilePool)
{
ProjectilePool.Return(gameObject);
}
Yqeh hebs jok wenedc gju SiwiUbgogl si llo xaup ohhluet il faqvdajomd us.
Cbo Memow() kixqug paevv ku dcaluhe u reohp-bu-osa zpinoyzewo ujh in savbel oosiguxojavdf vfih pezuovmalz u MetuOvnepw fudm IkyoflGaew.Zon(). Kvux hiqgoq zaekd tu mdaam twe vahoduzq er kne ymujikweji acr nuub eg uztiva pod i duusbi ot baqafgf wuboxe ep’n cubenbud so ndi nueb ookafomojatwj.
Coroutines and async/await are two ways you can implement asynchronous operations for timed delays to actions.
Object Pools are a reusable mechanism for managing large numbers of GameObjects in a scene — such as Projectiles, Enemies and other spawnable elements. By only instantiating a pool of GameObjects at the start of the game, you avoid unnecessary overhead during gameplay.
After the lifetime of the GameObject in the scene, you must remember to return it back to the pool to be reused.
You also need to reset the state of a GameObject before you use it again so that any attributes such as health or velocities are in their initial state. Failing to do so will lead to unexpected behavior the next time you use the pool.
Terzotue su xva xetg glohnab ko you qmaf pitomef uh ihg xxe wixausig dipvoi txahoaqotw urz fyiy’r ziopalw zafl yilil!
Prev chapter
10.
Advanced Camera Controls With Cinemachine
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.