Personaggi nemici
In Unreal Engine, i PNG e i nemici sono generalmente configurati in modo molto simile al giocatore, in quanto un nemico ha un controller e una pedina. In effetti, i nemici e il giocatore condividono alcune funzioni in una classe di base comune, AParrotCharacterBase. Per il gioco Parrot, gli alberi di comportamento sono utilizzati per controllare il comportamento del nemico, quindi la classe Controller IA è usata per creare i nostri controller nemici. Inizieremo con la Blueprint di animazione, dal momento che quella configurazione è condivisa tra i nemici.
Le Blueprint di animazione nemici
Modelli di Blueprint di animazione
Per casi in cui hai mesh scheletriche diverse che altrimenti condividono identiche esigenze di animazione, puoi creare quello che si chiama un modello di Blueprint di animazione (vedi Animation Blueprint Linking). In questo caso, ci sono quattro tipi diversi di nemici: scheletro senza testa, scheletro, squalo e squalo capo. Poiché condividono tutti uno scheletro e una configurazione di animazione identici, può essere riutilizzato per ciascuno di essi un modello che implementa il grafico di animazione e il grafico eventi. Puoi visualizzare la modalità di configurazione di questo modello qui: Blueprint > Enemy > EnemyBase > ABT_EnemyBase. Sembra molto simile alla blueprint di animazione del giocatore perché un modello è configurato quasi nella stessa maniera.
Blueprint di animazione
In questo caso, tutta l'implementazione sta nel modello, mentre le animazioni sono invece assenti, poiché il modello non fa riferimento a uno scheletro specifico. Ciascuno dei nemici ha la sua blueprint di animazione derivata dal modello, e ciascuno ha le animazioni di quello scheletro inserite negli override del grafico di animazione. Puoi visualizzarne un esempio qui: Blueprint > Enemy > HeadlessSkeleton > ABP_Enemy_HeadlessSkeleton.
Di seguito, abbiamo selezionato le animazioni appropriate della mesh scheletrica dello scheletro senza testa per ciascuno stato di animazione.
La pedina nemica
I personaggi nemici di Parrot condividono molte funzioni con il giocatore; in particolare, i punti danno e funzioni simili (come la morte). L'implementazione condivisa è visibile in AParrotCharacterBase. Per l'implementazione specifica del nemico, abbiamo una sottoclasse AParrotEnemyCharacterBase. Questa gestisce tutta l'implementazione del funzionamento del sistema di pattugliamento, del combattimento e altro ancora. Puoi saperne di più sul funzionamento del combattimento nella documentazione Combattimento su Parrot.
In questa configurazione, i controlli dei danni e delle ferite da combattimento sono effettuati sul nemico con un'implementazione della modalità di trigger dei volumi nella classe di blueprint base che si trova qui: Blueprint > Enemy > EnemyBase > BP_EnemyCharacter_Base.
L'implementazione è effettuata qui, anziché gestita nella classe C++ nativa, perché i volumi trigger devono essere differenti per ogni nemico per via delle diverse forme, dimensioni e complessità delle loro mesh. Questo è necessario perché un volume trigger ereditato non può essere modificato nella classe derivata.
Il Controller IA nemico
Come menzionato in precedenza, i nemici sono controllati con alberi comportamentali, dunque esiste una classe di base derivata da AIController in AParrotEnemyAIControllerBase. Di seguito vedrai una gamma di BlueprintImplementableEvents utilizzati per inviare dati alla lavagna perché vengano usati dagli alberi comportamentali.
Puoi visualizzare come il Controller IA trasmette i dati nell'albero comportamentale e come gestisce la rilevazione della presenza di un giocatore in Blueprint > AI > EnemyBase > BP_EnemyController_Base.
Creazione di IA con gli alberi comportamentali
Unreal Engine offre un'infrastruttura potente e flessibile per costruire IA utilizzando alberi comportamentali. Una guida rapida per configurare il testo standard di base con alcuni comportamenti si trova nella Behavior Tree Quick Start Guide. I risultati di quella guida sono utilizzati come fondamento dell'IA del nemico e per apportare modifiche per la configurazione dei comportamenti necessari.
Abbiamo due task di alberi comportamentali, Blueprint > AI > EnemyBase > BTT_FindNextPatrol e Blueprint > AI > EnemyBase > BTT_AttackPlayer per fornire la funzionalità di base necessaria per il pattugliamento e per attaccare il giocatore. C'è una lavagna condivisa, Blueprint > AI > EnemyBase > BB_Enemy_Base, dato che l'infrastruttura per supportare tutte le funzioni è presente in ciascun nemico. Spetta all'implementazione degli alberi comportamentali decidere quali funzioni utilizzare per personalizzare i comportamenti dei nemici.
Ciascun nemico ha una configurazione di albero comportamentale diversa, cosicché ognuno si comporti in maniera differente. Puoi dare un'occhiata a tutti e quattro nei punti seguenti:
Blueprint > AI > HeadlessSkeleton > BT_HeadlessSkeleton
Blueprint > AI/Skeleton > BT_Skeleton
Blueprint > AI > Sharky > BT_Sharky
Blueprint > AI > BossShark > BT_Boss_Shark
Creazione di un sistema di punti di riferimento del pattugliamento personalizzabile
Per i nemici, Parrot non richiede la stessa funzionalità di pattugliamento illustrata nella guida agli alberi comportamentali, dove l'IA nemica seleziona a caso un punto raggiungibile entro un raggio ogni 4 secondi. Si desidera che i nemici seguano attivamente un percorso di pattugliamento avanti e indietro, come molti altri giochi platform.
Per questo Parrot ha creato il suo proprio sistema che fornisce la funzionalità necessaria. Consiste nel UParrotEnemyPatrolRigComponent che può essere posizionato nella scena per creare un pattugliamento. Utilizza oggetti secondari predefiniti della classe per istanziare una spline: la spline è usata per creare i punti di riferimento del pattugliamento, due volumi trigger (usati per attivare il comportamento dell'IA) e un visualizzatore solo editor che disegna l'ordinamento dei punti di riferimento. L'ordinamento dei punti di riferimento consente la direzione del percorso di pattugliamento da vedere al momento della modifica. Puoi vedere i dettagli dell'implementazione C++ in UParrotEnemyPatrolRigComponent.
Questa implementazione è un componente in modo che un rig di pattugliamento possa essere collegato a qualsiasi attore in una scena. Questo permette di posizionare un rig su un oggetto mobile e indica che il pattugliamento resterà correttamente posizionato nello spazio locale. Per posizionare un rig di pattugliamento che non sia collegato a un attore esistente in una scena, abbiamo AParrotEnemyPatrolRigActor, che è un attore posizionabile ovunque in una scena e genera un UParrotEnemyPatrolRigComponent come oggetto secondario predefinito su di sé.
Questa implementazione consente di selezionare un nemico da generare nel runtime per seguire il percorso di pattugliamento. Questo processo utilizza una funzione di Unreal Engine chiamata generazione differita di attore, che consente la generazione di un attore in due fasi: la prima costruisce l'oggetto attore senza effettuare alcuna inizializzazione AActor come BeginPlay. Ciò ti dà l’opportunità di effettuare qualsiasi configurazione o impostazione necessaria per l'attore prima che sia inizializzata. Dopo aver effettuato la configurazione, invochi la seconda fase per finalizzare la generazione e inizializzare l'attore. L'operazione si effettua per il rig di pattugliamento, quindi quando viene generato l'attore nemico, la spline di pattugliamento e i volumi trigger possono essere inviati nell'attore in modo da essere elaborati durante la sua inizializzazione e la sequenza di pattugliamento può iniziare automaticamente.
Puoi visualizzare il codice che esegue la generazione differita dell'attore in UParrotEnemyPatrolRigComponent. Una funzione simile esiste in blueprint, dove puoi taggare le proprietà su un attore blueprint come Esponi alla generazione, che ti permette di trasmettere gli argomenti nel nodo blueprint generato, che sono impostati prima che abbia luogo l'inizializzazione dell'attore.
Di seguito puoi vedere illustrato un esempio di come viene configurato uno di questi rig di pattugliamento in Maps > Level_1 > Level_1 con un rig di pattugliamento a due punti, che inizia al punto 0 sulla destra. Il rig di pattugliamento è configurato per generare un BP_EnemyCharacter_Skeleton.
Di seguito, è raffigurato un menu attiva/disattiva Mostra contrassegno che individua i punti di riferimento del rig di pattugliamento per una facile identificazione al momento della modifica. La maggior parte delle caselle di spunta mostra contrassegno è stata selezionata. Puoi vedere i dettagli di come questo sia implementato in un componente visualizzatore solo editor, UParrotPatrolRigDebugVisualizer.