The Ultimate Beginners Guide to Game Development In Unity

Enhet er et flott verktøy for prototyping av alt fra spill til interaktive visualiseringer. I denne artikkelen går vi gjennom alt du trenger å vite for å komme i gang med Unity.

Først litt om meg: Jeg er en hobbyutviklingsenhet, 3d-modellerer og grafisk designer som har jobbet med Unity og Blender i over 5 år. Jeg er nå en økonomisk matematikkstudent ved University College Dublin, og noen ganger gjør jeg frilans grafisk design, webprototyping og prototyping av spill.

Introduksjon

Denne artikkelen er rettet mot alle som aldri har brukt Unity før, men har noen tidligere erfaring med programmering eller innen webdesign / utvikling. Mot slutten av denne artikkelen, bør du ha en god generell oversikt over motoren, samt alle nødvendige funksjoner og kode for å begynne å lage et grunnleggende spill.

Hvorfor enhet?

Hvis du vil lage spill

Det er veldig få alternativer når det gjelder utvikling av Indie Game. De tre hovedvalgene hvis du vil bygge spill er Unreal, Unity eller GameMaker.

Enhet er trolig den minst oppfattede av de tre plattformene. Det gir deg et veldig råprodukt ut av esken, men er svært fleksibelt, veldokumentert og svært utvidbart for å bygge stort sett alle spillgenrer du kan tenke deg.

Det er mange svært vellykkede spill som Escape from Tarkov (FPS), Monument Valley (Puzzler) og This War of Mine (Strategy / Survival), alt bygget i Unity.

I virkeligheten er motoren du bygger ditt første spill på sannsynligvis ikke kritisk, så mitt råd er bare å velge en og gå med den.

Hvis du vil prototype brukeropplevelser

Siden enhet bare er en motor med en mengde fysikk, animasjon og 3D-gjengivelse i sanntid, er det også et flott sted å lage fullverdige interaktive prototyper for UX-studier.

Unity har full støtte for VR og AR, og kan derfor være et flott verktøy for å utforske arkitektur, automatisering og simuleringer med klienter.

Avsnitt til denne artikkelen

  • Hvorfor enhet?
  • Unity Editor-vinduet
  • Enhetsspillobjekter
  • Enhets innebygde komponenter
  • Opprette egendefinerte komponenter
  • Strukturen til en MonoBehaviour
  • Manipulere GameObjects
  • Raycasting
  • Kollisjonsdeteksjon
  • Avanserte funksjoner
  • Råd for nykommere
  • Hyggelige ressurser og fellesskap
  • Konklusjon

Enhetsredigeringsvindu

Editor-vinduet er delt opp i et par seksjoner. Vi vil dekke dette veldig kort, ettersom vi hele tiden vil referere til det gjennom artikkelen. Hvis du er kjent med dette, hopper du bare forbi!

Scene View: Tillater plassering og bevegelse av GameObjects i Scene Game View: Forhåndsvisning av hvordan spilleren vil se scenen fra kameraet Inspektør: Gi detaljer om det valgte GameObject i scenen. Eiendeler / prosjekt: Alle prefabrikker, teksturer, modeller, skript osv. Lagres her. Hierarki: Gjør det mulig å hekke og strukturere GameObjects i scenen

Nå er vi gode å starte!

Enhetsspillobjekter

Hva er GameObjects

GameObjects er kjernebyggesteinen i alt i Unity-spillmotoren. Navnet gir det nesten bort:

Alt du plasserer i en scene i Unity, må pakkes inn i et "spillobjekt."

Hvis du har en webdesignbakgrunn, kan du tenke på GameObjects som mye som elementer! Ekstremt kjedelige containere, men er svært utvidbare for å skape komplekse funksjonaliteter eller visuelle bilder.

Bokstavelig talt er alt fra partikkeleffekter, kameraer, spillere, UI-elementer, ... (listen fortsetter) et GameObject.

Opprette hierarki

Som en i webutvikling, er en GameObject også en container. Akkurat som du hekker for å lage varierte og ønskelige oppsett eller abstraksjoner, kan det være lurt å gjøre det samme med spillobjekter.

Logikken bak hekkende spillobjekter er mye den samme som webutvikling, jeg vil gi noen eksempler ...

Rot og effektivitet

Webanalogi: Du har mange lignende elementer som kan genereres dynamisk i farta som svar på brukerinteraksjon og vil holde dem ryddige. Enhetsoversettelse: Når du bygger en Minecraft-klon, og du har mange blokker i scenen, må du legge til og fjerne 'biter' av blokker fra scenen av ytelsesgrunner. Dermed er det fornuftig å ha dem som foreldre til et tomt GameObject for hver del, da det å fjerne alle foreldrenes blokkeringer blir fjernet.

Posisjonering

Webanalogi: Du vil beholde posisjonen til innholdet som er 'relativt' i forhold til beholderen og ikke til websiden. Enhetsoversettelse: Du har laget en haug med hjelpedroner som svever rundt spilleren. Du vil egentlig ikke heller skrive kode for å be dem jage etter spilleren, så i stedet instantierer du dem som barn av spillerspillobjektet.

Enhets innebygde komponenter

Skuespillerkomponentmodellen

GameObjects på egen hånd er ganske ubrukelige - som vi har sett er de stort sett bare containere. For å legge til funksjonalitet til dem, må vi legge til komponenter, som egentlig er skript skrevet i C # eller Javascript.

Enhet fungerer av en Actor Component-modell, rett og slett, GameObjects er skuespillerne og komponentene er manusene dine.

Hvis du har skrevet noen webapper før, vil du bli kjent med ideen om å lage små gjenbrukbare komponenter som knapper, skjemaelementer, fleksible oppsett som har forskjellige forskjellige direktiver og egendefinerbare egenskaper. Sett deretter sammen disse små komponentene til større websider.

Den store fordelen med denne tilnærmingen er nivået på gjenbrukbarhet og klart definerte kommunikasjonskanaler mellom elementene. På samme måte i spillutviklingen ønsker vi å minimere risikoen for utilsiktede bivirkninger. Små feil har en tendens til å gå ut av kontroll hvis du ikke er forsiktig og er ekstremt vanskelig å feilsøke. Dermed er det viktig å lage små, robuste og gjenbrukbare komponenter.

Nøkkel innebygde komponenter

Jeg tror det er på tide med noen få eksempler på de innebygde komponentene som leveres av Unity Games-motoren.

  • MeshFilter: Lar deg tildele materialer til et 3D-nett til et GameObject
  • MeshRender: Lar deg tilordne materialer til et 3D Mesh
  • [Ramme | Mesh] Collider: Gjør det mulig å oppdage GameObject under kollisjoner
  • Rigidbody: Gjør det mulig for realistisk fysisk simulering å handle på GameObjects med 3d-masker og vil utløse deteksjonshendelser på boksekolliderere
  • Lys: Lyser deler av scenen din
  • Kamera: Definerer spillervisningen som skal festes til et GameObject
  • Ulike UI Canvas-komponenter for visning av GUIer

Det er mange flere, men disse er de viktigste du trenger å bli kjent med. Et tips er at du kan få tilgang til alle dokumentene for disse gjennom enhetsmanualen og skriptreferansen offline uansett hvor du er:

Opprette egendefinerte komponenter

De innebygde komponentene styrer først og fremst fysikk og grafikk, men for å virkelig lage et spill, må du godta brukerinngang og manipulere disse standardkomponentene, så vel som GameObjects selv.

For å begynne å lage komponenter, gå inn i ønsket GameObject> Legg til komponent> skriv inn navnet på den nye komponenten i søkefeltet> nytt skript (c #).

Som en generell anbefaling vil jeg fraråde bruk av Javascript in Unity. Det har ikke blitt oppdatert med alle de flotte tingene som fulgte med ES6, og de fleste av de mer avanserte tingene er avhengige av C # ting som blir overført til Javascript ... Det blir bare en gigantisk løsning i min erfaring.

Strukturen til en MonoBehaviour

Nøkkelfunksjoner

Alle komponenter arver fra MonoBehaviour-klassen. Den inneholder flere standardmetoder, viktigst av alt:

  • ugyldig Start () som kalles når et objekt som inneholder skriptet blir instantiert i scenen. Dette er nyttig når som helst vi vil utføre en initialiseringskode, f.eks. sette utstyret til en spiller etter at de gyter til en kamp.
  • void Update () som kalles hver ramme. Dette er hvor mesteparten av koden som involverer brukerinngang vil gå, og oppdaterer forskjellige egenskaper som bevegelsen til spilleren i scenen.

Inspektørvariabler

Ofte ønsker vi å gjøre komponenter så fleksible som mulig. For eksempel kan alle våpen ha forskjellig skade, skuddhastighet, has_sight osv. Selv om alle våpnene egentlig er de samme, kan det være lurt å kunne lage forskjellige variasjoner raskt gjennom enhetsredigereren.

Et annet eksempel der vi kanskje vil gjøre dette, er når vi oppretter en brukergrensesnittkomponent som sporer brukermusbevegelser og plasserer en markør i visningsområdet. Her vil vi kanskje kontrollere følsomheten til markøren for bevegelser (hvis brukeren brukte styrespak eller gamepad mot en datamus). Dermed vil det være fornuftig å ha denne variabelen enkel å endre både i redigeringsmodus og også eksperimentere med dem i løpetid.

Vi kan gjøre dette enkelt ved ganske enkelt å erklære dem som offentlige variabler i komponenten.

Godtar brukerinngang

Selvfølgelig vil vi at spillet vårt skal svare på brukerinnspill. De vanligste måtene å gjøre det er å bruke følgende metoder i Update () -funksjonen til en komponent (eller hvor som helst du vil):

  • Input.GetKey (KeyCode.W) Returnerer True W-tasten holdes nede
  • Input.GetKeyDown (KeyCode.W) Returnerer True når W-tasten først trykkes på
  • Input.GetAxis (“Vertical”), Input.GetAxis (“Horizontal”) Returnerer mellom -1,1 muses inngangsbevegelse

Manipulere GameObjects

Når vi har fått brukerinngang, vil vi at GameObjects i vår scene skal svare. Det er flere typer svar vi kan vurdere:

  • Oversettelse, rotasjon, skala
  • Lag nye GameObjects
  • Sende meldinger til eksisterende GameObjects / komponenter

Transformasjoner

GameObjects har alle en transformeringsegenskap som gjør det mulig å utføre forskjellige nyttige manipulasjoner på det nåværende spillobjektet.

Metodene ovenfor er ganske selvforklarende, bare vær oppmerksom på at vi bruker små bokstaver gameObject for å referere til GameObject som eier denne spesifikke forekomsten av komponenten.

Generelt er det en god praksis å bruke lokal [Position, Rotation] i stedet for den globale posisjonen / rotasjonen til et objekt. Dette gjør det vanligvis lettere å flytte objekter på en måte som gir mening, da den lokale romaksen vil være orientert og sentrert på det overordnede objektet i stedet for verdensopprinnelsen og retninger x, y, z.

Hvis du trenger å konvertere mellom lokalområdet og verdensrommet (som ofte er tilfelle), kan du bruke følgende:

Som du kan forestille deg, ligger det noen ganske enkel lineær algebra bak dette antydet av 'Inversen' i metodens navn.

Opprette nye GameObjects

Siden GameObjects i utgangspunktet er alt i scenen din, vil du kanskje kunne generere dem på farten. For eksempel hvis spilleren din har en slags prosjektilstarter, vil du kanskje kunne lage prosjektiler på farten som har sin egen innkapslede logikk for flytur, håndtering av skader osv ...

Først må vi introdusere forestillingen om en prefab . Vi kan lage disse ganske enkelt ved å dra et hvilket som helst GameObject i scenehierarkiet til eiendomsmappen.

Dette lagrer egentlig en mal av objektet vi nettopp hadde i vår scene med alle de samme konfigurasjonene.

Når vi har disse prefabrikkerte komponentene, kan vi tilordne dem til inspektørvariabler (som vi snakket om tidligere) på en hvilken som helst komponent i scenen, slik at vi når som helst kan opprette nye GameObjects som spesifisert av prefabrikken.

Vi kan deretter utføre 'instantiering' av prefabrikken og manipulere den til ønsket sted i scenen og etablere de nødvendige foreldreforholdene.

Få tilgang til andre GameObjects og komponenter

Ofte trenger vi å kommunisere med andre GameObjects, så vel som deres tilhørende komponenter. Når du har referert til et spillobjekt, er dette ganske enkelt.

ComponentName comp = some_game_object.GetComponent ();

Etter det kan du få tilgang til noen av de offentlige metodene / variablene til komponenten for å manipulere GameObject. Dette er den enkle biten, men å få referanse til GameObject kan faktisk gjøres på flere måter ...

Tilgang via inspektørvariabel

Dette er det mest enkle. Bare lag en offentlig variabel for GameObject, som vi har demonstrert tidligere med prefabrikkerne, og dra og slipp den manuelt på komponenten via inspektøren. Deretter får du tilgang til variabelen som ovenfor.

Tilgang via merking

Vi kan merke GameObjects eller prefabs via inspektøren, og deretter bruke finn spillobjektfunksjonene til å finne referanser til dem.

Dette gjøres ganske enkelt som nedenfor.

GameObject some_game_object = GameObject.FindGameObjectWithTag (“Brick”);

Tilgang via transform

Hvis vi ønsker å få tilgang til komponenter i noe overordnet objekt, kan vi enkelt gjøre dette via transformattributtet.

ComponentName comp = gameObject.transform.parent.GetComponent ();

Tilgang via SendMessage

Alternativt hvis vi ønsker å sende en melding til mange andre komponenter eller ønsker å sende en melding til et objekt som er langt oppe i et nestet hierarki, kan vi bruke sendemeldingsfunksjonene, som godtar navnet på funksjonen etterfulgt av argumentene.

gameObject.SendMessage (“MethodName”, params); // Broadcast messagegameObject.SendMessageUpwards (“MethodName”, params); // Bare mottatt av komponenter som er nestet ovenfor.

Raycasting

Du har kanskje hørt om dette før når folk sammenligner FPS-spill som er 'fysikkbasert' eller 'strålebasert'. Raycasting er egentlig som å ha en laserpeker som når den kommer i kontakt med en "kollider" eller "stiv kropp", returnerer den et "treff" og sender detaljene til objektet tilbake.

Det er to scenarier der dette kommer til nytte (det er sannsynligvis mye mer):

  1. Hvis du designer et våpensystem for et spill, kan du bruke raycasting for treffdeteksjon, og til og med tilpasse lengden på strålen slik at nærkampartikler "treffer" bare i korte avstander.
  2. Lag en stråle fra musepekeren til et punkt i 3d-rom, dvs. hvis du ønsker at brukeren skal kunne velge enheter med musen i et strategispill.

Som du kan se, er koden for dette litt mer involvert. Det viktigste å forstå er at å kaste en stråle til der musen peker i 3d-rom krever ScreenPointToRay-transformasjon. Årsaken til dette er at kameraet gjengir et 3d-rom som et 2d-visningsfelt på den bærbare skjermen, så det er naturlig nok en projeksjon involvert for å overføre tilbake til 3d.

Kollisjonsdeteksjon

Tidligere nevnte vi Collider- og Rigidbody-komponentene som kan legges til et objekt. Regelen for kollisjoner er at det ene objektet i kollisjonen må ha en stiv kropp og den andre en kolliderende (eller begge har begge komponenter). Merk at når du bruker strålesending, vil stråler bare samhandle med objekter med kolliderende komponenter festet.

Når vi har konfigurert en hvilken som helst tilpasset komponent knyttet til objektet, kan vi bruke metodene OnCollisionEnter, OnCollisionStay og OnCollisionExit til å svare på kollisjoner. Når vi har kollisjonsinformasjonen, kan vi få GameObject ansvarlig og bruke det vi lærte tidligere til å samhandle med komponenter som er festet til den også.

En ting å merke seg er at stive kropper gir fysikk som tyngdekraft for objekter, så hvis du vil at dette er slått av, må du sjekke is_kinematic på.

Avanserte funksjoner

Vi vil ikke gå inn på noe av dette nå, men kanskje i en fremtidig artikkel - bare for å gjøre deg oppmerksom på at de eksisterer.

Opprette GUI-er

Unity har en fullverdig brukergrensesnittmotor for å legge ut GUI for spillet ditt. Generelt fungerer disse komponentene ganske likt resten av motoren.

Utvide Unity Editor

Unity lar deg legge til egendefinerte knapper til inspektørene dine, slik at du kan påvirke verden i redigeringsmodus. For å hjelpe deg med verdensbygging kan du for eksempel utvikle et tilpasset verktøyvindu for å bygge modulhus.

Animasjon

Unity har et grafbasert animasjonssystem som lar deg blande og kontrollere animasjoner på forskjellige objekter, for eksempel spillere som implementerer et beinbasert animasjonssystem.

Materialer og PBR

Unity har en fysisk basert gjengivelsesmotor som muliggjør sanntidsbelysning og realistiske materialer. Realiteten er at du enten må lære 3d-modellering først eller bruke modeller laget og optimalisert av noen andre før du kommer til dette, for å lage ting som faktisk ser bra ut.

Råd for nykommere

Hvis du planlegger å skrive ditt første spill, må du ikke undervurdere kompleksiteten og tiden det tar å skrive til og med det mest trivielle spillet. Husk at de fleste spillene som kommer ut på Steam, har team som jobber med dem i mange år på heltid!

Velg et enkelt konsept og del det opp i små oppnåelige milepæler. Det anbefales sterkt å skille spillet ditt i så små uavhengige komponenter som mulig, ettersom det er mye mindre sannsynlighet for at du støter på feil hvis du holder komponentene enkle i stedet for monolitiske kodeblokker.

Før du går og skriver noen kode for en hvilken som helst del av spillet ditt, kan du gå og undersøke hva noen andre har gjort før for å løse det samme problemet - sjansen er stor for at de får en mye glattere løsning.

Hyggelige ressurser og fellesskap

Spilldesign har et av de beste samfunnene der ute, og det er mange dyktige proffer i bransjen som stiller innhold gratis eller for ingenting. Det er et felt som krever 3d-modellerere, konseptartister, spilldesignere, programmerere og så videre. Jeg har knyttet noen gode generelle ressurser som jeg har kommet over for hvert av disse feltene nedenfor:

Konseptkunst

  • Feng Zhu Design School (Over 90 timer lange konseptkunstopplæringer)
  • Tyler Edlin Art (flott BST kunstsamfunn med tilbakemelding fra proffer på månedlige utfordringer)
  • Art Cafe (intervjuer og workshops med kjente konseptartister)
  • Trent Kaniuga (Illustrator og 2D-artist som også lager sitt eget spill)

3D-modellering

  • CG Cookie (de beste grunnleggende om maskemodellering i blender noensinne, de har masse annet utmerket innhold for blender)
  • Tor Frick (Hard Surface Modelers & Sculptors in Blender)
  • Gleb Alexandrov (Korte kraftige gjengivelsesopplæringer i Blender)

Spilldesign

  • DoubleFine Amnesia Fortnight (GameDevs som gjør en 2 ukers hackathon og registrerer hele designprosessen)
  • GameMakers Toolkit (undersøker prinsippene for spilldesign)

Programmering

  • Håndlaget helt (skriver et spill og en motor fra bunnen av i C)
  • Jonathan Blow (Indie-dev som livestreamer sin spillutvikling)
  • Brackeys (Nice Unity Tutorials)

Konklusjon

Håper dere likte denne veiledningen! Jeg gjør litt grafisk design, i tillegg til prototyper for spill og brukergrensesnitt, så sjekk ut porteføljen min ! Jeg er også koblet inn .

Portefølje| LinkedIn