前書き

本記事は「Verseデバイス」を作成し、機能を実装することを理解している人向けとなります。Verseってなんぞや…という人には少し難しいかもしれませんので、一度別の記事やチュートリアルで勉強してみるのをオススメします。基本的に、用語や前提知識を知っている状態で進めていきます。

NPCスポナーとnpc_behavior

Verseファイルを作成する画面を見てみると、「NPC behavior basic」と呼ばれるテンプレートが用意されているはずです。これは、NPCを実装するうえで最低限必要なコードと一緒にファイルを作成してくれます。

今回は、こちらのテンプレートからNPCの機能を試していこうと思います。NPC Behavior Nameは自由に決めていただき、作成を押してみましょう。

Verseコードをビルドしてみると、Verseデバイスと同様にVerseクラスアセットが生成されるはずです。

これをレベル上にドラッグすると、NPCスポナーと呼ばれる専用のデバイスが配置されるはずです。VerseのNPCは全て「NPCスポナー」と紐づけてスポーンさせたり、デスポーンさせたりの処理を行います。イベントバインディングやVerseでスポーンさせる機能を呼び出したり、時間経過で自動でスポーンする設定をしたりと、一般的な仕掛けと同じような扱いです。

    # Used to spawn NPCs made with Character Definition asset.
    npc_spawner_device<public> := class<concrete><final>(creative_device_base):
        # Signaled when a character is spawned.
        # Sends the `agent` character who was spawned.
        SpawnedEvent<public>:listenable(agent) = external {}

        # Signaled when a character is eliminated.
        # `Source` is the `agent` that eliminated the character. If the character was eliminated by a non-agent then `Source` is 'false'.
        # `Target` is the character that was eliminated.
        EliminatedEvent<public>:listenable(device_ai_interaction_result) = external {}

        # Enables this device. Characters will start to spawn.
        Enable<public>():void = external {}

        # Disables this device. Characters will despawn if *Despawn AIs When Disabled* is set.
        Disable<public>():void = external {}

        # Resets the spawn count allowing spawning of a new batch of characters.
        Reset<public>():void = external {}

        # Tries to spawn a character.
        Spawn<public>():void = external {}

        # Despawns all characters. If set, `Instigator` will be considered as the eliminator of those characters.
        DespawnAll<public>(Instigator:?agent):void = external {}

Verseの定義にも、「npc_spawner_device」として用意されています。

NPCキャラクター定義

ここで、NPCスポナーを扱ううえで必要な要素である「NPCキャラクター定義」についても見ていきます。

VerseだけではNPCの見た目や移動速度、その他細かいパラメーターの調整を行うことができません。そのため、「AI > NPCキャラクター定義」に用意されているこちらのアセットを使用します。

アセット作成後は、NPCスポナー内の「NPCキャラクター定義」に作成したものを入れることができます。

NPCスポナーが複数個あった場合、同じNPCキャラクター定義を使うこともあれば、スポナーごとに別々のアセットを作成して分けることもあります。

定義を開いてみると、キャラクタービジュアルや体力の数値など、キャラクター自信の個性を決めるパラメータがいくつも用意されています。これらはまた後々解説しますが、現状は「VerseのNPC」と「NPCキャラクター定義」はセットで使われる、と覚えていただければ大丈夫です。

npc_behavior

using { /Fortnite.com/AI }
using { /Verse.org/Simulation }
 
# Getting started: https://www.epicgames.com/fortnite/en-US/creative/docs/uefn/Verse/onboarding-guide-to-programming-with-verse-in-unreal-editor-for-fortnite

# A Verse-authored NPC Behavior that can be used within an NPC Character Definition or an NPC Spawner device's NPC Behavior Script Override.
new_npc_behavior_basic := class(npc_behavior):

    # This function runs when the NPC is spawned in the world and ready to follow a behavior.
    OnBegin<override>()<suspends>:void=
        # TODO: Replace this with your code
        Print("Hello, NPC!")

    # This function runs when the NPC is despawned or eliminated from the world.
    OnEnd<override>():void=
        # TODO: Replace this with your code
        Print("Goodbye, NPC!")

さて、Verseの方に戻って基本的な部分を見ていきます。

npc_behaviorはVerseデバイスと同様に、OnBeginと呼ばれる関数をオーバーライドすることができます。Verseデバイスの場合はゲーム開始と同時に呼び出されていましたが、NPCの場合はNPCスポナーからスポーンされると同時にOnBeginが呼び出されます。

試しにゲーム内で確認をしてみると、スポーンのタイミングで「Hello, NPC!」が、倒したりデスポーンをさせると「Goodbye, NPC!」と左上に表示されるはずです。

OnEndに関してはVerseデバイスでは使うことはなかったかもしれません(一応用意はされていますが)。ただ、NPCはゲームの状況に合わせて人数が増えたり減ったり、はたまた何体も連続でスポーンやデスポーンが繰り返されるなど、常にNPCが存在しているとは限りません。

そのため、OnEndを使って「倒された際は○○という処理を停止する」といった処理を書くことで、ゲームを安定して動かすことができるようになるのです。

GetAgent

    # Inherit from this to create a custom NPC behavior.
    # The npc_behavior can be defined for a character in a CharacterDefinition asset, or in a npc_spawner_device.
    npc_behavior<native><public> := class<abstract>:
        # This function is called when the NPC is added to the simulation.
        OnBegin<native_callable><public>()<suspends>:void = external {}

        # This function is called when the NPC is removed from the simulation.
        OnEnd<native_callable><public>():void = external {}

        # Returns the agent associated with this behavior.
        GetAgent<native><public>()<transacts><decides>:agent

npc_behaviorには「GetAgent」と呼ばれる失敗関数が用意されています。これは、スポーンしたNPC自体を指す「agent」を取得する関数です。

フォートナイトのプレイヤーはagentと呼ばれる型で定義されています。同様に、NPCもagentと呼ばれる型で定義されています。agentは仕掛けに対して情報を渡す際や、「誰」に「何」をするかの指示をする際に重要な要素となっています。

using { /Fortnite.com/AI }
using { /Verse.org/Simulation }
using { /Fortnite.com/Characters }
 
# Getting started: https://www.epicgames.com/fortnite/en-US/creative/docs/uefn/Verse/onboarding-guide-to-programming-with-verse-in-unreal-editor-for-fortnite

# A Verse-authored NPC Behavior that can be used within an NPC Character Definition or an NPC Spawner device's NPC Behavior Script Override.
new_npc_behavior_basic := class(npc_behavior):

    # This function runs when the NPC is spawned in the world and ready to follow a behavior.
    OnBegin<override>()<suspends>:void=
        # TODO: Replace this with your code
        Print("Hello, NPC!")

        if:
            NPCAgent := GetAgent[]
            NPCCharacter := NPCAgent.GetFortCharacter[]
        then:

    # This function runs when the NPC is despawned or eliminated from the world.
    OnEnd<override>():void=
        # TODO: Replace this with your code
        Print("Goodbye, NPC!")

実際に使う場合はこのように記述します。GetAgent自体はnpc_behaviorの一部であるため、npc_behavior内であれば先頭に何かを付け足す(○○.GetAgent[]」とする必要はありません。また、プレイヤー同様にfort_characterに変換することもできます。Damage関数を呼び出したり、IsOnGround関数で着地しているかなど、fort_characterの機能も一通り使えます。

次回

次回はNPCに行動をさせるための方法を紹介します。例えばNavigateToという関数を使って、目的地まで歩かせたり…NPCの一番楽しい部分が始まるので、楽しみにしておきましょう。