Cara Mendesain Behavior Tree agar NPC Kompleks Tetap Mudah Diatur

Behavior Tree biasanya terlihat sangat rapi ketika NPC hanya mempunyai tiga perilaku.

Namun setelah game berkembang, tree mulai dipenuhi pengecekan health, target, cover, ammunition, suara, alert level, squad order, hingga objective.

Graph yang awalnya mudah dibaca bisa berubah menjadi labirin. Karena itu, Cara Mendesain Behavior Tree untuk karakter kompleks bukan sekadar mengetahui fungsi Sequence dan Selector.

Developer juga perlu memikirkan modularitas, prioritas, interruption, data flow, serta debugging sejak awal agar sistem AI tetap mudah dikembangkan setelah proyek bertambah besar.

Desain dari Perilaku, Bukan dari Node

Kesalahan yang sering terjadi adalah membuka Behavior Tree Editor lalu langsung menambahkan node.

Pendekatan yang lebih baik adalah menulis perilaku karakter dalam bahasa sederhana terlebih dahulu.

Contohnya:

“Ketika tidak ada ancaman, penjaga berpatroli. Jika mendengar suara, ia menyelidiki. Jika melihat musuh, ia bertarung. Jika health sangat rendah, ia mencoba mundur.”

Dari deskripsi tersebut, empat state perilaku utama sudah terlihat: Patrol, Investigate, Combat, dan Retreat.

Barulah masing-masing state diterjemahkan menjadi subtree.

Teknik ini menjaga tree tetap dekat dengan desain gameplay. Designer juga lebih mudah memahami logic tanpa harus membaca implementasi teknis.

Gunakan Selector sebagai Sistem Prioritas

Karakter kompleks hampir selalu menghadapi beberapa kebutuhan secara bersamaan.

NPC bisa sedang mengejar pemain tetapi pada saat sama health-nya rendah dan granat jatuh di dekatnya.

Behavior Tree membutuhkan aturan untuk menentukan mana yang harus ditangani dulu.

Gunakan Selector berdasarkan urgency:

Avoid Immediate Danger → Survival → Combat → Objective → Idle

Fallback dalam BehaviorTree.CPP bekerja dengan mencoba child secara berurutan sampai salah satunya berhasil. Karena itu, posisi node dapat digunakan sebagai bentuk priority system.

Urutan tersebut harus mencerminkan desain karakter.

NPC pemberani bisa mempertahankan Combat lebih lama sebelum Retreat. NPC pengecut dapat memberikan prioritas tinggi pada Survival.

Dengan struktur serupa tetapi parameter berbeda, developer dapat menciptakan variasi karakter tanpa membuat AI baru dari nol.

Bedakan Condition, Action, dan Data

Tree yang sulit dirawat biasanya mencampurkan tiga hal sekaligus.

Condition menjawab pertanyaan: “Apakah tindakan ini boleh dilakukan?”

Action benar-benar menjalankan sesuatu, seperti bergerak atau menembak.

Data menyimpan keadaan dunia yang digunakan oleh keduanya.

Pada Unreal Engine, Decorator berfungsi sebagai condition untuk menentukan apakah cabang dapat dieksekusi, Task menjalankan pekerjaan AI, sedangkan Blackboard menyimpan informasi yang dipakai tree dalam pengambilan keputusan.

Pertahankan pembagian tersebut.

Jangan membuat Task AttackTarget sekaligus mencari musuh, mengecek health, memutuskan weapon, menentukan cover, dan melakukan serangan.

Semakin banyak responsibility di satu node, semakin sulit node itu dipakai ulang.

Gunakan Blackboard dengan Disiplin

Blackboard sangat berguna, tetapi juga bisa berubah menjadi tempat sampah global.

Jika setiap node bebas menambahkan variable baru, developer akhirnya memiliki puluhan key dengan fungsi yang tidak jelas.

Gunakan naming yang konsisten seperti:

TargetActor, TargetLocation, HasLineOfSight, CurrentState, CoverPosition, atau AlertLevel.

Unreal Engine memungkinkan Blackboard menyimpan user-defined Keys dan bahkan memiliki parent Blackboard untuk mewarisi key dari aset lain.

Inheritance seperti ini berguna pada banyak tipe NPC.

Semua karakter dapat memakai Blackboard dasar berisi position dan target. AI combat kemudian memiliki tambahan ammo, cover, dan threat level, sedangkan civilian mempunyai panic level serta safe destination.

Jangan menyimpan data yang sebenarnya hanya dibutuhkan sebentar oleh satu Task jika tidak perlu dibagikan.

Blackboard harus menjadi shared context, bukan pengganti seluruh variable lokal.

Gunakan Reactive Behavior untuk Perubahan Mendadak

Karakter kompleks harus mampu mengubah keputusan ketika situasi berubah.

Misalnya NPC sedang membuka pintu untuk mengejar pemain. Saat itu muncul granat di lantai.

AI tidak seharusnya terus menyelesaikan animasi membuka pintu hanya karena branch tersebut sudah dimulai.

Pada BehaviorTree.CPP, ReactiveSequence dan ReactiveFallback memungkinkan condition sebelumnya dievaluasi ulang sehingga tindakan asynchronous bisa diinterupsi ketika kondisi berubah.

Unreal mempunyai konsep serupa melalui Decorator dan Observer Aborts. Sebuah perubahan pada Blackboard dapat menyebabkan branch sendiri atau branch berprioritas lebih rendah dibatalkan.

Gunakan interruption untuk ancaman yang memang perlu respons langsung.

Namun jangan membuat setiap condition reactive.

Reevaluasi terlalu banyak kondisi setiap saat dapat menambah kompleksitas dan menghasilkan NPC yang terus berganti keputsan sebelum menyelesaikan tindakan apa pun.

Pecah Tree Besar Menjadi Subtree

Jika satu Behavior Tree tidak muat nyaman di layar, itu biasanya sinyal bahwa struktur perlu dibagi.

Gunakan subtree sesuai domain.

Misalnya:

BT_Combat, BT_Investigation, BT_Patrol, BT_Retreat, dan BT_Social.

Main Behavior Tree hanya menentukan subtree yang harus aktif.

BehaviorTree.CPP mendukung komposisi perilaku besar menggunakan subtree reusable. Unity Behavior juga dirancang dengan arsitektur modular, hierarchical design, dan reusable subgraphs.

Pendekatan ini membuat pengembagan AI lebih scalable.

Jika logic mencari cover mengalami bug, developer cukup membuka Combat subtree daripada menelusuri graph dengan 200 node.

Subtree juga memungkinkan beberapa karakter berbagi sistem dasar tetapi menggunakan variasi tertentu.

Hindari Tree yang Terlalu Dalam

Modularitas penting, tetapi terlalu banyak nesting juga dapat menjadi masalah.

Bayangkan developer harus membuka enam tingkat subtree hanya untuk menemukan node ReloadWeapon.

Struktur seperti itu mengurangi keterbacaan.

Gunakan hierarki berdasarkan konsep yang memang berbeda, bukan hanya karena ingin memecah graph.

Behavior Tree dikenal karena sifat hierarkis dan modularnya.

Survey akademis tentang Behavior Trees mencatat bahwa pemisahan logic menjadi struktur hierarkis menjadi salah satu alasan BT lebih mudah diperluas dan digunakan kembali dibanding beberapa pendekatan FSM kompleks.

Tetapi modular bukan berarti setiap tiga node harus menjadi subtree.

Cari level abstraksi yang masuk akal untuk tim.

Jangan Memproses Semua Hal Setiap Frame

NPC kompleks dapat memiliki perception, target selection, navigation, cover analysis, tactical scoring, dan berbagai sistem lain.

Jika seratus NPC mengevaluasi semuanya setiap frame, CPU cost dapat meningkat dengan cepat.

Tidak semua data membutuhkan update 60 kali per detik.

Posisi musuh dekat mungkin perlu diperbarui sering. Pilihan patrol point mungkin hanya perlu dihitung ketika waypoint sebelumnya selesai.

Unity Behavior menggunakan arsitektur event-driven untuk mendukung reaksi dinamis, sementara Unreal Behavior Trees juga memakai event-driven implementation untuk sejumlah perubahan kondisi daripada melakukan polling seluruh tree setiap frame.

Gunakan event ketika memungkinkan.

Misalnya perception system mengirim perubahan TargetActor hanya ketika target terlihat atau hilang.

Pendekatan ini dapat membuat tree lebih bersih sekaligus mengurangi pekerjaan yang tidak dibutuhkan.

Bangun Debugging ke Dalam Sistem AI

Semakin kompleks karakter, semakin penting kemampuan memahami mengapa NPC melakukan sesuatu.

Jangan hanya menampilkan current Task.

Tampilkan target aktif, state utama, alert level, destination, health, branch priority, serta Blackboard key penting.

Unity Behavior menyediakan real-time debugging visualization dalam Play mode. Unreal Behavior Tree Editor juga dapat memperlihatkan Blackboard Keys dan branch yang sedang berjalan saat debugging.

Tambahkan debug text di atas NPC pada development build.

Contohnya:

State: Combat
Target: Player
Decision: SeekCover
Reason: HealthLow

Informasi seperti ini jauh lebih berguna daripada sekadar melihat karakter berlari ke arah yang salah.

Debugging bukan fitur tambahan. Pada AI kompleks, debugging adalah bagian dari arsitektur.

Uji dengan Situasi yang Saling Bertabrakan

Behavior Tree paling sering gagal bukan ketika hanya satu kondisi aktif, tetapi ketika beberapa kondisi terjadi bersamaan.

NPC melihat pemain, health rendah, kehabisan peluru, mendengar ledakan, dan jalur menuju cover terhalang.

Apa yang harus dilakukan?

Buat test scenario yang sengaja menghasilkan konflik seperti ini.

Periksa apakah priority tree memberikan respons yang masuk akal dan apakah branch gagal memiliki fallback.

Misalnya, jika cover tidak tersedia, NPC dapat mencoba mundur. Jika jalur mundur juga gagal, ia mungkin tetap bertarung dari posisi sekarang.

Perhatikan juga konfigruasi timeout. Task yang tidak pernah mengembalikan Success atau Failure bisa membuat seluruh branch terjebak dalam status Running.

Semakin ekstrem pengujan yang dilakukan, semakin kecil kemungkinan AI menghasilkan perilaku aneh saat game dirilis.

Cara Mendesain Behavior Tree untuk NPC kompleks membutuhkan struktur prioritas, pemisahan data dan aksi, Blackboard yang disiplin, subtree modular, serta interruption yang terkendali. Hindari graph raksasa dan evaluasi berlebihan setiap frame.

Bangun debugging sejak awal, lalu uji beberapa kondisi yang bertabrakan sekaligus. Dengan struktur yang sehat, AI dapat terus berkembang tanpa membuat sistem sulit dipahami tim.