Sündmuste järjekord Unity3D-s ja Coroutine'i kasutamine. Minu märkmed. Mängusündmused ja näited Unity regulaarsete värskenduste sündmustest

Unity3D sündmused on jagatud kolme suurde rühma:

Sündmused, mille käivitasid naftaõli sündmused (stseeni laadimine, kasutaja väljumine)
See sündmuste rühm toimub ebaregulaarselt

Raami joonistamisel kutsutud sündmused
Sel juhul kutsutakse ekraani joonistamise tsüklis välja kõik kasutatud skriptid, mis tähendab, et need mõjutavad otseselt FPS-i (kaadrit sekundis). Seetõttu peate siin väga hoolikalt töötama funktsioonidega, mis nõuavad palju töötlemisaega.

Füüsikaliste arvutuste käigus käivitatud sündmused
Ja viimane rühm. Füüsika arvutamiseks luuakse eraldi iseseisev lõim, milles sündmusi kutsutakse teatud ajaintervalli järel. Selle intervalli suurust saab seadistada menüüpunktis Redigeerimine -> Projekti sätted -> Aeg -> Fikseeritud ajasamm.

Seda jaotust teades saate juba teha otsuseid selle kohta, kuhu milline kood on parem paigutada.
Kuid kõik nii füüsikaliste arvutuste kui ka renderdamise ajal tehtud arvutused mõjutavad mängu "reageerimisvõimet". Seetõttu on rakenduse arendamisel soovitatav rakendada Coroutines kõige ressursimahukamad arvutused.

Liigume nüüd edasi abiosa tõlkimise juurde.

Sündmuse funktsioonide järjekord
Unity3D-s on mitmeid sündmusi, mis täidetakse kindlas järjekorras. Kirjeldame seda protseduuri allpool:

Ärkvel: Seda funktsiooni kutsutakse alati välja enne mis tahes funktsiooni käivitamist ja ka kohe pärast tehase lähtestamist.
OnEnable:(kutsutakse, kui objekt on aktiivne): seda funktsiooni kutsutakse välja alles pärast objekti lubamist.

Enne esimest kaadri värskendust

Alusta: Kutsutakse enne esimese kaadri joonistamist ainult siis, kui skript on määratletud.

Kaadrite vahel

OnApplicationPause: Seda sündmust tõstetakse kaadri lõpus, kui tuvastatakse paus, tõhusalt tavaliste kaadrivärskenduste vahel. Pärast OnApplicationPause'i joonistatakse üks lisaraam, mis näitab pausi ajal kuvatavat akent.

Värskendusprotseduur
Mänguloogika, objektide interaktsioonide ja animatsioonide, kaamera asukoha jms jälgimiseks saate kasutada mitmeid erinevaid sündmusi. Enamiku ülesannete täitmise üldine mehhanism on funktsioonis Update(), kuid on ka teisi funktsioone.

FixedUpdate: FixedUpdate() on sõltumatu Update()-st ja seda saab kutsuda sagedamini või harvemini (tavaliselt kutsutakse seda harvemini, kui FPS on piisavalt kõrge). Seda sündmust võidakse käivitada mitu korda kaadri kohta, kui FPS on madal, ja kaadrite vahel ei pruugita üldse käivitada, kui FPS on kõrge. Kõik mootori füüsilised arvutused ja värskendused toimuvad kohe pärast FixedUpdate(). FixedUpdate()-s liikumisarvutuste rakendamisel ei pea te väärtust korrutama Time.deltaTime-ga. Seda seetõttu, et FixedUpdate() kutsutakse kaadrisagedusest sõltumatult taimerilt.
Värskendus: Update() kutsutakse üks kord kaadri kohta. See on raami joonistamise põhisündmus.
Hiline värskendus: LateUpdate() kutsutakse üks kord kaadri kohta pärast seda, kui Update() on lõpetatud. Kõik rakenduses Update() tehtud arvutused viiakse lõpule, kui kutsutakse LateUpdate(). LateUpdate() peamine kasutusala on tavaliselt kolmanda isiku kaamera jälgimine. Kui liigutate oma tegelast sündmuses Update(), saate kaamerat liigutada ja arvutada selle asukoha sündmuses LateUpdate(). See tagab, et tegelane on kogu tee kaamera ees kõndinud ja oma positsiooni kindlustanud.

Stseeni renderdamine

OnPreCull: Helistatakse enne, kui stseen on kaamerasse kokku pandud. Koost määrab, millised objektid on kaamerale nähtavad. OnPreCulli kutsutakse välja ainult siis, kui stseen on nähtamatutest objektidest “lõigatud”.
OnBecameVisible / OnBecameInvisible: Kutsutakse välja, kui objekt muutub mis tahes kaamera jaoks nähtavaks/nähtamatuks.
OnWillRenderObject: Helistatakse üks kord kaamera kohta, kui objekt on nähtav.
OnPreRender: Helistatakse enne, kui kaamera hakkab stseeni renderdama
OnRenderObject: Kutsutakse välja, kui kõik stseeni objektid on joonistatud. Selle kaameraga oma jooniste loomiseks saate kasutada GL või Graphics.DrawMeshNow funktsioone.
OnPostRender: Kutsutakse pärast stseeni kaameras renderdamist.
OnRenderImage (ainult Pro versioon): Kutsutakse pärast stseeni renderdamist ekraanil oleva pildi järeltöötluseks.
OnGUI: Kutsutakse mitu korda kaadri kohta vastuseks liidese sündmustele. Esmalt töödeldakse asukoha ja värvi täitmise sündmusi, seejärel klaviatuuri/hiire sisestussündmusi.
OnDrawGizmos: Kasutatakse Gizmo laval joonistamiseks.

Korutiinid
Tavaliselt tehakse korutiinikutse pärast funktsiooni Update() naasmist. Korutiin on funktsioon, mis võib täitmise (saagise) peatada kuni selle täitmiseni. Korutiini mitmesugused kasutusalad:

saagikus: korutiin jätkub pärast kõiki Update() funktsioone, mida järgmises kaadris kutsutakse.
tootlus WaitForSeconds(2): Jätkake pärast määratud viivitusaega, kui kõik Update() funktsioonid on kaadris juba välja kutsutud
tootlus WaitForFixedUpdate(): Jätkub, kui kõik FixedUpdate() funktsioonid on juba välja kutsutud
tootlus WWW: Jätkub, kui WWW sisu laadimine on lõppenud.
tootlus StartCoroutine (MyFunc): Korutiini seosed, korutiinikõne ootab funktsiooni MyFunc lõpuleviimist.

Objektide hävitamine

OnDestroy: Seda funktsiooni kutsutakse välja objekti olemasolu viimases kaadris (objekti saab hävitada vastusena Object.Destroyle või stseeni sulgemisel).

Väljumisel
Neid funktsioone kutsutakse kõigi stseeni aktiivsete objektide jaoks:

OnApplicationQuit: Seda funktsiooni kutsutakse kõikidel mänguobjektidel enne rakenduse sulgemist. Redigeerijas juhtub see siis, kui kasutaja PlayMode'i peatab. Veebipleieris juhtub see siis, kui veebipleier on suletud.
Keelatud: Seda funktsiooni kutsutakse välja, kui objekt on keelatud või muutub passiivseks.

Seega toimub järgmine skripti täitmise järjekord:

Kõik Awake'i sündmused
Kõik alguse sündmused
tsükkel (deltaaja muutuja juurdekasvuga)
-kõik FixedUpdate funktsioonid
- füüsikamootori arendamine
- käivitada sündmused OnEnter/Exit/Stay
-kokkupõrke sündmused sisenemisel/väljumisel/jäämisel
Jäiga keha teisendus teisenduse järgi.asend ja pöörlemine
OnMouseDown/OnMouseUp muud sisendsündmused
Kõik Update() sündmused
Animatsioon, segamine ja transformatsioon
Kõik LateUpdate'i sündmused
Renderdamine

nõu
Kui käivitate LateUpdate'is korutiinid, kutsutakse neid ka pärast LateUpdate'i vahetult enne renderdamist.
Korutiinid käivitatakse pärast kõiki Update() funktsioone.


Head päeva!

Täna tahaksin lühidalt rääkida sündmuste kasutamisest prügist vabanemiseks ning teie koodile keeruka ja dünaamilise funktsionaalsuse pakkumiseks. Tuleb märkida, et see artikkel on suunatud rohkem algajatele, kes soovivad sündmuste süsteemide kohta rohkem teada saada.

Analüüsime kogu seda asja helijuhtimissüsteemi näitel. See süsteem võimaldab meil mängu seadetes muusikat ja helisid sisse/välja lülitada.

Enne heli- ja muusikaseadeid haldava halduriklassi loomist loome lihtsa serialiseeritava klassi. Seda kasutatakse JSON-i salvestatava andmemudelina.

System.Collections kasutamine; kasutades System.Collections.Generic; UnityEngine'i kasutamine; //================================================= ============ // AudioSettingsModel // @helisätete kasutusmudel // // Arendaja CodeBits Interactive // ​​​​https://cdbits.net/ //===== ================ ====================== avalik klass AudioSettingsModel ( public bool music = true; // Muusika eest vastutav lipp (public bool sounds = true) // Helide eest vastutav lipp;
Nüüd saate alustada juhiklassi kirjutamist. Paigaldame selle esimesel etapil. See haldur on globaalne objekt ja seda ei kustutata stseenist stseeni liikumisel.

System.Collections kasutamine; kasutades System.Collections.Generic; UnityEngine'i kasutamine; kasutades System.IO; //================================================= ============ // Helihaldur // @kasutus töötab heliseadetega // // Arendaja CodeBits Interactive // ​​​​https://cdbits.net/ //==== ================= ======================== avalik klass AudioManager: MonoBehaviour( // Avalik parameetrid public static AudioManager eksemplar = null // Halduri eksemplar public static AudioSettingsModel settings = null // Helisätete mudel privaatne staatiline string _settings_path = "" // Halduri lähtestamine void Awake ()) ( // Seadete salvestamise tee määramine _settings_path = Application.persistentDataPath + "/audioSettings.gdf" ; // Kontrollige, kas meie halduri eksemplar on määratud if (eksemplar == null)( // Eksemplari pole määratud eksemplar = this // Määrake praegune objekt eksemplarile ) // Määrake parameeter, mis näitab, // mis see objekt on, seda ei tohiks mahalaadimisel kustutada // tase DontDestroyOnLoad(gameObject) // Initsialiseerige meie halduri InitializeSettings(); ); ) // Halduri lähtestamine privaatne void InitializeSettings())( // Kui sätete mudelit pole määratud if (settings == null) settings = new AudioSettingsModel(); // Loo uus mudel if (File.Exists(_settings_path) )( // Kui on fail sätetega loadSettings(); // Laadige heliseadete fail ) ) // Laadi heliseaded public void loadSettings())( string _data = File.ReadAllText(_settings_path); // Loe kõike tekst failiseadetest = JsonUtility.FromJson (_andmed); // Serialiseerige see praegusesse mudelisse) // Salvestage heliseaded public void saveSettings())( string _json_data = JsonUtility.ToJson(settings); // Serialiseerige praegused seaded mudelist File.WriteAllText(_settings_path, _json_data); // Salvesta meie faili ) // Looge meie sündmuse jaoks delegaadid, mida hiljem // kasutatakse heliseadete muudatuste jälgimiseks public delegate void AudioSettingsChanged(); // Lisa uus delegeeritud avalik sündmus AudioSettingsChanged OnAudioSettingsChanged; // Looge selle põhjal sündmus // Lülitage helid sisse/välja public void toggleSounds(bool enabled)( settings.sounds = enabled; // Muutke praeguse mudeli heliseadeid saveSettings(_settings_path, settings); // Salvestage sätted, kui (OnAudioSettingsChanged ! = null) OnAudioSettingsChanged(); // Käivitage meie sündmus. seaded // Salvesta sätted if (OnAudioSettingsChanged != null) OnAudioSettingsChanged( // Kutsu meie sündmusele ) )
Nüüd, kui haldur on valmis, saate oma algstseenis luua tühja objekti ja anda sellele nimeks nt. "_AUDIO_MANAGER" ja seejärel lisage sellele meie klassijuhataja. Seda saab teha lihtsalt objekti lisamise menüü kutsudes ja valides "Mänguhaldurid" => "Helihaldur".

Pärast seda peame kirjutama komponendi, mille kinnitame AudioSource abil igale objektile.

System.Collections kasutamine; kasutades System.Collections.Generic; UnityEngine'i kasutamine; //================================================= ============ // Helisummuti // Objektide heliallikate @kasutus sisse/välja // // Arendaja CodeBits Interactive // ​​​​https://cdbits.net/ //= ================ =========================== avalik klass AudioMuter: MonoBehaviour ( // Komponendi public bool is_music = false // See lipp teeb meie klassile selgeks, kas AudioSource on heli või muusika // Privaatsed parameetrid AudioSource _as // AudioSource privaatne heliallikas = 1F; AudioSource'i baasheli // Objekti lähtestamine void Start())( // Hangi AudioSource'i komponent ja selle esialgne helitugevus _as = this.gameObject.GetComponent (); // Hangi komponent _base_volume = _as.volume; // Hangi baasheli // Siia lisame kuulaja, mis käivitab meetodi _audioSettingsChanged // kui muusika/heli seadeid on muudetud AudioManager.instance.OnAudioSettingsChanged += _audioSettingsChanged; // Installimine // Noh, alguses peame kontrollima helide/muusika hetkeseisu _audioSettingsChanged(); ) // Objekti hävitamisel void OnDestroy())( AudioManager.instance.OnAudioSettingsChanged -= _audioSettingsChanged; // Destroy the kuulaja ) // Seda meetodit kasutatakse AudioSource privaatse void helitugevuse sisse/välja lülitamiseks _audioSettingsChanged() if (is_muusika) _as.volume = (AudioManager.settings.music) ? _base_volume: 0F; if (!is_music) _as.volume = (AudioManager.settings.sounds) ?
Nii saame juhtida mängu helisid/muusikat. See näide ei ütle kuidagi, kuidas seda õigesti teha, vaid demonstreerib ainult Unity3D sündmuste süsteemi ja kuulajate tööd.

Ja lõpuks tahaksin rääkida sellest, mida me nüüd kasutasime. Allolevas näites deklareeriti delegaat, millest kuulaja loodi:

Avalik delegaat void AudioSettingsChanged(); avalik üritus AudioSettingsChanged OnAudioSettingsChanged;
Saate seadistada kuulaja teatud tingimustel käivitama ja aheldada nendega spetsiifilisi meetodeid, mis käivitatakse, kui need tingimused on täidetud.

Ja delegaatide abiga, mille alusel kuulaja lõime, saate luua tagasihelistamisfunktsioone. See võib olla eriti kasulik asünkroonsete meetodite puhul (näiteks asünkroonsete POST-päringute saatmisel).

Loodan, et minu väike kogemus selles küsimuses on teile kasulik ja saate seda näidet oma projektides rakendada. Vastan meeleldi ka teie küsimustele (kui keegi millestki aru ei saa).

Saate saidi arendamiseks aidata ja raha üle kanda

Unity3D mängumootoriga töötades on üks esimesi mõisteid, mida peate õppima, sündmuste väljakutsumise järjekord mängus ja nende samade sündmuste töötlemine.

Kuigi venekeelset infot on selle mootori kohta päris palju, siis õiget sündmuste kirjeldust ma ei leidnud. Aga leidsin Unity3D abist ingliskeelse artikli Event Functions Execution Order of Event Functions.

Tõlkija eessõna

Kuid enne ametliku teabe alustamist tahan märkida, et Unity3D sündmused on jagatud nelja suurde rühma:

  1. Raami joonistamisel kutsutud sündmused
    Sel juhul kutsutakse ekraani joonistamise tsüklis välja kõik kasutatud skriptid, mis tähendab, et need mõjutavad otseselt FPS-i (kaadrit sekundis). Seetõttu peate siin väga hoolikalt töötama funktsioonidega, mis nõuavad palju töötlemisaega.
  2. Füüsikaliste arvutuste käigus käivitatud sündmused
    Füüsika arvutamiseks luuakse eraldi iseseisev lõim, milles sündmusi kutsutakse teatud ajaintervalli järel. Selle intervalli suurust saab seadistada menüüpunktis Redigeerimine -> Projekti sätted -> Aeg -> Fikseeritud ajasamm.
  3. Korutiinid (Corutins).
    Ja viimane rühm. Kui väga eemalt, siis saab neid võrrelda eraldi protsessidega, aga kuna Unity3D ei luba eraldi lõime luua, siis on see omamoodi kompromiss. See võimaldab teil katkestada arvutused, anda põhilõimele ressursse ja seejärel jätkata arvutuste järgmise osaga. Markantne näide on kaupade omahinna pidev ümberarvutamine erinevates jaemüügipunktides. See töötab iseseisvalt, ei aeglusta mänguprotsessi ja hinnad kauplustes on alati ajakohased.

Seda jaotust teades saate juba teha otsuseid selle kohta, kuhu milline kood on parem paigutada.

Kuid kõik nii füüsikaliste arvutuste kui ka renderdamise ajal tehtud arvutused mõjutavad mängu "reageerimisvõimet". Seetõttu ärge unustage rakenduse arendamisel jagada kõige ressursimahukamad arvutused etappideks ja korraldada need korutiinidesse.

Liigume nüüd edasi abiosa tõlkimise juurde.

Sündmuse funktsioonide järjekord

Unity3D-s on mitmeid sündmusi, mis täidetakse kindlas järjekorras. Kirjeldame seda protseduuri allpool:

Stseeni esmakordne laadimine

Neid funktsioone kutsutakse välja stseeni alguses (üks kord iga kaadris oleva objekti jaoks).

  • Ärkvel: See funktsioon kutsutakse alati välja enne mis tahes funktsioonide käivitamist ja ka kohe pärast eeltehase lähtestamist.
  • OnEnable:(kutsutakse, kui objekt on aktiivne): seda funktsiooni kutsutakse välja alles pärast objekti lubamist.

Enne esimest kaadri värskendust

  • Alusta: Kutsutakse enne esimese kaadri joonistamist ainult siis, kui skript on määratletud.

Kaadrite vahel

  • OnApplicationPause: Seda sündmust tõstetakse kaadri lõpus, kui tuvastatakse paus, tõhusalt tavaliste kaadrivärskenduste vahel. Pärast OnApplicationPause'i joonistatakse üks lisaraam, mis näitab pausi ajal kuvatavat akent.

Värskendamise protseduur

Mänguloogika, objektide interaktsioonide ja animatsioonide, kaamera asukoha jms jälgimiseks saate kasutada mitmeid erinevaid sündmusi. Enamiku ülesannete täitmise üldine mehhanism on funktsioonis Update(), kuid on ka teisi funktsioone.

  • FixedUpdate: FixedUpdate() on sõltumatu Update()-st ja seda saab kutsuda sagedamini või harvemini (tavaliselt kutsutakse seda harvemini, kui FPS on piisavalt kõrge). Seda sündmust võidakse käivitada mitu korda kaadri kohta, kui FPS on madal, ja kaadrite vahel ei pruugita üldse käivitada, kui FPS on kõrge. Kõik mootori füüsilised arvutused ja värskendused toimuvad kohe pärast FixedUpdate(). FixedUpdate()-s liikumisarvutuste rakendamisel ei pea te väärtust korrutama Time.deltaTime-ga. Seda seetõttu, et FixedUpdate() kutsutakse kaadrisagedusest sõltumatult taimerilt.
  • Värskendus: Update() kutsutakse üks kord kaadri kohta. See on raami joonistamise põhisündmus.
  • Hiline värskendus: LateUpdate() kutsutakse üks kord kaadri kohta pärast seda, kui Update() on lõpetatud. Kõik rakenduses Update() tehtud arvutused viiakse lõpule, kui kutsutakse LateUpdate(). LateUpdate() peamine kasutusala on tavaliselt kolmanda isiku kaamera jälgimine. Kui liigutate oma tegelast sündmuses Update(), saate kaamerat liigutada ja arvutada selle asukoha sündmuses LateUpdate(). See tagab, et tegelane on kogu tee kaamera ees kõndinud ja oma positsiooni kindlustanud.

Stseeni renderdamine

  • OnPreCull: Helistatakse enne, kui stseen on kaamerasse kokku pandud. Koost määrab, millised objektid on kaamerale nähtavad. OnPreCulli kutsutakse välja ainult siis, kui stseen on nähtamatutest objektidest “lõigatud”.
  • OnBecameVisible / OnBecameInvisible: Kutsutakse välja, kui objekt muutub mis tahes kaamera jaoks nähtavaks/nähtamatuks.
  • OnWillRenderObject: Helistatakse üks kord kaamera kohta, kui objekt on nähtav.
  • OnPreRender: Helistatakse enne, kui kaamera hakkab stseeni renderdama
  • OnRenderObject: Kutsutakse välja, kui kõik stseeni objektid on joonistatud. Selle kaameraga oma jooniste loomiseks saate kasutada GL või Graphics.DrawMeshNow funktsioone.
  • OnPostRender: Kutsutakse pärast stseeni kaameras renderdamist.
  • OnRenderImage(Ainult Pro versioon): kutsutakse pärast stseeni renderdamist ekraanil kuvatava pildi järeltöötluseks.
  • OnGUI: Kutsutakse mitu korda kaadri kohta vastuseks liidese sündmustele. Esmalt töödeldakse asukoha ja värvi täitmise sündmusi, seejärel klaviatuuri/hiire sisestussündmusi.
  • OnDrawGizmos: Kasutatakse Gizmo laval joonistamiseks.

Korutiinid

Tavaliselt tehakse korutiinikutse pärast funktsiooni Update() naasmist. Korutiin on funktsioon, mis võib täitmise (saagise) peatada kuni selle täitmiseni. Korutiini mitmesugused kasutusalad:

  • saagikus: korutiin jätkub pärast kõiki Update() funktsioone, mida järgmises kaadris kutsutakse.
  • tootlus WaitForSeconds(2): Jätkake pärast määratud viivitusaega, kui kõik Update() funktsioonid on kaadris juba välja kutsutud
  • tootlus WaitForFixedUpdate(): Jätkub, kui kõik FixedUpdate() funktsioonid on juba välja kutsutud
  • tootlus StartCoroutine (MyFunc): Korutiini seosed, korutiinikõne ootab funktsiooni MyFunc lõpuleviimist.

Objektide hävitamine

  • OnDestroy: Seda funktsiooni kutsutakse välja objekti olemasolu viimases kaadris (objekti saab hävitada vastusena Object.Destroyle või stseeni sulgemisel).

Väljumisel

Neid funktsioone kutsutakse kõigi stseeni aktiivsete objektide jaoks:

  • OnApplicationQuit: Seda funktsiooni kutsutakse kõikidel mänguobjektidel enne rakenduse sulgemist. Redigeerijas juhtub see siis, kui kasutaja PlayMode'i peatab. Veebipleieris juhtub see siis, kui veebipleier on suletud.
  • Keelatud: Seda funktsiooni kutsutakse välja, kui objekt on keelatud või muutub passiivseks.

Seega kutsutakse sündmused pärast lõpetamist välja järgmises järjekorras:

  • Kõik Awake'i sündmused
  • Kõik alguse sündmused
  • tsükkel (deltaaja muutuja juurdekasvuga)
    • Kõik FixedUpdate funktsioonid
    • füüsikamootori testimine
    • käivitavad sündmused OnEnter/Exit/Stay
    • OnEnter/Exit/Stay kokkupõrke sündmused
  • Jäigakeha teisendus teisenduse järgi.asend ja pöörlemine
  • OnMouseDown/OnMouseUp muud sisendsündmused
  • Kõik Update() sündmused
  • Animatsioon, segamine ja transformatsioon
  • Kõik LateUpdate'i sündmused
  • Renderdamine

Kui käivitate LateUpdate'is korutiinid, kutsutakse neid ka pärast LateUpdate'i vahetult enne renderdamist.

Korutiinid käivitatakse pärast kõiki Update() funktsioone.

P.S. lisa kasutaja Leopotamil

Korutiin on vaid kooditükk, mis käivitatakse põhilõime. Seda on väga oluline mõista, sest lihtsalt raske arvutuse panemine korutiini ja eeldamine, et kõik läheb hästi, on põhimõtteliselt vale, et arvutused lihtsalt ummistavad voolu samamoodi, nagu oleks need tehtud värskenduses või mujal standardses meetodid. Arvutused tuleb jagada iteratsioonideks, et uuesti itereerides protsess jätkuks. Korutiinide mõte on automatiseerida nende iteratsioonide kutsumine igas renderdustsüklis.

Näiteks:

IElugeja FindBozons() ( var isFound = false ; var colliderSectionID = 0 ; var colliderSectionCount = 10 ; while (! isFound) ( // Koormuse vähendamiseks töödeldakse korraga ainult ühte jaotist isFound = ProcessDataFromSection(colliderSectionID) ; colliderSectionID = (colliderSectionID ++ ) % colliderSectionCount; tulu tootlus null; ) // Ostame jahte/laevu // Korutiin lõpeb) void Start() ( StartCoroutine(FindBozons() ) ; )

Korutiinimehhanism tagab funktsiooni täitmise konteksti oleku automaatse salvestamise ja naasmise katkestuspunkti (tootlus).

Unity skriptimine ei sarnane programmi traditsioonilisele ideele, kus kood jookseb pidevalt tsüklina, kuni see täidab oma ülesande. Selle asemel annab Unity perioodiliselt juhtimise üle skriptile, kui kutsutakse välja teatud selles deklareeritud funktsioonid. Kui funktsioon on täitmise lõpetanud, naaseb juhtimine tagasi Unity'i. Neid funktsioone tuntakse sündmuste funktsioonidena, kuna Unity aktiveerib need vastusena mängu ajal toimuvatele sündmustele. Unity kasutab nimetamisskeemi, et määrata, millist funktsiooni konkreetse sündmuse jaoks kutsuda. Näiteks olete juba näinud funktsiooni Update (kutsutakse enne kaadrivahetust) ja funktsiooni Start (kutsutakse vahetult enne objekti esimest kaadrit). Unitys on saadaval palju rohkem sündmuste funktsioone; täieliku loetelu koos lisateabega nende kasutamise kohta leiate MonoBehaviour klassi dokumentatsiooni lehelt. Järgmised on mõned kõige olulisemad ja sagedamini esinevad sündmused.

Regulaarsed uuendused

Mäng on omamoodi animatsioon, milles kaadreid genereeritakse lennult. Mängu programmeerimise põhikontseptsioon on objektide asukoha, oleku ja käitumise muutmine mängus vahetult enne kaadri joonistamist. Seda tüüpi kood Unity'is paigutatakse tavaliselt värskendusfunktsiooni. Värskendus kutsutakse välja enne kaadri joonistamist ja enne animatsioonide arvutamist.

Void Update() ( ujumiskaugus = kiirus * Time.deltaTime * Input.GetAxis("Horisontaalne"); transform.Translate(Vector3.right * distance); )

Füüsikamootorit värskendatakse ka fikseeritud aja sammudega, sarnaselt kaadri renderdamisega. Vahetult enne iga füüsiliste andmete värskendamist kutsutakse välja eraldi sündmusefunktsioon FixedUpdate. Sest Kuna füüsikat ja kaadrit ei värskendata sama kiirusega, saate füüsikakoodist täpsemad tulemused, kui lisate selle funktsiooni FixedUpdate, mitte Update'i.

Kehtetu FixedUpdate() ( Vector3 jõud = transform.forward * driveForce * Input.GetAxis("Vertical"); rigidbody.AddForce(jõud); )

Mõnikord on kasulik teha täiendavaid muudatusi ajal, mil funktsioonid Update ja FixedUpdate on kõigi stseeni objektide puhul töötanud ja kõik animatsioonid on arvutatud. Näiteks peaks kaamera jääma sihtobjekti suhtes lukustatuks; kaamera orientatsiooni tuleb reguleerida pärast sihtobjekti liikumist. Teine näide on see, kui skriptikood peab alistama animatsiooni efekti (näiteks panema tegelase pea pöörama stseeni sihtobjekti poole). Seda tüüpi olukordades saate kasutada funktsiooni LateUpdate.

Kehtetu LateUpdate() ( Camera.main.transform.LookAt(target.transform); )

Initsialiseerimise sündmused

Sageli on kasulik kutsuda initsialiseerimiskood välja enne, kui mängu ajal värskendusi tehakse. Funktsioon Start kutsutakse välja enne, kui värskendatakse objekti esimest kaadrit või füüsikat. Funktsioon Awake kutsutakse iga stseeni objekti jaoks stseeni laadimisel. Pange tähele, et kuigi funktsioonid Start ja Awake kutsutakse erinevate objektide jaoks välja erinevas järjekorras, käivitatakse kõik ärkveloleku funktsioonid enne esimese käivitamise väljakutsumist. See tähendab, et funktsiooni Start kood võib kasutada kõike seda, mida ärkveloleku faasis tehti.

GUI sündmused

Unityl on süsteem GUI juhtelementide renderdamiseks kõigele, mis stseenis toimub, ja reageerib nendel elementidel tehtud klikkidele. Seda koodi käsitletakse pisut teisiti kui tavalist kaadrivärskendust, seega tuleb see paigutada OnGUI funktsiooni, mida perioodiliselt kutsutakse.

Void OnGUI() ( GUI.Label(labelRect, "Game Over"); )

Samuti saate määrata hiiresündmused, mis käivitavad stseenis oleva GameObjecti. Seda saab kasutada relvade sihtimiseks või märkide teabe kuvamiseks hiirekursori all. OnMouseXXX sündmuste funktsioonide komplekt (nt OnMouseOver, OnMouseDown), mis võimaldavad skriptil vastata kasutaja hiiretoimingutele. Näiteks kui hiirenuppu vajutatakse, kui hiirekursor on teatud objekti kohal, siis kui selle objekti skriptis on olemas funktsioon OnMouseDown, kutsutakse see välja.

Füüsikaüritused

Füüsikamootor teatab kokkupõrgetest objektiga, kutsudes välja selle objekti skripti sündmuste funktsioonid. Funktsioonid

Tere kõigile. Täna tahan rääkida sellest, kuidas saate mängusündmusi rakendada, neid esitleda ja ka sellest, kuidas luua Unitys kahe klõpsuga täiesti vastuvõetav mängusündmuste süsteem ilma erinevaid UnityActione kasutamata.

Märge: See artikkel ei ole tõdede tõde. See on lihtsalt minu idee ja minu kogemus.

Mul ei ole aega artikli jaoks pilte teha, aga ma pean! Sellepärast on pilt Google'ist pärit!

Lubage mul tuua teile näide liftiga. Mida me temast teame? See võib sõltuvalt nupuvajutusest liikuda üles või alla. Siiski tasub meeles pidada
et see avab/sulgeb ka uksi, mängib heli ja ehk veel midagi. Olen juba ammu harjunud paljusid asju abstraktselt käsitlema,
Seetõttu võin öelda, et mängusündmused võib jagada kaheks komponendiks. Esimene neist on Handlers. Teine on sündmused.
Käsitlejad on skriptid, mis käivitavad mängusündmusi. Jagasin ürituse kutsumise mitmeks variandiks:

  1. Lineaarne. See valik tähendab, et pärast järgmist käivitatakse N arv sündmusi.
  2. Paralleelselt. Ühe käitlejaga rohkem kui ühe sündmuse tõstmine.
  3. Segatud. See on segu esimesest ja teisest võimalusest.

Lähme tagasi lifti. Kohe võib öelda, et lift kuulub varianti nr 3. Las ma seletan. Kui vajutame nuppu, käivitub lifti liikumise sündmus. Järgmiseks, kui see on teie põrandal, avanevad uksed ja kostub näiteks heli. Ukse avanemine ja heli tekivad paralleelselt, kuid pärast liikumist. Saate seda mängu rakendamisel kohe ette kujutada. Aga hiljem.

Et saaksite aru, mida ma käsitlejate all mõtlen, on siin näited: Päästikud, vajutatud nupud (klaviatuuriklahvid), kiired (Raycast) jne.
Noh, päästikute all: helide esitamine, liikuvad objektid jne.

Abstraktselt lõin järgmise arhitektuuri:

Tundub üsna lihtne, kas pole? Isegi tarkvara mõttes pole vaja konvolusioone laadida (kuigi mul oli keeruline rakendust välja mõelda)

Kõikide sündmuste põhiklass näeb välja selline:

UnityEngine'i kasutamine; // System.Collections.Generics; avalik abstraktne klass CoreEvent: MonoBehaviour ( public CoreEvent nextEvent; // Järgmine sündmus // avalik nimekiri sündmuste loend; public abstract void Action(); )

Kommentaarides märkisin nimekirja sündmustest, mis võiksid/peaksid vallandada. väike näide:

UnityEngine'i kasutamine; public class LookEvent: CoreEvent ( public override void Action() ( //if(nextEvent != null) nextEvent.Action(); //else print("Vaata"); ) )

Selles näites tõstatan ainult järgmise sündmuse. Loendi/massiivi jaoks kasutage tsüklit. Kui üks sündmus peaks süttima,
Me ei täpsusta midagi väljal nextEvent ja see on kõik, sest Rakendamisel oleme juba hoolitsenud nullväärtuste töötlemise eest.

Üks punkt rakendamise kohta. Algselt ei olnud baassündmuste klass mõeldud abstraktseks. Ma selgitan, miks. Nagu nägid
ise, nullväärtuse tingimus on iga sündmuse jaoks meetod Action() oli virtuaalne
mis võimaldas baasklassi sisse registreerida, kirjutades selle ühe korra ja seejärel teha seda järgmiselt:

Avalik ovveride void Action() ( base.Action(); //Mõni funktsioon)

Siin on aga igaühele mugavam. Otsustasin teha selle abstraktseks, kuna see vähendas oluliselt koodi hulka põhisündmuste klassis + see,
Programmeerimise seisukohalt on mõttekam, kui tead abstraktse märksõna definitsiooni.

Avalik klass HandlerEvents: MonoBehaviour ( avalik nimekiri üritused; // Määrake põhiklass. public virtual void Launch() ( for (byte countEvent = 0; countEvent< events.Count; countEvent++) { if (events != null) events.Action(); // Вызываем только те события, которые указаны в листе (не null). } } } public enum TriggerType { Enter, Stay, Exit } public class TriggerHandler: HandlerEvents { public TriggerType triggerType; private void OnTriggerEnter2D(Collider2D other) { if (triggerType == TriggerType.Enter && other.GetComponent()) Käivita(); ) private void OnTriggerExit2D(Collider2D muu) ( if (triggerType == TriggerType.Exit && other.GetComponent ()) Käivita(); ) private void OnTriggerStay2D(Collider2D muu) ( if (triggerType == TriggerType.Stay && other.GetComponent ()) Käivita(); ) )

Üsna universaalne kood, kas pole? See on väga mitmekülgne lähenemine, kuna saate teha ühe sündmusekõne, mis kutsub teisi sündmusi ja nii edasi kuni igavlemiseni. Tegin vara sarnase tehnoloogiaga ja see on seal olnud pool aastat, kuid otsustasin seda siin jagada, kuna see versioon on aegunud.

See näib olevat kõik. Kui teil on küsimusi, küsige!

Peagi räägin paljudest huvitavatest põhimõtetest, mida kasutan, mis võivad Unityga töötamisel abiks olla.
Noh, seal on projekti korraldamine, XML-ist lugemine, koodikorraldus jne. Varsti!