トレース ソース フィルタリングの実行方法

Trace Source Filtering を実装して Animation Insights トレースを最適化する方法を説明します。

Choose your operating system:

Windows

macOS

Linux

前提トピック

このページは以下のトピックへの知識があることを前提にしています。まず以下のトピックの内容についてご確認をお願いします。

このガイドではユース ケースを 2 つ実装して、作成したプロジェクトで Trace Source Filtering を使用する方法を学びます。たとえば 2 番目のユース ケースを実装すると、以下に示すビデオのプレイヤー ポーンのレイキャストが、立っているアクタにヒットした時に Trace Source Filtering でアクタをフィルタできます。

アクタをフィルタする方法に注目してください

必要なセットアップ

この操作ガイドでは [Games (ゲーム)] > [Third Person Template (サードパーソン テンプレート)] プロジェクトを使用し、 [C++] [No Starter Content (スターター コンテンツ無し)] を有効にして Animation Starter Pack (アニメーション スターター パック) ( Epic Games マーケットプレイスから入手 ) を利用します。

  1. 立っているスケルタルメッシュ アクタと屈んでいるスケルタルメッシュ アクタを 1 つずつシーンに追加します。

    右:Equip_Rifle_Standing 左:Crouch_Idle_Rifle_Ironsights

  2. 立っているスケルタル メッシュ アクタを選択し、 Standing アクタ タグでタグ付けします。

  3. この手順を繰り返して、しゃがんでいるスケルタル メッシュ アクタにもタグを付けます。

    HT_ReqSetup_2.png

Trace Source Filtering

概要

大規模なプロジェクトで Animation Insights を使用する場合は、アプリケーションのオーバーヘッドと使用するディスク容量に限度を設けることが不可欠です。次の例では Animation Insights がシーンにあるすべてのアクタのトレース データを出力しています。

今後このプロジェクトが数千のオブジェクトを含むようになると、パフォーマンスの問題を特定するのが困難になります。

そこで Trace Source Filtering を使用してトレース データを出力するゲームプレイ オブジェクトを選択することで、Animation Insights がトレースするデータ量を減らすことができます。以下の手順で Trace Source Filtering を有効化します。

  1. [Animation Insights] [Menu] > (Filtering) [Trace Source Filtering] の順に選択します。

    HT_TraceSourceFiltering_1.png

  2. [Trace Source Filtering] で [Options] > [Visualize (視覚化する)] > [Actor Filtering] を有効化します。

    HT_TraceSourceFiltering_2.png

  3. Trace Source Filtering がエディタで実行されていることを確認するには、アクティブ レベルのエディタ ビューポート (PIE セッション) でそのレベルをプレイします。すると以下のように表示されるはずです。

    Trace Source Filtering により、シーンに内すべてのアクタ周辺にボックスをレンダリング。

  4. Trace Source Filters を実行するには、[Options] > [Visualize] > [Only Actor(s) passing Filtering] を有効にします。

    HT_TraceSourceFiltering_3.png

PIE セッションでレベルをプレイして Actor Filtering と Only Actor(s) passing Filtering の両方を有効にすると、フィルタがまだ実行されていないので、Trace Source Filtering 機能はシーン内のすべてのアクタを視覚化します。

HT_TraceSourceFiltering_EndResult.png

Trace Source Filtering を有効にした Animation Insights

すでに Trace Source Filtering を有効化したので、フィルタをいくつか実装して Animation Insights が出力するトレース データ量を制限できます。ここからガイドではユースケースをいくつか示し、各ユースケースごとにブループリントと C++ (ネイティブ) でフィルタの実装を行います。

ユースケース 1

ここでは、プレイヤー ポーンの位置から指定した範囲に存在する、タグ付きのアクタを対象とするフィルタを実装します。このユースケースを踏まえながら、以下のフィルタを実装していきます。

実装タイプ

フィルター名

使用

Blueprint

HasTag

指定したアクタ タグを持つアクタをフィルタします。

Native

DistanceToPlayer

プレイヤー ポーンの位置から指定した範囲に存在するアクタをフィルタします。デフォルトの範囲は 300 Unreal 単位 (cm) と定義します。

実装したフィルタを組み合わせることで、タグが付ついたアクタがプレイヤー ポーンの指定した範囲内にある場合に、そのアクタをフィルタして Animation Insights がトレース データを記録するようにします。このセクションの最後までに、以下のようなフィルタ ロジックでフィルタがユース ケースの要件を満たすようにします。

フィルタ ロジック

True を返す

False を返す

DistanceToPlayer AND HasTag

フィルタを通すアクタ

フィルタで除くアクタ

フィルタ ロジックを定義するときは要件を完全な文章に起こすと、ロジックの潜在的な欠陥を実装前に特定しやくなります。

HasTag ブループリント フィルタ

  1. [Trace Source Filtering] ダイアログ ボックスで [Add Filter (フィルタを追加)] > [Create new Filter Blueprint (新しい Filter Blueprint を作成する)] の順に選択します。

    HT_HasTagBPFilter_1.png

  2. [Save Asset As] メニュー ページが表示されたら、「 /Game/ 」配下に新しい「 FilterBP 」フォルダを作成します。

    HT_HasTagBPFilter_2.png

  3. このアセットを「 /Game/FilterBP/ 」配下に HasTag として保存します。

  4. HasTag Blueprint エディタで、 [Functions] > (Function) [Override] > [Does Actor Pass Filter] の順に選択します。

    HT_HasTagBPFilter_3.png

  5. 以下の詳細に従って新しい変数を追加します。

    • 変数名: ActorTag

    • 変数の型: String

    • インスタンス編集可能: Enabled

    • ツールチップ: Actor Tag Name

  6. デフォルト値を定義するには、ブループリントをコンパイルします。

  7. [Details (詳細)] パネルで ACTOR TAG をデフォルト値に指定します。

    HT_HasTagBPFilter_4.png

  8. 以下のブループリントによって Does Actor Pass Filter 関数を定義します。

    クリックしてフルサイズで表示。

  9. [My Blueprint] パネルの Trace Source Filtering カテゴリから Get Tool Tip Text 関数を選択して [Implement Function (関数を実装する)] を選択します。

    HT_HasTagBPFilter_6.png

  10. 以下のブループリントによって Get Tool Tip Text 関数を定義します。

    クリックしてフルサイズで表示。

    {0} 形式のプレースホルダーを使用します。テキストの書式設定に関する詳細は「 テキストのローカライズ

  11. 以下のブループリントによって Get Display Text 関数を定義します。

    クリックしてフルサイズで表示。

  12. コンパイルと保存をしてから HashTag ブループリント エディタを閉じると HashTag ブループリント フィルタがフィルタ欄に表示されます。

    クリックしてフルサイズで表示。

    [Add Filter (フィルタを追加)]

  13. HashTag フィルタをクリックして「 ACTOR TAG 」を「 Crouching 」に変更し、アクタ タグ名を定義します。

    HasTag Filter

  14. この「必要な設定を行う」セクションで正しくアクタにタグ付けできたかどうかを確認するには PIE セッションを実行します。

    左側の「Crouching」とタグ付けしたアクタが PIE セッションでフィルタされます。

    HasTag ブループリント フィルタが想定どおり動作することを確認したら、次に DistanceToPlayer ネイティブ フィルタを実装します。

    HasTag がアクタをフィルタしない場合は、アクタ タグ名の変数に割り当てた名前と、アクタのタグ名が一致していることを確認します。名前が一致している場合はブループリントのバグを調査してください。

DistanceToPlayer ネイティブ フィルタ

  1. プロジェクトに空の C++ クラスを追加して DistanceToPlayer と名前を付けます。

  2. プロジェクトの「 *.Build.cs 」ファイルで、Public Dependency Module Names に "SourceFilteringTrace"、"SourceFilteringCore"、"SourceFilteringEditor" を追加します。

    // Copyright 1998-2019 Epic Games, Inc.All Rights Reserved.
    
    using UnrealBuildTool;
    
    public class TraceSourceFilterHT :ModuleRules
    {
        public TraceSourceFilterHT(ReadOnlyTargetRules Target) : base(Target)
        {
            PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
    
            PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "SourceFilteringTrace", "SourceFilteringCore", "SourceFilteringEditor" });
        }
    }
  3. DistanceToPlayer.h において以下のコードを追加します。

    // Fill out your copyright notice in the Description page of Project Settings.
    
    #pragma once
    
    #include "DataSourceFilter.h"
    #include "DistanceToPlayer.generated.h"
    
    UCLASS(NotBlueprintable)
    class UDistanceToPlayer : public UDataSourceFilter
    {
        GENERATED_BODY()
            UDistanceToPlayer();
    public:
        UPROPERTY(Category = Filtering, EditAnywhere)
            float Distance;
    protected:
        virtual bool DoesActorPassFilter_Internal(const AActor* InActor) const override;
        virtual void GetDisplayText_Internal(FText& OutDisplayText) const override;
    };
  4. DistanceToPlayer.cpp において以下のコードを追加します。

    // Fill out your copyright notice in the Description page of Project Settings.
    
    #include "DistanceToPlayer.h"
    #include "GameFramework/PlayerController.h"
    #include "GameFramework/Pawn.h"
    #include "Engine/World.h"
    
    #define LOCTEXT_NAMESPACE "UDistanceToPlayer"
    
    /**
    Set initial distance to 300 Unreal Units (cm).
    */
    UDistanceToPlayer::UDistanceToPlayer() :Distance(300.0f)
    {
    }
    
    /**
    Check the Actor's distance to our Player Pawn.
    */
    bool UDistanceToPlayer::DoesActorPassFilter_Internal(const AActor* InActor) const
    {
        if (InActor)
        {
            UWorld* World = InActor->GetWorld();
            if (World)
            {
                if (APlayerController* Controller = World->GetFirstPlayerController())
                {
                    if (APawn* Pawn = Controller->GetPawn())
                    {
                        /**Return true if Actor is less than the distance threshold to our Player Pawn.*/
                        return Pawn->GetDistanceTo(InActor) < Distance;
                    }
                }
            }
        }
        return false;
    }
    
    /**
    The player can customize the distance value.
    */
    void UDistanceToPlayer::GetDisplayText_Internal(FText& OutDisplayText) const
    {
        OutDisplayText = FText::Format(LOCTEXT("DisplayText", "Distance to Player Pawn < {0}"), { Distance });
    }
    #undef LOCTEXT_NAMESPACE // "UDistanceToPlayer"
  5. コードをコンパイルすると [Add Filter] ドロップダウンに DistanceToPlayer フィルタが表示されます。

    HT_DistanceToPlayerNativeFilter_1.png

  6. DistanceToPlayer を選択して、新しいネイティブ フィルタをフィルタ欄に追加します。

  7. [`Crouching`] タグを右クリックし [Remove Filter] を選択してフィルタ欄から HasTag ブループリント フィルターを除去します。

    DistanceToPlayer Filter

  8. DistanceToPlayer フィルタを確認するには PIE セッションを実行します。

    プレイヤー ポーン フィルタによる 300 Unreal 単位 (cm) 圏内のアクタ。

DistanceToPlayer ネイティブ フィルタが想定どおりに動作することを確認したら、次にユース ケースの要件を満たすようにフィルタを組み合わせます。

ユースケース 1 を実装する

このユース ケースの要件をもう一度確認します。

フィルター ロジック

False を返す

True を返す

DistanceToPlayer AND HasTag

フィルタを通すアクタ

フィルタで除くアクタ

この要件を満たすために次の手順を実行します。

  1. フィルタ欄に HasTag フィルタを追加します。

  2. Actor Tag name 変数を「 Standing 」に設定します。

  3. フィルター欄で HasTag DistanceToPlayer の隣にドラッグします。

    Dragging HasTag

  4. Distance 変数のデフォルト値を 300 から 400 に変更します。

    Changing Distance Variable

    フィルタ セットの構成には、論理演算子 AND、OR、NOT を使用できます。論理演算子を右クリックすると、別の論理演算子を選択できます。

    HT_DistanceToPlayerNativeFilter_4.png

  5. PIE セッションを実行してフィルタ ロジックを確認しましょう。

プレイヤー ポーンが「Standing」アクタ タグを付けたアクタの 400 cm 圏内に入ると、Trace Source Filtering がアクタをフィルタします。

プレイヤー ポーンが圏内に入った時に、左下のパネルで Animation Insights が「Equip_Pistol_Standing - Blend Weight」のデータだけをグラフでトレースしている様子に注目してください。

ユースケース 2

ここでは、シーンを移動するときにプレイヤー ポーンのレイキャストに当たった (または衝突する)、タグ付きのスケルタル メッシュ アクタのフィルタを実装します。このユースケースを念頭に置き以下のフィルタを実装します。

実装タイプ

フィルター名

使用

ブループリント

IsOfClass

指定したクラスに属するアクタをフィルタします。このデフォルトのクラスはスケルタル メッシュ アクタを指定します。

ネイティブ

Raycast

プレイヤー ポーンのレイキャストにヒットした、タグ付きのアクタをフィルタします。レイのデフォルトの長さは 400 cm に指定します。

実装したフィルタを組み合わせて、タグ付きのスケルタル メッシュ アクタにプレイヤー ポーンのレイキャストがヒットした際に、アクタをフィルタして Animation Insights がトレース データを記録するようにします。このセクションの最後までに、以下のようなフィルタ ロジックでフィルタがユース ケースの要件を満たすようにします。

フィルタ ロジック

True を返す

False を返す

RaycastActor AND IsOfClass

フィルタを通すアクタ

フィルタで除くアクタ

IsOfClass ブループリント アクタ

  1. [Trace Source Filtering] ダイアログ ボックスで [Add Filter (フィルタを追加)]] > [Create new Filter Blueprint (新しい Filter Blueprint を作成する)] の順に選択します。

  2. アセットを「 /Game/FilterBP/ 」配下に IsOfClass として保存します。

  3. IsOfClass Blueprint エディタで、 [Functions] > (Function) [Override] > [Does Actor Pass Filter] の順に選択します。

  4. 以下の詳細に従って新しい変数を追加します。

    • 変数名: ActorClassRef

    • 変数の型: Actor Class Reference

    • インスタンス編集可能: Enabled

    • ツールチップ: Actor Class Reference

  5. デフォルト値を定義するには、ブループリントをコンパイルします。

  6. SkeletalMeshActor をデフォルト値に指定します。

    HT_IsOfClassBP_1.png

  7. 以下のブループリントによって Does Actor Pass Filter 関数を定義します。

  8. [My Blueprint] パネルの Trace Source Filtering カテゴリから Get Tool Tip Text 関数を選択して [Implement Function (関数を実装する)] を選択します。

  9. 以下のブループリントによって Get Tool Tip Text 関数を定義します。

  10. 以下のブループリントによって Get Display Text 関数を定義します。

  11. コンパイルと保存をしてから IsOfClass ブループリント エディタを閉じると HashTag ブループリント フィルタがフィルタ欄に表示されます。

  12. IsOfClass filter フィルタを確認するには PIE セッションを実行します。

    PIE セッションでフィルタされたスケルタル メッシュ アクタ。

IsOfClass ブループリント フィルタが想定どおり動作することを確認したら、次に RaycastActor ネイティブ フィルタを実装します。

RaycastActor ネイティブ フィルタ

  1. プロジェクトに空の C++ クラスを追加して RaycastActor と名前を付けます。

  2. RaycastActor.h に以下のコードを追加します。

    // Fill out your copyright notice in the Description page of Project Settings.
    
    #pragma once
    
    #include "DataSourceFilter.h"
    #include "RaycastActor.generated.h"
    
    UCLASS(NotBlueprintable)
    class URaycastActor : public UDataSourceFilter
    {
        GENERATED_BODY()
            URaycastActor();
    
    private:
        UPROPERTY(Category = Filtering, EditAnywhere)
            FName ActorTagName;
    
        UPROPERTY(Category = Filtering, EditAnywhere)
            float RayLength;
    
    protected:
        virtual bool DoesActorPassFilter_Internal(const AActor* InActor) const override;
        virtual void GetDisplayText_Internal(FText& OutDisplayText) const override;
    };
  3. RaycastActor.cpp に以下のコードを追加します。

    // Fill out your copyright notice in the Description page of Project Settings.
    
    #include "RaycastActor.h"
    #include "GameFramework/PlayerController.h"
    #include "GameFramework/Pawn.h"
    #include "Engine/World.h"
    #include "DrawDebugHelpers.h"
    
    #define LOCTEXT_NAMESPACE "URaycastActor"
    
    /**
    Set initial distance to 400 Unreal Units (cm).
    */
    URaycastActor::URaycastActor() :ActorTagName("ADD ACTOR TAG"), RayLength(400.0f)
    {
    }
    
    /**
    Raycast from Player Pawn to hit a tagged Actor.
    */
    bool URaycastActor::DoesActorPassFilter_Internal(const AActor* InActor) const
    {
        if (InActor)
        {
            UWorld* World = InActor->GetWorld();
            if (World)
            {
                if (APlayerController* Controller = World->GetFirstPlayerController())
                {
                    if (APawn* Pawn = Controller->GetPawn())
                    {
                        FHitResult* HitResult = new FHitResult();
                        FVector StartTrace = Pawn->GetActorLocation();
                        FVector ForwardVector = Pawn->GetActorForwardVector();
                        FVector EndTrace = (ForwardVector * RayLength) + StartTrace;
                        FCollisionQueryParams* CollisionQuery = new FCollisionQueryParams();
                        World->LineTraceSingleByChannel(*HitResult, StartTrace, EndTrace, ECC_Visibility, *CollisionQuery);
                        DrawDebugLine(World, StartTrace, EndTrace, FColor(0, 255, 0), false, 0.0f);
    
                        /**Return true if Player Pawn's Ray hits a tagged Actor.*/
                        if (HitResult->GetActor() != NULL && HitResult->GetActor()->ActorHasTag(ActorTagName))
                        {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }
    
    /**
    The player can customize the following:
    * - The Actor Tag Name to look for
    * - The Ray Length
    */
    void URaycastActor::GetDisplayText_Internal(FText& OutDisplayText) const
    {
        OutDisplayText = FText::Format(LOCTEXT("TraceSourceText", "Hit {0} Actor with Ray Length {1}"), FText::FromName(ActorTagName), RayLength);
    }
    #define LOCTEXT_NAMESPACE // "URaycastActor"
  4. コードをコンパイルすると [Add Filter] ドロップダウンに RaycastActor Filter フィルタが表示されます。

    HT_RaycastActor_1.png

  5. [is a SkeletalMeshActor filter] を右クリックし [Remove Filter] を選択してフィルタ欄から IsOfClass ブループリント フィルターを除去します。

  6. RaycastActor を選択して、新しいネイティブ フィルタをフィルタ欄に追加します。

  7. Rayfilter フィルタをクリックして「 ADD ACTOR TAG 」を「 Standing 」に変更し、アクタ タグ名を定義します。

    RaycastActor Filter

  8. RaycastActor フィルタを確認するには PIE セッションを実行します。

    立っているアクタがプレイヤー ポーンのレイキャストにヒットすると、すべてのアクタがフィルタされます。

RaycastActor ネイティブ フィルタが想定どおりに動作することを確認したら、次にユース ケースの要件を満たすようにフィルタを組み合わせます。

ユース ケース 2 を実装する

このユース ケースの要件をもう一度確認します。

フィルタ ロジック

True を返す

False を返す

RaycastActor AND IsOfClass

フィルタを通すアクタ

フィルタで除くアクタ

  1. フィルタ欄に IsOfClass フィルタを追加します。

  2. フィルタ欄で [IsOfClass] を [RaycastActor]の隣にドラッグします。

    Dragging IsOfClass Filter

  3. PIE セッションを実行してフィルタ ロジックを確認しましょう。

プレイヤー ポーンのレイキャストが「Standing」アクタ タグを付けたアクタにヒットすると、Trace Source Filtering システムがスケルタル メッシュ アクタをフィルタします。

プレイヤー ポーンのレイキャストが立っているアクタにヒットすると、左下のパネルで Animation Insights が「Equip_Pistol_Standing - Blend Weight」と「Crouch_Idle_Rifle_Ironsights - Blend Weight」のデータだけをグラフでトレースしている様子に注目してください。

応用編

ここまでの実践ではユース ケースを 2 つ実装して Trace Source Filtering の使用方法を学びました。注視が必要なアクタのデータだけを Animation Insights でトレースする、他のフィルタについても考えてみましょう。

たとえば以下のようなフィルタのアイデアはどうでしょう。

  • 発射物のコリジョン

  • ホーミング発射物のコリジョン

  • ボタン トリガー

フィルタを実装する際は、論理的に組み合わせてアニメーションの最適化とデバッグに必要なアクタ データをフィルタする方法を考えます。今回は AND 論理演算子のみを使用しましたが、独自のロジックを OR や NOT 演算子と組み合わせる方法も考えてみましょう。

Unreal Engine のドキュメントを改善するために協力をお願いします!どのような改善を望んでいるかご意見をお聞かせください。
調査に参加する
キャンセル