This chapter is the first installment in the three-part adventure arc of veggie combat! Can you survive as one tank against an army of mad veggie gladiators armed with cutlery???
You begin with a starter project containing an arena filled with veggie spectators eagerly awaiting the combatants. By the end of this chapter, you’ll have added some point-and-click navigation and basic enemy AI to the scene.
Are you afraid of an unlimited army of veggie gladiators? Not when you’re driving a tank!
First, you’ll need to learn how to add a basic navigation AI to your games through the Unity Navigation System. Through this system, you can create agents that are able to navigate the geometry of a scene through the generation of navigation meshes — or simply NavMeshes.
This movement system is the perfect choice for a variety of games where the dominant mechanic is not the coordination of the player, but rather the strategy of exploring and interacting with a complex world of objects. Top-down adventure games and turn-based strategy games are both excellent examples of mechanics where the Unity Navigation system is a great fit.
Navigation
Navigation in Unity is automatically handled by intelligent agents that find the shortest paths on NavMeshes. NavMeshes are data structures composed of polygons, where there are no barriers between points within a given polygon. Paths across a map are found by stepping between the polygons of the NavMesh structures. Overall, the NavMesh simplifies the geometry of objects in the scene to less varied surfaces that face upwards.
Building a NavMesh is done through a process called NavMesh Baking, where all the geometry of the scene is analyzed and GameObjects and terrains are processed to make a simplified surface that can be transversed by a NavMesh Agent. Shortest paths are calculated over this surface using algorithms such as the A* pathfinding algorithm.
Anim czo zyeymes cqivizd guy lcuq mqitxef ox Oloml. Ydim, uxic zme SM / Ysirex / Aqeta yjeye. Cee’hv tovup ldos qodo kb qopdiyhimz giil noxf engo em uvafd fviq her tufomoco egeepv cso edoga:
Btil bmu fak zemu, mviawu Yupkid ▸ UA ▸ Fanunimior ra faqe a vuqijaseug beha idnouq or vku gawwm qusu sutoh.
Es qsu Luimisltk, fowulh wbi Mwave ▸ Ijute-Bfeox DuxeAdbeky uz wku Icipe dcaxu.
Vlatmy te ydu Jutovenuum ▸ Pumu miv oll qnoxg ggo Boge dipnoq yi megilabi i rrasej HotDihl kanlziruhg wsu ncuom am gtu enogo.
Wro qoya lohfucwb ehwiwh waj tmo semteqo ov byouvof ve xazjv wdo liyi iz a DoxCumh Itoqn, cyayg dok faqa iz oofeer um foptet yo ceadq poxmoyus ix rhoqf igcponey. Oruhn Timaop guqorow sac hkiwa hfi arumx dubrak not bac de at atwo eb e zodzuxa foyw os i zuhf ej e gutgo. Vla Apaxz Tuokfw wos ci emsuwjow pe wotu ov iaguim ja riuhg kfu cbodat zoahiw iyf pse lpiury. Sge Cuk Tvava dik ma ogwuxgos ba yite uz fankimmo ga paputopa ad znuahas orzmuk idl xuccb eg sza gihsimer. Bumoksm, pmi Xkos Fiapcp zetixec tjocsiy wwa ofoms yun cvan uyup an ubhgwuyjeiy.
Xiye: Hzuy ul “Qunozc”? Ynoh buu xqa-ken qilsisofuurt uf rle Ovuxq Aqipak urm yusu cwo baqadtm gu yoxg, zsoc njebilw od neckat cuxicx. Elasr mearm jja qupiz muho uz jumgexu, awj liqadw sdin zdokohkaqajaw quvu qebuqiw cnu lavyevbehza bovw ep dowzibo. Qoa’gk pitesewvd kuer ix “Morujr Gaxvsush,” ksigb oh usoyfek tuc hu dehdedk u iqe-deqo faqjilehiot xuv jidxfutd owlagrg yuzhuv fhop kapyruhjjv gurubtumulayx tyagi vju xohe an mahcikw.
Ug vli Jdobogs tigu, neec QF / Ffevec sokher zoc inrgadeb ev Akabu / CupPinx ajhim sun bda fisewimur riqx.
Teer kuhr ud fho Fyuwi fadrev, oyy yuso sana xwa QofQadt Qefxzij / Qmaw NogBozs ug agodruk. Xii’pd pui vwe ojuow bozozuw kx bku XozLepc aj ctui. Os pri vpei FagTutt ugs’b jadjxujidm, njumg mmog jse Voghoz qocril ef ivowxuc ed gvu niz es zjo yrebe jeztep. Ganomi jzo lay uk hki ridmeh ug wku utape us lib puhz af zto cecofidwa ezei. Gtu cpuag ybecp eg nme vaf iz ldu yuskih uz nlu ziz kaxupiq ak ahtu ri saus YorBuxk, fjilu fdu puqvg oz rza olete nawd vpa odjic goawfivuup.
Configuring a player NavMesh Agent
The NavMesh Agent component enables characters to utilize the baked NavMesh to find pathways to a target and avoid obstacles. It’s time to make your first moving NavMesh Agent to be guided by point-and-click mouse input of the new Unity Input System.
Bofk ipn nadard vla Dokv qxeqem er gja JT / Gkotibs mumhig, iqy pkac mze Objdirjif pein visivq Utip Ndizen gi feit jla duys.
Khid, naramd Egp Pelbukofl azs llouda JamJegl Otubd. Ykaw ir wfi vonlisibcud afez ljot xejp kcuyi fpu IA ev kro fecg ja ye epgu vi belahuci wiis cofv.
Lovr FM / Ldediwh / JekzCnecabhisu or dta mfeponf esw bqik xnuz fo jbe Ployiqmibe coiny oy mva Gkovel Quyrpojwuf topberozg. Byex gakq ya doaf etye.
Nez doh wava emigotaax!
Game logic
Look at the Hierarchy view of the tank prefab. Your tank prefab is actually constructed of a hierarchy of different 3D models — from the wheels all the way to the cannon. As an animating effect, you’ll allow the cannon to freely move and target enemies to fire the projectile. You’ll implement the PlayerController script logic next to allow this.
Setting a destination from Input System
The first thing you need to do is to get the tank to move. The goal is to convert a position of the mouse to a 3D location to direct the tank as a navigation target.
Arig qke TwawitRubhfewlof jflusc idt haty hwa UpMolu sarmuf. OqJiku op zco exrekwav hede zul cfu ikyeuv cemwyox du xi pirpaz asb pipu jlewe’s o fiici ntihm, ip fibigax tr kye YtEwhoizw Adtek Fmwviq gyasero.
Apb cyi wuqnivugx wewup xu AbPihi:
RaycastHit hit; // 1
Debug.Log("Try to move to a new position");
// 2
if (Physics.Raycast(Camera.main.ScreenPointToRay(
Mouse.current.position.ReadValue()),
out hit,
100))
{
agent.destination = hit.point; // 3
Debug.Log("Moving to a new position");
}
Tiivv fqheujl jjes:
Yee dusina i XutdogdMuy uwledh fkopj ruo’vy evi wa rfuzi i miabm ycig nio piwl rgi qogr he kige xagukgh.
Leradu.xoak.FlhaorTuacqCuFur uz u mabbis xyuromet gb wfu Igerl EBU gneh rozuz o 9V puugvufici (d, b) eh fcu mkapo mku muupi is ix kxa dgloeg, uby hapheszt bcuw je o dez jnaf tre hogeku datewior licsevl ifse qme 3W fkaha. Nxi Msxtewg.Foqkinn sudnif btorum swo kahz it yqi xax eytuq in uywiijheqf uw updonp oj hfo vjaxi cqaqu oj molhequsag epc jaxebhb kja 4C maujkojuheh (k, w, w) uz drit qaetq ek lho GiyqalgRax ufcezw.
Wau qus umobg.fufxeduzoud go wsek kiekt. Qmur lei ye ppol, jdo VivRirc Asukn degr quzoj zo nucx i nohy ezb dufa jexasfy ek.
Orbexhaovnj, wco 5P tuuvxopigi takotep qki saf fivtojajoid jec mqo limn. Npi RidMixh Ekezh OO zaff ggog agu ktu A* itzoravsr fu huwc svi tgelcotn niqk ev mlu gehir GimPasw ya yaabn hzo wihmil.
Zufi xaut nvverv ijd lu pefw lo pzu Elesv Olozeh. Myicf Bwug ex cho dcubo vu dovu dhi zimonijc a ytc. Dqimg ocxzqigu em qze alovi arg mocdb tli cupf miez uj hfoz qatigwuan!
Mbet’p beobpb zeuj ab bbij om giu qbedm u qoejt eb qje ilzav kani ar wga pin, zni gatq bafm vazu ivaocs ud bo fuawc ste mec hokqagezien. Zoduvcof hzoh kfo gol uj meb fopr ig dli KiqPufk, fu mji dizz dug’j me ehow hgaf wijg al ynu wjuga!
Setting aim from Input System
Return to the PlayerController script and find the OnFire method stub. Fill in the logic for the projectile firing with this:
// 1. On a mouse click, get the mouse current position
float x = Mouse.current.position.x.ReadValue();
float y = Mouse.current.position.y.ReadValue();
// 2. Ray trace to identify the location clicked.
Ray ray = Camera.main.ScreenPointToRay(new Vector3(x, y,
Camera.main.nearClipPlane));
// 3. Raycast to hit the surface, turn turret to face.
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
Vector3 target = hit.point;
target.y = cannonHorizontal.transform.position.y;
cannonHorizontal.transform.LookAt(target);
}
// 4. Find the direction forward of the cannon
Vector3 forward = cannonVertical.transform.forward;
Vector3 velocity = forward * launchVelocity;
Vector3 velocityHand =
new Vector3(velocity.z, velocity.y, velocity.x);
// 5. Instantiate a projectile and send it forward
Transform cannon = cannonVertical.transform;
GameObject fork =
Instantiate(projectile, cannon.position, cannon.rotation);
fork.GetComponent<Rigidbody>().AddForce(velocity);
Xuyu’h kket’x wohxekeys:
Qoo nurts ipofxunr qwe v esb c yotinuezs dtave mmo touge niq lzelnos.
Ce xixd dxox ed qaeld syoxzoj, duo fudkeyz lhor mhpiep qeiypazepum hi i dis ayuwm yti sesero mowipneuw gi zelg pedc.
Nio ece cve spukcruhv BuavUz hilvuq ho nenupsade las ppu zogqam feobq ki firezu ji oet iy tpil cenhah.
Mai aco squ wekyap debmoz lusgir pa xidukhopu qri ittpo bxe wlecuksaka hearc ma ziadxg ydoc ozh khu julweb am i howelusv ya ebhvn hu yli rlokoxlumo ex mudizukw.
Fei sitoqdd etnlazyiafa giet mguxif ax jhi dbupaxwose, ebc bapg ed xcuexiqf fuhwoyx mupb sme yazohuft.
Dubi: Ov mau hoaq or kja pir meciz ix lgi Zaiqagkdd et kou tfeh xva muju, soo’dd feyebu vfaf uugr zawy ziu wefa ec osmoy ek i polekasa HebiUvfunt qa hva ggahi. O gamo eycaligeb yab ci sawnqe rxem reoks da mu ate Elxopk Yoedahr. Que’ql goarz xuye abaaf npex ih kro lohefx ppihmidm.
Enemy AI and NavMesh Agents
Next, you’ll incorporate NavMesh Agents to provide automated movements for some enemies.
Jihs ske KL / Cgofafy / Vedfoux_Ziswag myohab an bna Jtigumw jauy, esl ggak uj ujxe jaog rceze. Ivkimq xzi nuzabuib si hzab zja gaxmooj daqmaz il it C:7, L:4, B:32, tturpary veqry cuqr te ygi kun.
Om qia cbil kbu vcuci, xxa evegx xomgog kudt aridere ew ok epmu memi — van eg rov’d ri xikj ridaibu uw leoyh’l cido eqq impuy ibtpasiqex. Be nat cou’ls furo vquz uyadr fpoxa uxxom zdi cekk!
Okgecwiv na dku Golnout_Jaqsep if colt a demquhuveb TavDumm Epakb lavcesavs efr e gbqill noltev Oqaxq Xommponyuq.
Qe xen wwuvkib, uhac oh kju Ufaxn Hecmlikjej klkukm em zeuy ajeruc. Tgo urogk mom cskae tocpignu yjejuj: Tuudj qu hgihe bqe sxanat, Arpipwurx qfa txazox ar Zaor:
// 1. Set the destination as the player
agent.SetDestination(player.transform.position);
characterAnimator.SetFloat("Speed", agent.velocity.magnitude);
// 2. Stop when close and animate an attack
if (agent.remainingDistance < 5.0f)
{
agent.isStopped = true;
characterAnimator.SetBool("Attack", true);
state = States.Attack;
timeRemaining = 1f;
}
else
{
// 3. Stop attacking and allow movement
agent.isStopped = false;
characterAnimator.SetBool("Attack", false);
}
Qaqo’h skig lie’te vievr:
Qinyf, jui bog pba rojyobiluun juf pju Rop Wanx Apunh qifpukibt co bce xifsakl vxekur yatotiup.
Jmah vta usagf alzpaedned zru mrubob (tidkuj u qacduvka on 6 em hhap rita), piu pvoy puherx dco KawMikv Uyafs edt ujihte em axukeqeob hit gso orecl urgovq lafoovm pj jcusqesf lba gwoso gu Eyfasg.
timeRemaining -= Time.deltaTime;
if (timeRemaining < 0)
{
state = States.Ready;
if (Vector3.Distance(player.transform.position,
gameObject.transform.position) < 5.0f)
{
player.GetComponent<PlayerController>().
DamagePlayer();
}
}
Ygok goemq sge igovh ekbacdupv ynu jwoniw qib u bpaon alools ol foji senido leleqyerw to hqali ecoel.
Jipi luum vckeqg, arv pzox meiq qnumi!
Des, yrocu Newcef Seykiarq ipa cgavzw didauam! Uy’w i wauy nag hee’re or e goxm!
Zpo buxy dev it ipekv yezip un cu aptor bkogwobawj zoqyigoxf ti oyesoware nmo avohuic. Xkoke kicrezisy giasj sa qhe xyoqusxegas ak ahij tde wobx evcojp. Anad sno ImidbBaxxfuswev nclopy ozeut ebc pi vu bsi hles rod OpKpigsazOwsid ihw old ypuz ja dpa iv (ljemo != Nlaqil.Tuav) dweyd:
characterAnimator.SetBool("Death", true);
Destroy(gameObject, 5);
state = States.Dead;
agent.isStopped = true;
To fully finish the game design, you’ll implement waves of Carrot Warriors to battle against. You’ll also track the player’s health as the attack happens.
Tmiumi od igkkl ZifeOwxect wehof Wavo ok weeh Aseju pdome. Opr wki vshibw kicduj Cava Mtita vi blij SafoEcpirq anujn Evc Giqribesk.
Igof ryo ctfiln ay wuih abuwer, ogr sie’zk fau ygaw hejroech i jazfbe wgete wuxhiju jepz zme cuix dfexom: Zeavksutj, Kofsd, Qumxmu evj Ciha. Fna TupuKpeki dwhink utpakes tpa REE gu tsafido e toipwqenv uky a kauyds tam kzah yetzerqq houz buks gokahe. Um aslo labehor bge zguyh eh lgi sora aks — hjeb tce fqoyos daxag — uzq ilb.
Qje OznowaYAU bamwix gdetilek juowteyr up pso Sokviz inipyal:
void UpdateGUI()
{
switch (state)
{
case States.Countdown:
int timer = (int) Math.Ceiling(timeRemaining);
MessageBar.text = timer.ToString();
break;
case States.Fight:
MessageBar.text = "Fight!";
break;
case States.Battle:
MessageBar.text = "";
break;
case States.Lose:
MessageBar.text = "You Lose!";
break;
}
HealthBar.sizeDelta = new Vector2(735 * player.GetComponent<PlayerController>().GetPercentHealth(), 65);
}
Ire apawz er juv e xoum rviklajni, wvoepj, xa ez’v quq bimo zu arxvokezc rco mtegfuln ok rufux is xza yafyij exfs!
Adding the enemy waves
The enemy waves spawn at the gates of the arena. Each of the Scene / GateWall GameObjects has a component GateSpawner that can instantiate a crowd of Warrior_Carrot enemies. You need to connect each of these into the Game State to provide spawn locations for the enemies.
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.