The Smoke & Mirrors of Good Countdowns, Part 2

Wat je gaat creëren

De laatste keer hebben we gekeken naar aftellingen in games, hoe ze zijn ingesteld en welke elementen je kunt gebruiken om ze boeiender te maken. Er zijn echter veel meer dan in één artikel passen!

Dit gaat verder vanaf deel 1, daarom beginnen we met nummer zeven.

Klaar? Laten we gaan!

7: Heb een andere constante tikken snelheid

Dit is een simpele truc waarbij je niet eens hoeft te liegen tegen de speler. Je zegt gewoon "wanneer de timer afloopt" en toont een tikkende klok. Wat u niet noemt is het eenheid dat wordt getoond.

Als je een "10" laat zien, zal de speler weten dat dit 10 seconden is, maar het nummer kan langzamer verminderen dan seconden. Als u de waarde wijzigt met a 0.5 vermenigvuldiger, bijvoorbeeld, het zal erna opraken 20 seconden in plaats van alleen 10.

Je kunt kijken hoe dit werkt in mijn Ludum-Dare-spel, Every Ten Seconds a Kitten Drowns.

Een timer in Elke tien seconden verdrinkt een kitten. De timer is langzaam genoeg om de speler een behoorlijke hoeveelheid tijd te geven terwijl hij nog steeds erg laag lijkt

Het thema van de jam maakte dat noodzakelijk 10 seconden worden gebruikt, maar 10 effectieve seconden zijn een veel te lage hoeveelheid tijd om iets zinvols te bereiken.

8: Pas de tikkende snelheid aan tijdens het spelen

Dit werkt ook beter als tijdseenheden niet worden genoemd en de speler slechts een ruw idee krijgt van "totdat dit gebeurt".

Als u een reeks panelen hebt die oplichten om de voortgang van de timer weer te geven, hoeft u ze niet met dezelfde snelheid te activeren. Het wordt zelfs intenser als de eerste paar snel oplichten, en de laatste hebben meer tijd tussen hen in. In de hitte van een actievolle gameplay, zal de speler dit niet realiseren en zal hij een veel intensere ervaring hebben.

Dit moet niet worden gebruikt met werkelijke tijdseenheden, omdat spelers zich misschien bedrogen en voorgelogen voelen. Breek het vertrouwen van de speler in uw systeem niet.

Dit is te zien op één niveau van Starfox 64, waar de speler een positie moet verdedigen tegen een naderend gigantisch schip.

Minimap in Starfox 64. Het aanvallende moederschip (de zwarte cirkel) beweegt naar de basis in het midden, waardoor de speler een ruwe tikkende klok krijgt van hoeveel tijd het nog over is om het te vernietigen

Op het eerste gezicht krijg je een idee van hoeveel tijd er nog over is, maar het schip lijkt met verschillende snelheden te bewegen en niet in een rechte lijn.

De timer is in essentie on-the-fly aangepast, het proces is verborgen achter rook en spiegels.

9: Gebruik Geluiden

Countdowns hoeven niet puur optisch te zijn! Een piepgeluid om de paar seconden zal de onderdompeling enorm verbeteren.

Als je dat eenmaal hebt, kun je de frequentie ook aanpassen als een bepaalde hoeveelheid tijd is verstreken. Als de pieptoon elke vijf seconden optreedt, krijgt de speler in de laatste 30 seconden van de timer een melding zonder naar het nummer te hoeven kijken en moet hij mentaal berekenen hoeveel er nog over is.

Evenzo helpt het ook als een personage reageert op de voortgang. Iemand laten zeggen "We zijn halverwege klaar!" geeft u een goed ingelijst stuk informatie dat veel gemakkelijker te begrijpen is dan het uit een uitlezing te ontleden.

10: gebruik afbeeldingen aanpassen

Dit werkt erg goed wanneer het aanrecht het einde nadert. Telkens als er een tweede seconde verstrijkt, schaaft u de hele teller een halve seconde op.

Naast kleur en geluid maakt dit het veel sappiger.

11: Do Something When It Reaches Zero

Zorg ervoor dat een timer nooit negatief wordt, dit zal voor veel mensen verwarrend zijn en een bug lijken, omdat afgeluisterde, slecht gemaakte timers dat meestal doen.

Flash hebben zou een leuke touch zijn, omdat het nogmaals onderstreept dat het net op is.

Als je een positieve timer hebt, is het een leuk element om het gewoon door te laten gaan en dat element als een hoge score te gebruiken. Het spel Devil Daggers doet een soortgelijk ding, waarbij het hoofddoel "Overleef 500 seconden" is.

Gameplay van Devil Daggers

Wat niet te doen dat het vertrouwen van de speler zou schaden

Zodra de regels van een timer zijn vastgesteld, zouden ze moeten blijven ongeveer consistent, met meer speelruimte wordt toegestaan, hoe minder exact een timer is. De belangrijkste vraag zou moeten zijn: "Hoe kan deze verborgen regel de ervaring ten goede komen?"

Wanneer u de laatste drie seconden een timer vertraagt, wordt de situatie gespannen en krijgt de speler een paar seconden meer tijd om dingen te voltooien. Willekeurig vertragen in het midden, of versnellen, zal alleen het vertrouwen van de speler in je regels breken.

Laten we het opbouwen

Dit gaat verder met de code-base van de laatste zelfstudie en daarop verder gebouwd. Als je het nog niet hebt uitgeprobeerd, doe het nu! Je kunt de voltooide bron ook downloaden in de rechterbovenhoek van dit artikel.

Toen we voor het laatst onze timer hadden verlaten, zag het er zo uit:

Nieuwe toevoegingen zorgen ervoor dat het zich interessanter gedraagt. We zullen doorgaan met de countdown.cs-script, welke er als volgt zou moeten uitzien:

gebruikmakend van UnityEngine; met behulp van System.Collections; openbare klasse Countdown: MonoBehaviour float timer = 60f; openbare AudioClip soundBlip; void Update () if (timer> 0f) timer - = Time.deltaTime;  else timer = 0f;  if (timer < 10f)  GetComponent() .color = Color.red;  else if (timer < 20f)  GetComponent() .color = Color.yellow;  GetComponent() .text = timer.ToString ("F2");  

Make It Beep

Laten we onze timer elke seconde laten piepen, zodat de speler weet dat hij afneemt, zelfs zonder ernaar te kijken.

Ten eerste hebben we een leuke nodig echo Geluidseffect. Je kunt een audiobestand in de bronbestanden vinden, of een leuk bestand maken met de gratis tool BFXR. Als je die hebt, kopieer deze dan naar je activamap.

Voeg een AudioSource-component toe aan uw countdown-object via Component> Audio> AudioSource. Voeg deze variabele toe aan het countdown-script:

openbare AudioClip soundBlip;

U moet ook het geluidsbestand toewijzen aan de soundBlip variabele:

En voeg dit blok toe aan de Bijwerken functie:

if (Mathf.Round (timer * 100) / 100% 1f == 0) GetComponent() .PlayOneShot (soundBlip); 

Hiermee wordt gecontroleerd of de timer op het volledige tweede merkteken staat en zo ja, het geluidsbestand.

De feitelijke werking van deze code is een beetje ingewikkelder. Wat het doet is eerst de drijvende-komma-timer tot twee decimalen afronden, dan door 1 delen en kijken of er een rest is. Als de rest nul is, betekent dit dat de timer een volle seconde heeft bereikt en dat het bliepgeluid kan worden gespeeld.

Als we dit niet doen, kan het systeem veel vaker worden geactiveerd, wat niet leuk is en bevorderlijk voor een goede timer.

Verschillende snelheden

Dit zal een vermenigvuldiger toevoegen die de snelheid van de tikkende klok zal verminderen of versnellen. Voeg deze variabele aan het begin toe:

zwevende vermenigvuldiger = 0,6f;

Zoek nu de regel die de timer vermindert - het is deze:

timer - = Time.deltaTime;

En pas het aan om er zo uit te zien:

timer - = Time.deltaTime * multiplier;

Als de vermenigvuldigingsfactor lager is 1.0 de timer zal nu langzamer lopen en als hij hoger staat 1.0 hij zal sneller werken. Instellen op 1.0 zal niets doen.

Probeer te experimenteren om een ​​goede prijs te vinden! Ik voel een iets lagere snelheid, zoals 0.85f, zorgt ervoor dat de speler de tikkende klok meer voelt.

Vertragen wanneer laag

Nu we een vermenigvuldigingscomponent hebben, kunnen we deze tijdens het spelen wijzigen!

Ga naar het kleurveranderende codeblok:

als (timer < 10f)  GetComponent() .color = Color.red;  else if (timer < 20f)  GetComponent() .color = Color.yellow; 

Hier hebben we al de omstandigheden waarin een verandering in teksnelheid passend zou zijn, dus we kunnen het gewoon toevoegen!

als (timer < 10f)  GetComponent() .color = Color.red; vermenigvuldiger = 0,6f;  else if (timer < 20f)  GetComponent() .color = Color.yellow; vermenigvuldiger = 0.8f;  else multiplier = 1.0f; 

Wanneer de timer geel wordt 20 seconden, zal het nu tikken met een snelheid van 80%. Zodra het rood wordt, gaat het naar 60% normale snelheid. Anders wordt deze op 100% snelheid ingesteld.

Schalen bij laag

Een andere geweldige manier om een ​​timer uit de tijd te laten vallen, is meer om hem op te schalen wanneer hij bijna leeg is. Omdat we al code hebben die elke seconde wordt geactiveerd, kunnen we deze verder aanpassen!

Ten eerste hebben we een functie nodig om de grootte van ons scherm te vergroten of te verkleinen. Voeg deze functie toe:

private bool isBlinking = false; private IEnumerator Blink () isBlinking = true; float startScale = transform.localScale.x; transform.localScale = Vector3.one * startScale * 1.4f; opbrengst retourneert nieuwe WaitForSeconds (0,3 f); transform.localScale = Vector3.one * startScale; isBlinking = false; 

Dit is een IEnumerator, dat is een type functie dat wachtcommando's kan bevatten. We hebben de isBlinking variabele om ervoor te zorgen dat we het niet meerdere keren noemen.

Als het eenmaal is gestart, wordt de grootte van het object met de factor 1,4f vergroot, 0,3 seconden gewacht en vervolgens weer naar de oorspronkelijke grootte teruggebracht.

We noemen het met behulp van deze speciale code:

if (Mathf.Round (timer * 100) / 100% 1f == 0) GetComponent() .PlayOneShot (soundBlip); als (timer < 10f)  if(!isBlinking)  StartCoroutine(Blink());   

Een IEnumerator moet worden gestart door het via te bellen StartCoroutine, anders zal het niet werken.

Het hele blok wordt gebeld wanneer een seconde verstrijkt. Op dat moment kunnen we controleren of de timer laag genoeg is om hem te laten knipperen.

Knipper op nul

Laten we iets doen als de timer op is. Als je gewoon op nul zit, kan dat saai zijn, dus laten we het laten knipperen.

Ten eerste hebben we een andere nodig IEnumerator functie:

private bool isZeroBlinking = false; private IEnumerator ZeroBlink () isZeroBlinking = true; GetComponent() .enabled = false; opbrengst retourneert nieuwe WaitForSeconds (1.5f); GetComponent() .enabled = true; opbrengst retourneert nieuwe WaitForSeconds (1.5f); isZeroBlinking = false; 

Hiermee zet u de timer aan en uit 1.5-tweede intervallen. Activeer het in het blok dat al controleert of de timer nul is.

if (timer> 0f) timer - = Time.deltaTime * multiplier;  else timer = 0f; if (! isZeroBlinking) StartCoroutine (ZeroBlink ()); 

Voordat we het uitvoeren, moeten we het piepen en knipperen op nul zelf uitschakelen, anders zal dit gedrag in botsing komen.

Pas de voorwaarden in het blok aan om te controleren of een seconde is verstreken en ook om te controleren of de huidige tijd meer dan nul is:

if (Mathf.Round (timer * 100) / 100% 1f == 0 && timer> 0f) GetComponent() .PlayOneShot (soundBlip); als (timer < 10f && timer > 0f) if (! IsBlinking) StartCoroutine (Knipperen ()); 

Dit zorgt ervoor dat regelmatig knipperend en nul knipperend werkt zonder dat dit met elkaar interfereert.

De hele countdown script zou er als volgt uit moeten zien:

gebruikmakend van UnityEngine; met behulp van System.Collections; openbare klasse Countdown: MonoBehaviour float timer = 5f; zwevende vermenigvuldiger = 0,6f; openbare AudioClip soundBlip; void Update () if (timer> 0f) timer - = Time.deltaTime * multiplier;  else timer = 0f; if (! isZeroBlinking) StartCoroutine (ZeroBlink ());  als (timer < 10f)  GetComponent() .color = Color.red; vermenigvuldiger = 0,6f;  else if (timer < 20f)  GetComponent() .color = Color.yellow; vermenigvuldiger = 0.8f;  else multiplier = 1.0f;  if (Mathf.Round (timer * 100) / 100% 1f == 0 && timer> 0f) GetComponent() .PlayOneShot (soundBlip); als (timer < 10f && timer > 0f) if (! IsBlinking) StartCoroutine (Knipperen ());  GetComponent() .text = timer.ToString ("F2");  private bool isBlinking = false; private IEnumerator Blink () isBlinking = true; float startScale = transform.localScale.x; transform.localScale = Vector3.one * startScale * 1.4f; opbrengst retourneert nieuwe WaitForSeconds (0,3 f); transform.localScale = Vector3.one * startScale; isBlinking = false;  private bool isZeroBlinking = false; private IEnumerator ZeroBlink () isZeroBlinking = true; GetComponent() .enabled = false; opbrengst retourneert nieuwe WaitForSeconds (1.5f); GetComponent() .enabled = true; opbrengst retourneert nieuwe WaitForSeconds (1.5f); isZeroBlinking = false;  

Dit zal de klus klaren. U kunt het natuurlijk eleganter maken en de opdrachten combineren tot een efficiëntere code.

Conclusie

Onze standaard kleine aftelling is veel interessanter en aantrekkelijker geworden. Als je dit eenmaal bouwt, kun je het gebruiken en aansluiten op elk project dat je maakt, hoe klein ook.

Ga nu en leg het in een spel!