Bpクラスのupropertyのリファレンスの取得について

お世話になっております。

UObject数の削減のためにBlueprintReadWrite、BlueprintReadOnlyに設定されていたけど実際のBPにアクセスされていないUPropertyを洗い出すツールを試しに作ってみましたけど、同じUPropertyのリファレンス数が変わることがあるので、質問させていただきます。

なお「実際のBPにアクセスされていないUProperty」をエディタ上でリファレンスを全検索して結果が見つからないUPropertyと定義しています。

現在使っているツールの処理は以下の通りになります:

// FAssetRegistryModuleからチェックするBPアセットを取得済み
// アセット情報からBPのGeneratedClassを取得して読み込み  
if (auto generatedClass = checkAsset.TagsAndValues.Find(TEXT("GeneratedClass")))
{
    const FString classPath = FPackageName::ExportTextPathToObjectPath(*generatedClass);
	FString className = FPackageName::ObjectPathToObjectName(classPath);

    UClass* bpClass = LoadClass(nullptr, *classPath, nullptr, LOAD_None, nullptr);
    if (bpClass)
    {
        UClass* parentClass = bpClass->GetSuperClass();
        if (parentClass && parentClass->IsNative())
        {
            for (TFieldIterator currentIter(bpClass); currentIter; ++currentIter)
            {
                // BPで見えるもののみチェックする
                if (!currentIter->HasAnyPropertyFlags(CPF_BlueprintVisible))
		        continue;
                // アプリ側で定義したUPROPERTYのみをチェックする
                UClass* ownerClass = currentIter->GetOwnerClass();
                if (ownerClass && !ownerClass->GetName().Contains(FString("チェックするクラス名"), ESearchCase::CaseSensitive))
		        continue;

                FReferencerInformationList referencers;
		        currentIter->RetrieveReferencers(&referencers.InternalReferences, &referencers.ExternalReferences);
		        // NativeClassが必ずExternalReferencesに入るのでリファレンス1個以下のUPROPERTYを出力				
		        if (referencers.ExternalReferences.Num() <= 1 && referencers.InternalReferences.Num() <= 0)
		        {
                    self.AddWarning(FString::Printf(TEXT("Property [%s] in Class [%s] is Not Used in Blueprint!"), *currentIter->GetName(), *parentClass->GetName()));  // AutomationTestのWarningとして出力
		        }
            }
        }
    }
}

この処理に関して質問は2点あります。

  1. 処理を組み込んだテストを実行するときの挙動が固定していません。チェックするBPアセットをエディタ上に開いていない場合は予想通りの出力をしてくれますが、そのBPアセットをエディター上で開いた後でテストを実行すると一切出力しなくなります。ブレークポイントを張って調べた結果、BPアセットを開いたとき、取得したリファレンスの配列に「BlueprintVariableNodeSpawner_XXXX」からの参照が2つ追加されたことを判明しました。このように参照の数が変わると判定がし辛くなりますので、UPropertyのリファレンスを取得する際はRetrieveReferencers()を使うのが正しいでしょうか?
  2. UPropertyをチェックするときに参照しているフラグは「CPF_BlueprintVisible」を使っていますが、そうするとEditDefaultsOnlyでしか設定していないUPropertyもそれに該当するので余分の結果が出力されます。BlueprintReadWriteとBlueprintReadOnlyが設定されているUPropertyだけをチェックするにはフラグ設定をどういう風に変更すればいいのでしょうか?

長文で失礼しました。

よろしくお願いいたします。

お世話になっております。
ご返答が遅くなっており申し訳ございません。ご質問内容に関して調査しておりますのでしばらくお待ちください。

お世話になっております。
返答が遅くなってしまい申し訳ございません。

ご提供頂いたコードを元に「BPにアクセスされていないUProperty」の処理のサンプルを修正したものが以下になります。こちらで想定されたものかご確認頂けますと幸いです。

・MyBlueprintFunctionLibrary.cpp
これはEditorから実行するために意図的にFunctionLibraryを利用しただけです

#include "MyBlueprintFunctionLibrary.h"
#include "AssetData.h"

void UMyBlueprintFunctionLibrary::TestFunc(const UObject* InAsset)
{
	FAssetData checkAsset(InAsset, true /* BlueprintClassも含む */ );
	const FString* generatedClass = checkAsset.TagsAndValues.Find(TEXT("GeneratedClass"));		// チェックするアセットのクラス名
	bool bFoundProperty = false;
	const FString  engineClassPrefix("/Script/Engine.");

	// Objectを生成
	UClass* bpClass = LoadClass(nullptr, *FPackageName::ExportTextPathToObjectPath(*generatedClass), nullptr, LOAD_None, nullptr);
	if (bpClass)
	{
		UClass* parentClass = bpClass->GetSuperClass();

		// 親クラスのNativeクラスから探す
		if (parentClass && parentClass->IsNative())
		{
			// UPropertyを全チェック
			for (TFieldIterator currentIter(bpClass); currentIter; ++currentIter)
			{
				// アプリ側で定義したUPROPERTYのみをチェックする
				UClass* ownerClass = currentIter->GetOwnerClass();
				if (ownerClass && ownerClass->GetFullName().Contains(engineClassPrefix, ESearchCase::CaseSensitive))
				{
					// EngineClassは除外
					continue;
				}

				if (!currentIter->HasAnyPropertyFlags(CPF_BlueprintVisible))
				{
					// BPに公開されていない
					continue;
				}

				if (ownerClass->IsNative() && currentIter->HasAllPropertyFlags(CPF_Edit | CPF_DisableEditOnInstance))
				{
					// NativeクラスのEditDefaultOnlyは除外
					continue;
				}

				FReferencerInformationList referencers;
				currentIter->RetrieveReferencers(&referencers.InternalReferences, &referencers.ExternalReferences);
				// NativeClassが必ずExternalReferencesに入るのでリファレンス1個以下のUPROPERTYを出力                
				if (referencers.ExternalReferences.Num() <= 1 && referencers.InternalReferences.Num() <= 0)
				{
					bFoundProperty = true;
					UE_LOG(LogTemp, Warning, TEXT("%s"), *FString::Printf(TEXT("[Check] Property [%s] in Class [%s] is Not Used in Blueprint!"), *currentIter->GetName(), *parentClass->GetName()));
				}
			}

			if (!bFoundProperty)
			{
				// BPにアクセスされていないUPropertyはない
				UE_LOG(LogTemp, Display, TEXT("This Class is OK"));
			}
		}
	}
}

・MyBlueprintFunctionLibrary.h
ヘッダファイル

UFUNCTION(BlueprintCallable, Category="Test")
static void TestFunc(const UObject* InAsset);

(ご質問)
1.
4.21で確認する限りではEditorの開いた状態に依存せず一定の結果が得られていました。このコードが見えない部分か、バージョンによる差分があるかもしれません。

2.
EditorDefaultOnlyのチェックに currentIter->HasAllPropertyFlags(CPF_Edit | CPF_DisableEditOnInstance))を利用するのはいかがでしょうか。

よろしくお願いします。

ご返答ありがとうございました!

挙動に関してはバージョン差分による問題なのを承知しました。
こちらの開発環境は4.20固定でしたので実行する際はアセットを開かないように回避したいと思います。

EditorDefaultOnlyのチェックはご教授頂いたフラグを使用して試したいと思います。

よろしくお願いいたします。