Advertisement
  1. Game Development

Tips dan Trik Countdown yang Baik, Bagian 2

Scroll to top
Read Time: 9 min
This post is part of a series called The Smoke & Mirrors of Good Countdowns.
The Smoke & Mirrors of Good Countdowns, Part 1

() translation by (you can also view the original English article)

Final product imageFinal product imageFinal product image
What You'll Be Creating

Terakhir kali, kita lihat hitung mundur dalam game, bagaimana menyiapkannya, dan elemen apa yang bisa kamu gunakan untuk membuatnya lebih menarik. Ada masih banyak yang bisa kita bahas yang tidak masuk dalam artikel sebelumnya.

Kita akan lanjutkan dari Bagian 1, jadi kita mulai langsung dari nomor 7.

Siap? Mulai!

7: Buat beberapa kecepatan hitung mundur

Ini adalah trik sederhana yang bahkan tidak membutuhkan kamu membohongi pemain. Kamu cukup bilang "saat timer habis" dan tampilkan sebuah penunjuk waktu. Yang tidak kamu sebutkank adalah satuan waktu yang ditampilkan.

Jika kamu tampilkan nilai "10", pemain akan mengira ini 10 detik, tapi nilainya berkurang lebih lambat detik. Jika kamu mengubah nilainya dengan pengali 0.5, misalnya, waktu akan habis setelah 20 detik, bukan 10.

Kamu bisa lihat bagaimana ini bekerja dalam game Ludum-Dare saya, Every Ten Seconds a Kitten Drowns.

A timer in Every Ten Seconds a Kitten DrownsA timer in Every Ten Seconds a Kitten DrownsA timer in Every Ten Seconds a Kitten Drowns
Timer pada Every Ten Seconds a Kitten Drowns. Timer berjalan cukup lambat untuk memberi pemain waktu yang cukup sambil terlihat cukup sedikit.

Tema event tersebut meminta 10 detik digunakan, tapi 10 detik adalah waktu yang terlalu sedikit untuk mencapai sesuatu yang bermakna.

8: Menyesuaikan kecepatan hitung mundur dalam permainan

Ini juga bekerja dengan baik jika satuan waktu tidak disebutkan dan pemain hanya diberikan gambaran kasar "sampai ini terjadi".

Jika kamu punya sejumlah panel yang menyala untuk menampilkan kemajuan timer, kamu tidak perlu mengaktifkannya dalam kecepatan yang sama. Bahkan, akan lebih menegangkan jika beberapa menyala dengan cepat, dan sisanya memiliki lebih banyak waktu diantara mereka. Dalam permainan yang penuh aksi, pemain tidak akan menyadari ini dan akan mendapatkan pengalaman yang lebih menegangkan.

Ini tidak boleh diimplementasi dengan satuan waktu yang benar, karena pemain bisa merasa dicurangi atau dibohongi. Jangan mematahkan kepercayaan pemain pada game yang kamu buat.

Ini bisa dilihat pada salah satu level pada Starfox 64, di mana pemain harus mempertahankan posisi terhadap sebuah kapal raksasa.

Minimap in Starfox 64Minimap in Starfox 64Minimap in Starfox 64
Minimap pada Starfox 64. Kapal induk yang menyerang (lingkaran hitam) bergerak menuju markas di tengah, memberi pemain gambaran kasar berapa banyak waktu yang tersisa untuk menghancurkannya.

Pada pengamatan pertama, kamu mendapat gambaran kasar berapa waktu yang tersisa, tapi pesawat tersebut terlihat bergerak dengan kecepatan yang berbeda dan tidak dalam garis lurus.

Timer pada dasarnya ditampilkan saat permainan berjalan, dan prosesnya yang disembunyikan dengan ilusi.

9: Gunakan suara

Hitung mundur tidak harus visual! Suara beep beberapa detik sekali akan menigkatkan rasa nyata permainan.

Setelah kamu mengimplementasinya, kamu juga bisa menyesuaikan frekuensi setelah waktu tertentu sudah berlalu. Jika suara berbunyi setiap lima detik di 30 detik terakhir timer, pemain akan tahu tanpa perlu melihat angka dan bisa menghitung secara mental berapa waktu yang tersisa.

Begitu pula, akan membantu jika seorang karakter mengomentari kemajuan pemain. Membuat karakter berkata "Sudah separuh jalan!" memberi kamu informasi yang cukup mudah dimengerti dibanding tulisan yang harus dibaca.

10: Gunakan visual yang berubah ukuran

Ini bekerja dengan baik saat perhitungan mendekati akhirnya. Kapanpun detik berlalu, perbesar timer selama setengah detik.

Bersama warna dan suara, ini akan membuat timer lebih menarik.

11: Lakukan sesuatu saat mencapai nol

Pastikan timer tidak pernah mencapai nilai negatif, ini akan memusingkan untuk banyak orang dan terlihat seperti kesalahan yang dimiliki timer yang jelek.

Membuatnya menyala adalah sentuhan yang baik, karena menekankan bahwa waktunya habis.

Jika kamu punya timer yang positif, menyenangkan jika membuatnya terus berjalan dan menggunakan elemen tersebut sebagai high-score. Game Devil Daggers melakukan hal yang serupa, di mana tujuan utamanya adalah "Bertahan selama 500 detik".

Gameplay from Devil DaggersGameplay from Devil DaggersGameplay from Devil Daggers
Permainan Devil Daggers

Hal yang jangan dilakukan karena akan mematahkan kepercayaan pemain

Begitu aturan timer sudah diterapkan, aturan tersebut seharusnya kurang lebih tetap konsisten, dengan toleransi untuk timer yang tidak perlu terlalu tepat. Pertanyaannya seharusnya "Bagaimana aturan tidak telrihat ini meningkatkan pengalaman pemain?".

Saat kamu memperlambat timer di tiga detik terakhir, itu akan membuat situasi lebih menegangkan dan memberi pemain beberapa detik tambahan untuk menyelesaikan misi. Memperlambat timer secara acak di tengah permainan, atau mempercepatnya, hanya akan mematahkan kepercayaan pemain pada aturan kamu.

Ayo kita buat

Kita akan melanjutkan kode yang kita buat dari tutorial sebelumnya. Jika kamu belum mencobanya, lakukan sekarang! Kamu bisa juga mengunduh kode yang selesai di kanan atas artikel ini.

Terakhir kali, timer kita terlihat seperti ini:

Our time when we last left itOur time when we last left itOur time when we last left it

Sekarang, kita akan buat timer lebih menarik. Kita lanjutkan dengan countdown.cs-script, yang terlihat seperti ini:

1
using UnityEngine;
2
using System.Collections;
3
4
public class Countdown : MonoBehaviour {
5
6
    float timer = 60f;
7
    public AudioClip soundBlip;
8
    
9
    void Update (){
10
      if (timer > 0f){
11
            timer -= Time.deltaTime;
12
    	} else {
13
            timer = 0f;
14
    	}
15
    	
16
    	if (timer < 10f) {
17
            GetComponent<TextMesh>().color = Color.red;
18
    	} else if (timer < 20f) {
19
            GetComponent<TextMesh>().color = Color.yellow;
20
    	}
21
    	
22
    	GetComponent<TextMesh>().text = timer.ToString("F2");
23
    }
24
}

Membuatnya berbunyi

Kita buat timer kita berbunyi tiap detik, agar pemain tahu bahwa timer berkurang walau tidak melihat.

Pertama, kita perlu efek suara blip. Kamu bisa menemukan file audio pada file sumber, atau buat sendiri menggunakan BFXR. Setelah kamu memiliki satu, salin file tersebut ke folder asset.

Tambahkan komponen AudioSource pada objek hitung mundur menggunakan Component > Audio > AudioSource. Tambahkan variabel ini pada skrip hitung mundur:

1
public AudioClip soundBlip;

Kamu juga perlu mengatur file suara ke variabel soundBlip:

Select Blip01Select Blip01Select Blip01

Dan tambahkan blok berikut pada fungsi Update:

1
if (Mathf.Round(timer * 100) / 100 % 1f == 0) {
2
    GetComponent<AudioSource>().PlayOneShot(soundBlip);
3
}

Ini akan memeriksa apakah timer berada pada detik penuh, dan jika iya kita jalankan file suara.

Cara kerja kode ini cukup rumit. Yang dilakukan adalah membulatkan bilangan real timer menjadi dua nilai desimal, lalu membaginya dengan 1 lalu melihat apakah ada sisa pembagian. Jika sisa pembagian bernilai nol, artinya timer mencapai detik penuh, dan suara blip bisa dijalankan.

Jika kita tidak melakukan ini, sistem mungkin akan menjalankan suara lebih sering, dan mungkin tidak menyenangkan untuk pemain.

Kecepatan berbeda

Ini akan memberi pengali yang akan mengurangi atau mempercepat kecepatan timer. Tambahkan variabel berikut di awal:

1
float multiplier = 0.6f;

Temukan baris yang mengurangi timer berikut:

1
timer -= Time.deltaTime;

Ubahlah menjadi sebagai berikut:

1
timer -= Time.deltaTime * multiplier;

Jika pengali di bawah 1.0, timer akan berjalan lebih lambat, dan jika di atas 1.0 akan berjalan lebih cepat. Mengaturnya menjadi 1.0 tidak mengubah apa-apa.

Cobalah mencari nilai yang baik! Saya rasa kecepatan yang lebih lambat, seperti 0.85f, akan membuat pemain lebih merasakan timer.

Melambatkan saat nilai rendah

Sekarang kita memiliki komponen pengali, kita bisa mengubahnya saat permainan.

Pindahlah ke bagian kode mengubah warna:

1
if (timer < 10f) {
2
    GetComponent<TextMesh>().color = Color.red;
3
} else if (timer < 20f) {
4
    GetComponent<TextMesh>().color = Color.yellow;
5
}

Di sini kita sudah memiliki kondisi di mana perubahan kecepatan sudah tepat, jadi kita cukup menambahkannya!

1
if (timer < 10f) {
2
    GetComponent<TextMesh>().color = Color.red;
3
    multiplier = 0.6f;
4
} else if (timer < 20f) {
5
    GetComponent<TextMesh>().color = Color.yellow;
6
    multiplier = 0.8f;
7
} else {
8
    multiplier = 1.0f;
9
}

Saat timer berubah menjadi kuning saat 20 detik, timer akan berjalan dengan kecepatan 80%. Begitu menjadi merah, kecepatannya turun menjadi 60%. Jika tidak, kecepatannya 100%.

Memperbesar ketika rendah

Cara lain untuk membuat timer yang wkatunya tinggal sedikit lebih mencolok adalah dengan memperbesar ukurannya setiap detik. Karena kita sudah punya kode yang dijalankan setiap detik, kita tinggal memodifikasinya!

Pertama, kita perlu fungsi untuk memperbesar dan memperkecil ukuran timer. Tambahkan fungsi berikut:

1
private bool isBlinking = false;
2
private IEnumerator Blink() {
3
    isBlinking = true;
4
    float startScale = transform.localScale.x;
5
    transform.localScale = Vector3.one * startScale * 1.4f;
6
    yield return new WaitForSeconds(0.3f);
7
    transform.localScale = Vector3.one * startScale;
8
    isBlinking = false;
9
}

Ini adalah sebuah IEnumerator, tipe fungsi yang bisa berisi perintah wait. Kita perlu variabel isBlinking untuk memastikan kita tidak memanggilnya beberapa kali.

Begitu diinisialisasi, fungsi akan memperbesar ukuran objek dengan skala sampai 1.4f, menunggu 0.3 detik, lalu memperkecil kembali ke ukuran asal.

Kita bisa panggil dengan kode berikut:

1
if (Mathf.Round(timer * 100) / 100 % 1f == 0) {
2
    GetComponent<AudioSource>().PlayOneShot(soundBlip);
3
4
    if (timer < 10f) {
5
        if(!isBlinking) {
6
            StartCoroutine(Blink());
7
        }
8
    }
9
}

Sebuah IEnumerator perlu diinisialisasi dengan memanggilnya via StartCoroutine, jika tidak, fungsi itu tidak akan bekerja.

Keseluruhan blok akan dipanggil ketika dijalankan kedua kali, yang merupakan saat kita memeriksa apakah timer cukup rendah untuk membuatnya berkedip.

Berkedip saat nol

Kita lakukan sesuatu saat timer habis. Akan membosankan jika tidak ada perubahan saat timer habis, jadi kita buat timer berkedip.

Pertama, kita perlu sebuah fungsi IEnumerator lagi:

1
private bool isZeroBlinking = false;
2
private IEnumerator ZeroBlink() {
3
    isZeroBlinking = true;
4
    GetComponent<Renderer>().enabled = false;
5
    yield return new WaitForSeconds(1.5f);
6
    GetComponent<Renderer>().enabled = true;
7
    yield return new WaitForSeconds(1.5f);
8
    isZeroBlinking = false;
9
}

Ini akan mengubah timer on dan off dengan interval 1.5 detik. Panggil fungsi tersebut di blok kode yang memeriksa timer habis.

1
if (timer > 0f){
2
    timer -= Time.deltaTime * multiplier;
3
} else {
4
    timer = 0f;
5
    if(!isZeroBlinking) {
6
        StartCoroutine(ZeroBlink());
7
    }
8
}

Sebelum menjalankannya, kita perlu menghilangkan bunyi dan berkedip saat nol, jika tidak perilakunya akan bertabrakan.

Ubah kondisi pada blok tersebut untuk memeriksa apakah detik sudah berlalu dan periksa juga jika waktu lebih besar dari nol:

1
if (Mathf.Round(timer * 100) / 100 % 1f == 0 && timer > 0f) {
2
    GetComponent<AudioSource>().PlayOneShot(soundBlip);
3
    
4
    if (timer < 10f && timer > 0f) {
5
        if(!isBlinking) {
6
            StartCoroutine(Blink());
7
        }
8
    }
9
}

Ini akan memastikan efek berkedip dan berkedip saat nol bekerja tanpa mengganggu satu sama lain.

Keseluruhan skrip countdown akan terlihat seperti ini:

1
using UnityEngine;
2
using System.Collections;
3
4
public class Countdown : MonoBehaviour {
5
    
6
    float timer = 5f;
7
    float multiplier = 0.6f;
8
    public AudioClip soundBlip;
9
    
10
    void Update (){
11
        if (timer > 0f){
12
            timer -= Time.deltaTime * multiplier;
13
        } else {
14
            timer = 0f;
15
            if(!isZeroBlinking) {
16
                StartCoroutine(ZeroBlink());
17
            }
18
        }
19
    
20
        if (timer < 10f) {
21
            GetComponent<TextMesh>().color = Color.red;
22
            multiplier = 0.6f;
23
        } else if (timer < 20f) {
24
            GetComponent<TextMesh>().color = Color.yellow;
25
            multiplier = 0.8f;
26
        } else {
27
            multiplier = 1.0f;
28
        }
29
    
30
        if (Mathf.Round(timer * 100) / 100 % 1f == 0 && timer > 0f) {
31
            GetComponent<AudioSource>().PlayOneShot(soundBlip);
32
            
33
            if (timer < 10f && timer > 0f) {
34
                if(!isBlinking) {
35
                    StartCoroutine(Blink());
36
                }
37
            }
38
        }
39
    
40
        GetComponent<TextMesh>().text = timer.ToString("F2");
41
    }
42
    
43
    private bool isBlinking = false;
44
    private IEnumerator Blink() {
45
        isBlinking = true;
46
        float startScale = transform.localScale.x;
47
        transform.localScale = Vector3.one * startScale * 1.4f;
48
        yield return new WaitForSeconds(0.3f);
49
        transform.localScale = Vector3.one * startScale;
50
        isBlinking = false;
51
    }
52
    
53
    private bool isZeroBlinking = false;
54
    private IEnumerator ZeroBlink() {
55
        isZeroBlinking = true;
56
        GetComponent<Renderer>().enabled = false;
57
        yield return new WaitForSeconds(1.5f);
58
        GetComponent<Renderer>().enabled = true;
59
        yield return new WaitForSeconds(1.5f);
60
        isZeroBlinking = false;
61
    }
62
}

Ini akan membuat pekerjaan selesai. Kamu tentu saja bisa membuatnya lebih rapi dan menggabungkan perintah-perintah tersebut menjadi kode yang lebih efisien.

Kesimpulan

Hitung mundur biasa kita sudah menjadi lebih menarik. Jika kamu buat ini sekali, kamu bisa menggunakannya ke semua proyek yang kamu buat, seberapa kecil pun game tersebut.

Sekarang buatlah dan masukkan ke dalam game!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Game Development tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.