Membuat Game FPS dengan Unreal Engine: Dari Proyek Baru sampai Musuh AI

Membuat Game FPS dengan Unreal Engine: Dari Proyek Baru sampai Musuh AI

Artikel ini memandu Anda membuat penembak orang pertama (FPS) dengan Unreal Engine 5, mulai dari klik menu pertama di Epic Games Launcher sampai musuh yang melihat pemain dan mengejarnya. Setiap bagian berupa langkah-langkah yang bisa Anda ikuti satu per satu. Artikel ini menunjukkan di mana setiap berkas kode harus diletakkan, dan diagram menunjukkan jalur keseluruhannya.

Yang Anda butuhkan

Anda memerlukan komputer Windows 10 atau 11, kartu grafis yang mendukung DirectX 12, ruang disk kosong minimal 100 GB, dan akun Epic Games gratis. Pasang Visual Studio 2022 dengan beban kerja Game development with C++ untuk mengompilasi kode C++. Jika Anda hanya ingin memakai Blueprint, Anda bisa mulai tanpa C++. Catatan: kode di sini ditulis berdasarkan dokumentasi Unreal Engine 5, tetapi belum dikompilasi dan diuji di mesin yang dipakai untuk menulis artikel ini. Hasil yang tercantum adalah apa yang seharusnya Anda lihat jika langkah-langkahnya dikerjakan dengan benar.

Ilustrasi

Jalur menu dari membuka Launcher sampai Unreal Editor
Jalur menu dari membuka Launcher sampai Unreal Editor

1. Pasang dan buat proyek FPS

Pertama pasang Unreal Engine melalui Epic Games Launcher, lalu buat proyek dari templat siap pakai.

1. Buka Epic Games Launcher dan masuk dengan akun Epic Games Anda

2. Di menu kiri, buka bagian Unreal Engine dan pilih tab Library

3. Klik + Add Version, pilih versi Unreal Engine 5 terbaru, lalu klik Install

4. Setelah pemasangan selesai, klik Launch untuk versi tersebut

5. Di Unreal Project Browser, pilih Games di panel kiri

6. Pilih templat First Person

7. Di bawah Project Defaults, pilih C++ jika Anda ingin menulis kode, atau Blueprint jika ingin mulai secara visual

8. Centang Starter Content untuk mendapatkan model dan material dasar

9. Beri nama proyek, misalnya FpsDemo, lalu klik Create

Yang seharusnya Anda lihat: Editor terbuka dengan level contoh dan karakter First Person. Menekan Play membuat Anda bisa berjalan dan memutar kamera.

2. Struktur proyek dan tempat skrip

Pelajari fungsi setiap bagian proyek. Kode C++ ditempatkan di folder Source, sedangkan Blueprint dan model berada di Content.

Catatan: Semua skrip C++ berada di Source/FpsDemo/. Blueprint dibuat dan diedit di dalam editor. Jangan mengedit berkas di Content/ secara manual.

Kode: project-tree.txt

FpsDemo/
├── FpsDemo.uproject        berkas proyek, klik dua kali untuk membuka di editor
├── Config/                 nilai awal game, seperti tombol kontrol
├── Content/                berkas game yang dibuat di editor, seperti Blueprint, model, level, suara
├── Source/
│   ├── FpsDemo/            kode C++ game, ditulis sebagai berkas .h dan .cpp
│   │   └── FpsDemo.Build.cs   menentukan pustaka apa yang dipakai modul ini, misalnya AIModule
│   ├── FpsDemo.Target.cs
│   └── FpsDemoEditor.Target.cs
└── Binaries/, Intermediate/, Saved/   berkas yang dibuat UE sendiri, tidak perlu diubah

3. Impor model 3D ke dalam proyek

Sebagian besar model disimpan sebagai berkas FBX. Dapatkan dari Fab atau sumber lain yang Anda punya izin untuk memakainya, dan periksa lisensinya sebelum dipakai di game Anda.

1. Di Content Browser di bagian bawah, klik kanan folder yang Anda inginkan, misalnya Content/Models

2. Pilih Import to /Game/Models lalu pilih berkas .fbx

3. Di jendela FBX Import Options, pilih Skeletal Mesh jika model memiliki kerangka, atau Static Mesh jika objeknya tetap

4. Centang Import Materials and Textures, lalu klik Import

5. Seret model dari Content Browser ke dalam level untuk mengujinya

Yang seharusnya Anda lihat: Model muncul di Content Browser, dan ketika Anda menyeretnya ke dalam level, ia berada di dalam adegan.

4. Atur kontrol dengan Enhanced Input

Unreal Engine 5 memakai sistem Enhanced Input untuk memisahkan penekanan tombol dari aksi, sehingga Anda bisa mengubah tombol tanpa mengedit kode.

1. Di Content Browser, buka folder Input yang datang bersama templat

2. Buka IA_Fire untuk memastikan ia adalah Input Action Digital (bool) untuk tombol tembak

3. Buka IMC_Default dan pastikan klik kiri mouse dipetakan ke IA_Fire

4. Untuk mengubah tombol, edit pemetaan di IMC_Default lalu klik Save

5. Tekan Play dan pastikan klik kiri memicu aksi tembak

Yang seharusnya Anda lihat: Menekan tombol yang dipetakan memanggil fungsi tembak pada karakter setiap kali.

5. Menembak dengan line trace

Sebagian besar senjata FPS memancarkan garis lurus tak terlihat dari kamera ke depan dan memeriksa apa yang tertabrak. Contoh ini memanggil LineTraceSingleByChannel dan memberikan kerusakan pada aktor yang terkena.

1. Buka Source/FpsDemo/FpsCharacter.h dan tambahkan variabel Range dan Damage serta deklarasi Fire seperti pada kode

2. Buka Source/FpsDemo/FpsCharacter.cpp dan tambahkan fungsi Fire

3. Di FpsCharacter.cpp, cari fungsi OnFire yang dibuat templat, lalu panggil Fire() sebagai ganti kode pembuatan proyektil

4. Tekan Ctrl+Alt+F11 atau klik Compile di editor untuk membangun kode

Kode: FpsCharacter_Fire.cpp

// Berkas: Source/FpsDemo/FpsCharacter.h  (tambahkan ke kelas karakter pemain yang dibuat templat)
//   UPROPERTY(EditAnywhere, Category = "Combat")
//   float Range = 10000.f;
//
//   UPROPERTY(EditAnywhere, Category = "Combat")
//   float Damage = 25.f;
//
//   void Fire();
//
// Berkas: Source/FpsDemo/FpsCharacter.cpp  (fungsi Fire di bawah)

#include "FpsCharacter.h"
#include "Camera/CameraComponent.h"
#include "Engine/World.h"
#include "Kismet/GameplayStatics.h"

void AFpsCharacter::Fire()
{
    if (!FirstPersonCameraComponent)
    {
        return;
    }

    // Titik awal adalah kamera, dan titik akhir adalah jarak Range ke arah kamera memandang
    const FVector Start = FirstPersonCameraComponent->GetComponentLocation();
    const FVector End = Start + FirstPersonCameraComponent->GetForwardVector() * Range;

    FHitResult Hit;
    FCollisionQueryParams Params;
    Params.AddIgnoredActor(this); // agar garis tembak tidak mengenai diri sendiri

    if (GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Visibility, Params))
    {
        if (AActor* Target = Hit.GetActor())
        {
            UGameplayStatics::ApplyDamage(Target, Damage, GetController(), this, UDamageType::StaticClass());
        }
    }
}

Yang seharusnya Anda lihat: Klik kiri pada suatu objek memberinya kerusakan. Output Log tidak menampilkan error ketika Anda menembak.

6. Musuh menerima kerusakan dan mati

Buat kelas musuh dari Character. Ia memiliki kesehatan, menerima kerusakan melalui TakeDamage, dan dihapus ketika kesehatannya mencapai nol.

1. Di editor, buka File > New C++ Class, pilih Character sebagai induk, dan beri nama EnemyCharacter

2. Buka EnemyCharacter.h dan tambahkan deklarasi seperti pada kode

3. Masukkan kode dari EnemyCharacter.cpp ke dalam berkas

4. Kompilasi, lalu buat Blueprint dari EnemyCharacter untuk ditempatkan di level

Kode: EnemyCharacter.cpp

// Berkas: Source/FpsDemo/EnemyCharacter.h
//   UCLASS()
//   class FPSDEMO_API AEnemyCharacter : public ACharacter
//   {
//       GENERATED_BODY()
//   public:
//       AEnemyCharacter();
//       virtual float TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent,
//                                AController* EventInstigator, AActor* DamageCauser) override;
//   protected:
//       UPROPERTY(EditAnywhere, Category = "Combat")
//       float Health = 100.f;
//   };
//
// Berkas: Source/FpsDemo/EnemyCharacter.cpp

#include "EnemyCharacter.h"
#include "EnemyAIController.h"

AEnemyCharacter::AEnemyCharacter()
{
    // Biarkan AI Controller musuh mengambil alih secara otomatis saat ditempatkan di adegan atau dibuat
    AIControllerClass = AEnemyAIController::StaticClass();
    AutoPossessAI = EAutoPossessAI::PlacedInWorldOrSpawned;
}

float AEnemyCharacter::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent,
                                  AController* EventInstigator, AActor* DamageCauser)
{
    const float Applied = Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);

    Health -= Applied;
    if (Health <= 0.f)
    {
        Destroy(); // ketika kesehatan habis, musuh hilang dari adegan
    }
    return Applied;
}

Yang seharusnya Anda lihat: Ketika Anda menembak musuh sampai kesehatannya mencapai nol, ia menghilang dari level.

7. Tambahkan level, properti, dan NavMesh

Musuh perlu berjalan di atas tanah, jadi level memerlukan NavMesh, yaitu peta area yang bisa dilalui. Tambahkan beberapa objek sebagai tempat berlindung juga.

1. Cari properti tambahan dari sumber yang Anda punya izin untuk memakainya, seperti Fab, lalu pilih Add to Project atau unduh dan impor

2. Seret objek dari Content Browser ke dalam level dan atur posisinya dengan alat Move dan Scale

3. Di Place Actors, cari Nav Mesh Bounds Volume dan seret ke dalam level

4. Ubah ukuran volume agar mencakup area yang bisa dilalui

5. Tekan P di editor untuk menampilkan NavMesh

Yang seharusnya Anda lihat: Pada tampilan P, tanah yang bisa dilalui ditampilkan dengan warna hijau, dan area di bawah objek tidak berwarna hijau.

8. AI Controller yang mendeteksi pemain

AI Controller adalah otak musuh. Ia memakai AI Perception untuk memeriksa apakah pemain terlihat, lalu menulis hasilnya ke Blackboard.

1. Buat kelas C++ dari AIController dengan nama EnemyAIController

2. Buka FpsDemo.Build.cs dan tambahkan "AIModule" ke PublicDependencyModuleNames

3. Masukkan kode .h dan .cpp ke dalam proyek dan kompilasi

4. Konstruktor musuh di EnemyCharacter menetapkan AI Controller, sehingga controller mengambil alih ketika musuh ditempatkan atau dibuat

Kode: EnemyAIController.cpp

// Berkas: Source/FpsDemo/EnemyAIController.h
//   UCLASS()
//   class FPSDEMO_API AEnemyAIController : public AAIController
//   {
//       GENERATED_BODY()
//   public:
//       AEnemyAIController();
//   protected:
//       virtual void BeginPlay() override;
//       UFUNCTION()
//       void OnTargetPerceptionUpdated(AActor* Actor, FAIStimulus Stimulus);
//       UPROPERTY(VisibleAnywhere)
//       UAIPerceptionComponent* Perception;
//       UPROPERTY()
//       UAISenseConfig_Sight* Sight;
//       UPROPERTY(EditAnywhere, Category = "AI")
//       UBehaviorTree* BehaviorTreeAsset;
//   };
//
// Berkas: Source/FpsDemo/EnemyAIController.cpp
// Harus menambahkan "AIModule" ke PublicDependencyModuleNames di FpsDemo.Build.cs terlebih dahulu

#include "EnemyAIController.h"
#include "BehaviorTree/BehaviorTree.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "Perception/AIPerceptionComponent.h"
#include "Perception/AISenseConfig_Sight.h"
#include "Perception/AIPerceptionTypes.h"

AEnemyAIController::AEnemyAIController()
{
    Perception = CreateDefaultSubobject<UAIPerceptionComponent>(TEXT("Perception"));
    SetPerceptionComponent(*Perception);

    Sight = CreateDefaultSubobject<UAISenseConfig_Sight>(TEXT("Sight"));
    Sight->SightRadius = 1500.f;          // jarak terjauh musuh masih bisa melihat
    Sight->LoseSightRadius = 1800.f;      // harus lebih jauh dari ini agar penglihatan hilang
    Sight->PeripheralVisionAngleDegrees = 90.f;
    Sight->DetectionByAffiliation.bDetectEnemies = true;
    Sight->DetectionByAffiliation.bDetectNeutrals = true;
    Sight->DetectionByAffiliation.bDetectFriendlies = true;

    Perception->ConfigureSense(*Sight);
    Perception->SetDominantSense(Sight->GetSenseImplementation());
    Perception->OnTargetPerceptionUpdated.AddDynamic(this, &AEnemyAIController::OnTargetPerceptionUpdated);
}

void AEnemyAIController::BeginPlay()
{
    Super::BeginPlay();
    if (BehaviorTreeAsset)
    {
        RunBehaviorTree(BehaviorTreeAsset);
    }
}

void AEnemyAIController::OnTargetPerceptionUpdated(AActor* Actor, FAIStimulus Stimulus)
{
    // ketika melihat pemain, tulis ke kunci TargetActor di Blackboard yang dipakai Behavior Tree
    if (UBlackboardComponent* BB = GetBlackboardComponent())
    {
        BB->SetValueAsObject(TEXT("TargetActor"), Stimulus.WasSuccessfullySensed() ? Actor : nullptr);
    }
}

Yang seharusnya Anda lihat: Ketika pemain masuk ke jarak dan sudut penglihatan musuh, kunci TargetActor di Blackboard berisi pemain.

9. Behavior Tree dan Blackboard

Behavior Tree adalah diagram keputusan, misalnya: jika ada target, bergerak ke sana dan menembak; jika tidak, berpatroli. Blackboard menyimpan data yang digunakan tree untuk mengambil keputusan.

1. Klik kanan di Content Browser, pilih Artificial Intelligence > Blackboard, lalu beri nama BB_Enemy

2. Buka BB_Enemy dan tambahkan kunci bernama TargetActor bertipe Object

3. Klik kanan lagi, pilih Artificial Intelligence > Behavior Tree, lalu beri nama BT_Enemy

4. Buka BT_Enemy dan atur Blackboard Asset-nya ke BB_Enemy

5. Tambahkan Selector di akar, lalu Sequence dengan kondisi Blackboard yang memeriksa apakah TargetActor terisi, diikuti tugas MoveTo yang memakai TargetActor

6. Di detail Blueprint musuh, atur aset Behavior Tree ke BT_Enemy pada kolom Behavior Tree di AI Controller

Yang seharusnya Anda lihat: Ketika musuh melihat pemain, ia bergerak menuju pemain. Ketika pemain keluar dari penglihatannya, ia berhenti mengikuti.

Lingkaran musuh: indra penglihatan mendeteksi pemain, AI controller menulis ke Blackboard, dan Behavior Tree memilih untuk bergerak atau menembak
Lingkaran musuh: indra penglihatan mendeteksi pemain, AI controller menulis ke Blackboard, dan Behavior Tree memilih untuk bergerak atau menembak

10. Bangun dan uji

Pastikan semuanya bekerja bersama, lalu perbaiki masalah yang umum.

1. Tekan Compile atau Ctrl+Alt+F11 untuk membangun kode C++

2. Tekan Play di editor dan berjalanlah menuju musuh

3. Tembak musuh sampai menghilang dan pastikan kerusakannya sesuai dengan nilai yang Anda atur

4. Buka Window > Developer Tools > Output Log untuk membaca peringatan dan error

Yang seharusnya Anda lihat: Game berjalan. Musuh menghadap pemain ketika melihatnya, kesehatan berkurang ketika ditembak, dan musuh menghilang ketika kesehatannya mencapai nol.

Langkah berikutnya

Berikutnya, tambahkan suara tembakan, sistem skor, menu awal, dan animasi musuh. Gunakan Unreal Engine Learning Portal dan dokumentasi Unreal Engine 5 di dev.epicgames.com/documentation sebagai referensi utama.

Ringkasan

Buat proyek FPS dari templat di Epic Games Launcher, impor model, tulis fungsi tembak dengan line trace dan kerusakan untuk musuh, atur AI Controller untuk mendeteksi pemain, lalu hubungkan ke Behavior Tree dan Blackboard. Setiap langkah berupa klik menu atau menempelkan kode sesuai urutan.