関連ブログ
- [UE4][UE5]開発環境の容量を少しでも減らす 2024.08.14UE
- [UE5] PushModel型のReplicationを使い、ネットワーク最適化を図る 2024.05.29UE
- [UE5]マテリアルでメッシュをスケールする方法 2024.01.17UE
CATEGORY
2021.10.06UE4その他
執筆バージョン: Unreal Engine 4.27 |
こんにちは。エンジニアの森です。
今回は、 UE4 上のデータテーブルとデータアセットを、テキスト出力する手法について考えます。
UE4 のデータテーブルは CSV 形式と Json 形式でのエクスポート/インポートをサポートしています。
また、データテーブルの右クリックメニューから「Export as CSV」が用意されているので、これを使えば、データテーブルのエクスポートはできます。
でも、データテーブルを手動でエクスポートするのって、面倒ですよね?
できれば自動でエクスポートを行う機能が欲しいです。
というわけで早速作っていきます。
データテーブルを CSV テキスト化して出力するために、実際に行うことは以下の 3 ステップです。
1. テキスト保存先をあらかじめ決めておく
2. データテーブルを CSV テキスト化
3. FFileHelper::SaveStringToFile を使用してテキストファイルを出力
出力先フォルダはプロジェクト設定で決められるようにして、出力ファイル名はアセット名と同じにしておけば良いでしょう。
データテーブルから CSV テキストへの変換は、 UDataTable::GetTableAsCSV を使用します。
独自のプロジェクト設定を追加する方法はこちらの記事(UDeveloperSettingsでプロジェクト設定に項目を追加する)を参照。
データテーブルの編集時には FTableRowBase::OnDataTableChanged が呼ばれますので、実装には UBlueprintFunctionLibrary を使うとすると、以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#pragma once #include "CoreMinimal.h" #include "Kismet/BlueprintFunctionLibrary.h" #include "MyBlueprintFunctionLibrary.generated.h" class UDataTable; UCLASS() class MYPROJECT_API UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary { GENERATED_BODY() public: UFUNCTION() static FString GetExportFileName(const UObject *Object, const FString &Extension); UFUNCTION() static void SaveStringToFile(const FString &String, const FString &FilePath); UFUNCTION() static void ExportDataTableAsCSV(const UDataTable *Table); }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
#include "MyBlueprintFunctionLibrary.h" #include "MyProject/MySettings/MySettings.h" #include "Engine/DataTable.h" #include "Misc/Paths.h" #include "Misc/FileHelper.h" #include "SourceControlHelpers.h" FString UMyBlueprintFunctionLibrary::GetExportFileName(const UObject *Object, const FString &Extension) { // 指定の拡張子で、UObject と同じ名前のファイル名を生成する // ファイルパスは、プロジェクト設定に依存 static const FString PathPrefix = TEXT("/Game"); const UMySettings *Settings = UMySettings::GetMySettings(); if (Settings != nullptr) { const FString ProjectDir = FPaths::ProjectDir(); FString FileName = Object->GetPackage()->GetFName().ToString() + TEXT(".") + Extension; if (FileName.StartsWith(PathPrefix)) { FileName = FileName.RightChop(PathPrefix.Len()); } const FString OutputPath = FPaths::Combine(ProjectDir, Settings->ResourceOutputFolder, FileName); return OutputPath; } return FString(); } void UMyBlueprintFunctionLibrary::SaveStringToFile(const FString &String, const FString &FilePath) { // UTF-8 設定でテキストファイルを出力 if (USourceControlHelpers::IsEnabled()) { USourceControlHelpers::CheckOutFile(FilePath); } FFileHelper::SaveStringToFile(String, *FilePath, FFileHelper::EEncodingOptions::ForceUTF8); if (USourceControlHelpers::IsEnabled()) { USourceControlHelpers::MarkFileForAdd(FilePath); } } void UMyBlueprintFunctionLibrary::ExportDataTableAsCSV(const UDataTable *Table) { // CSV 形式でデータテーブルを出力 if (!Table) { return; } const FString CsvString = Table->GetTableAsCSV(EDataTableExportFlags::None); const FString OutputPath = GetExportFileName(Table, TEXT("csv")); SaveStringToFile(CsvString, OutputPath); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#pragma once #include "CoreMinimal.h" #include "Engine/DeveloperSettings.h" #include "MySettings.generated.h" UCLASS(config = Game, defaultconfig) class MYPROJECT_API UMySettings : public UDeveloperSettings { GENERATED_BODY() public: UMySettings(); #if WITH_EDITORONLY_DATA // ファイルの出力先フォルダー UPROPERTY(BlueprintReadWrite, EditAnywhere, Config, Category = "Data") FString ResourceOutputFolder; // 自動エクスポート機能の ON/OFF UPROPERTY(BlueprintReadWrite, EditAnywhere, Config, Category = "Data") bool AutoExportOnEdit; #endif UFUNCTION(BlueprintPure) static UMySettings *GetMySettings(); virtual FName GetCategoryName() const override; #if WITH_EDITOR virtual FText GetSectionText() const override; virtual FText GetSectionDescription() const override; #endif }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
#include "MySettings.h" #define LOCTEXT_NAMESPACE "MySettings" UMySettings::UMySettings() : Super() #if WITH_EDITOR , ResourceOutputFolder(TEXT("Output")) , AutoExportOnEdit(true) #endif { } UMySettings *UMySettings::GetMySettings() { return GetMutableDefault<UMySettings>(); } FName UMySettings::GetCategoryName() const { return "MySettings"; } #if WITH_EDITOR FText UMySettings::GetSectionText() const { return LOCTEXT("UMySettings::GetSectionText", "Import/Export"); } FText UMySettings::GetSectionDescription() const { return LOCTEXT("UMySettings::GetSectionDescription", "Configuring the export and import of data assets"); } #endif #undef LOCTEXT_NAMESPACE |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#pragma once #include "CoreMinimal.h" #include "Engine/DataTable.h" #include "MyTableRowBase.generated.h" USTRUCT() struct MYPROJECT_API FMyTableRowBase : public FTableRowBase { GENERATED_BODY() public: #if WITH_EDITOR virtual void OnDataTableChanged(const UDataTable * InDataTable, const FName InRowName) override; #endif }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include "MyTableRowBase.h" #if WITH_EDITOR #include "MyProject/MyBlueprintFunctionLibrary/MyBlueprintFunctionLibrary.h" #include "MyProject/MySettings/MySettings.h" #endif #if WITH_EDITOR void FMyTableRowBase::OnDataTableChanged(const UDataTable * InDataTable, const FName InRowName) { const UMySettings *Settings = UMySettings::GetMySettings(); if ((Settings != nullptr) && (Settings->AutoExportOnEdit)) { UMyBlueprintFunctionLibrary::ExportDataTableAsCSV(InDataTable); } } #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#pragma once #include "CoreMinimal.h" #include "MyProject/MyDataTable/MyTableRowBase.h" #include "MyTestDataTable.generated.h" USTRUCT() struct MYPROJECT_API FMyTestDataTable : public FMyTableRowBase { GENERATED_BODY() public: UPROPERTY(EditAnywhere, Category = "Data") int IntValue; UPROPERTY(EditAnywhere, Category = "Data") TArray<int> IntArray; UPROPERTY(EditAnywhere, Category = "Data") TMap<FString, int> IntMap; }; |
1 2 3 4 5 6 7 8 9 10 11 |
~略~ PrivateDependencyModuleNames.AddRange( new string[] { "Core", "CoreUObject", "Engine", "DeveloperSettings", "SourceControl", } ); |
自動エクスポート機能ができました。
データアセットについての過去記事はこちら↓
独自に用意したデータアセットをより便利に活用する方法
データテーブルと同じように、データアセットもエクスポートをサポートしたいです。
しかし、データテーブルと違って UDataTable::GetTableAsCSV のような便利メソッドは存在しません。
標準の Json モジュールと JsonUtilities モジュールを使用すれば Json テキスト化が可能になります。
FJsonObjectConverter::UStructToJsonObject でデータアセットを JsonObject に変換し、シリアライズする、という流れです。
それ以外のステップは、データテーブルのときと同じ。
ただし、データテーブルと区別するためにファイル拡張子は .myjson にしておきます
1 2 3 4 5 6 7 8 9 10 |
class MYPROJECT_API UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary { ~略~ UFUNCTION() static bool UObjectToJsonString(const UObject *Object, FString &OutJsonString); UFUNCTION() static void ExportObjectAsJson(const UObject *Object, const FString &OutputPath); }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
~略~ bool UMyBlueprintFunctionLibrary::UObjectToJsonString(const UObject *Object, FString &OutJsonString) { // UObject から Json 文字列に変換 TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject()); FJsonObjectConverter::UStructToJsonObject(Object->GetClass(), (void*)(Object), JsonObject.ToSharedRef(), 0, 0, nullptr); TSharedRef<TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>> JsonWriter = TJsonWriterFactory<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>::Create(&OutJsonString, 0); return FJsonSerializer::Serialize(JsonObject.ToSharedRef(), JsonWriter); return false; } void UMyBlueprintFunctionLibrary::ExportObjectAsJson(const UObject *Object, const FString &OutputPath) { // JSON 形式で UObject を出力 if (!Object) { return; } FString JsonString; if (UObjectToJsonString(Object, JsonString)) { SaveStringToFile(JsonString, OutputPath); } else { UE_LOG(LogTemp, Error, TEXT("UMyBlueprintFunctionLibrary::ExportObjectAsJson: Failed to Export %s"), *Object->GetName()); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#pragma once #include "CoreMinimal.h" #include "Engine/DataAsset.h" #include "MyDataAsset.generated.h" class UAssetImportData; UCLASS() class MYPROJECT_API UMyDataAsset : public UDataAsset { GENERATED_BODY() public: #if WITH_EDITORONLY_DATA static FString FileExtension; #endif #if WITH_EDITOR UFUNCTION(Category = "Import/Export", meta = (CallInEditor = true)) void Export(); UFUNCTION(Category = "Import/Export", meta = (CallInEditor = true)) void OpenSourceLocation() const; void PostEditChangeProperty(FPropertyChangedEvent & PropertyChangedEvent); #endif }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
#include "MyDataAsset.h" #if WITH_EDITOR #include "MyProject/MyBlueprintFunctionLibrary/MyBlueprintFunctionLibrary.h" #include "MyProject/MySettings/MySettings.h" #include "UObject/UnrealType.h" #include "Windows/WindowsPlatformProcess.h" #endif #if WITH_EDITOR FString UMyDataAsset::FileExtension = TEXT("myjson"); void UMyDataAsset::Export() { FString FilePath = UMyBlueprintFunctionLibrary::GetExportFileName(this, FileExtension); UMyBlueprintFunctionLibrary::ExportObjectAsJson(this, FilePath); } void UMyDataAsset::OpenSourceLocation() const { if (AssetImportData != nullptr) { FPlatformProcess::ExploreFolder(*AssetImportData->GetFirstFilename()); } } void UMyDataAsset::PostEditChangeProperty(FPropertyChangedEvent &PropertyChangedEvent) { if (PropertyChangedEvent.ChangeType == EPropertyChangeType::ArrayAdd) { // 配列要素を追加した瞬間は自動エクスポートしない(クラッシュ回避) return; } const UMySettings *Settings = UMySettings::GetMySettings(); if ((Settings != nullptr) && (Settings->AutoExportOnEdit)) { Export(); } } #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#pragma once #include "CoreMinimal.h" #include "MyProject/MyDataAsset/MyDataAsset.h" #include "MyTestDataAsset.generated.h" UCLASS() class MYPROJECT_API UMyTestDataAsset : public UMyDataAsset { GENERATED_BODY() public: UPROPERTY(EditAnywhere, Category = "Data") int IntValue; UPROPERTY(EditAnywhere, Category = "Data") TArray<int> IntArray; UPROPERTY(EditAnywhere, Category = "Data") TMap<FString, int> StringIntMap; UPROPERTY(EditAnywhere, Category = "Data") TArray<FString> StringArray; UPROPERTY(EditAnywhere, Category = "Data") TMap<int, int> IntIntMap; }; |
1 2 3 4 5 6 7 8 9 |
~略~ PrivateDependencyModuleNames.AddRange( new string[] { ~略~ "Json", "JsonUtilities", } ); |
自動エクスポート機能ができました。
さて、データアセットをエクスポートできたのですが、今度はインポートもできるようにしたいと思います。
インポートを実装する際には、こちらの記事(独自のアセットを実装する方法(2) インポートの実装)が参考になります。
MyDataTable にコードを書き加えて、試してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
~略~ class MYPROJECT_API UMyDataAsset : public UDataAsset { ~略~ #if WITH_EDITORONLY_DATA UPROPERTY(VisibleAnywhere, Instanced, Category = "ImportSettings") UAssetImportData* AssetImportData; #endif #if WITH_EDITOR UFUNCTION(Category = "Import/Export", meta = (CallInEditor = true)) void Import(); void UpdateAssetImportData(FString Filename); #endif }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
~略~ #if WITH_EDITOR #include "EditorFramework/AssetImportData.h" #endif #if WITH_EDITOR FString UMyDataAsset::FileExtension = TEXT("myjson"); void UMyDataAsset::Import() { FString FilePath = UMyBlueprintFunctionLibrary::GetExportFileName(this, FileExtension); UMyBlueprintFunctionLibrary::ImportJsonToObject(FilePath, this); UpdateAssetImportData(FilePath); } void UMyDataAsset::Export() { FString FilePath = UMyBlueprintFunctionLibrary::GetExportFileName(this, FileExtension); UMyBlueprintFunctionLibrary::ExportObjectAsJson(this, FilePath); UpdateAssetImportData(FilePath); } void UMyDataAsset::UpdateAssetImportData(FString Filename) { if (AssetImportData == nullptr) { AssetImportData = NewObject<UAssetImportData>(this); } AssetImportData->Update(Filename); } #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#pragma once #include "AssetTypeActions_Base.h" class UMyDataAsset; class FAssetTypeActions_MyDataAsset : public FAssetTypeActions_Base { public: virtual FText GetName() const override { return NSLOCTEXT("AssetTypeActions", "AssetTypeActions_MyDataAsset", "MyDataAsset"); } virtual FColor GetTypeColor() const override { return FColor::Red; } virtual uint32 GetCategories() override { return EAssetTypeCategories::Misc; } virtual void GetResolvedSourceFilePaths(const TArray<UObject*>& TypeAssets, TArray<FString>& OutSourceFilePaths) const override; virtual UClass* GetSupportedClass() const override; virtual bool IsImportedAsset() const override { return true; } virtual bool HasActions(const TArray<UObject*>& InObjects) const override { return true; } virtual void GetActions(const TArray<UObject*>& InObjects, FMenuBuilder& MenuBuilder) override; void Export(TArray<TWeakObjectPtr<UMyDataAsset>> Objects); }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
#include "AssetTypeActions_MyDataAsset.h" #include "MyDataAsset.h" #include "EditorFramework/AssetImportData.h" #define LOCTEXT_NAMESPACE "AssetTypeActions" UClass* FAssetTypeActions_MyDataAsset::GetSupportedClass() const { return UMyDataAsset::StaticClass(); } void FAssetTypeActions_MyDataAsset::GetResolvedSourceFilePaths(const TArray<UObject*>& TypeAssets, TArray<FString>& OutSourceFilePaths) const { for (UObject *TypeAsset : TypeAssets) { const UMyDataAsset *MyDataAsset = CastChecked<UMyDataAsset>(TypeAsset); if(MyDataAsset != nullptr && MyDataAsset->AssetImportData != nullptr) { MyDataAsset->AssetImportData->ExtractFilenames(OutSourceFilePaths); } } } void FAssetTypeActions_MyDataAsset::GetActions(const TArray<UObject*>& InObjects, FMenuBuilder& MenuBuilder) { TArray<TWeakObjectPtr<UMyDataAsset>> MyAssetImports = GetTypedWeakObjectPtrs<UMyDataAsset>(InObjects); MenuBuilder.AddMenuEntry( LOCTEXT("MyDataAsset_Export", "Export"), LOCTEXT("MyDataAsset_ExportTooltip", "Export this MyDataAsset"), FSlateIcon(), FUIAction(FExecuteAction::CreateSP(this, &FAssetTypeActions_MyDataAsset::Export, MyAssetImports), FCanExecuteAction()) ); } void FAssetTypeActions_MyDataAsset::Export(TArray<TWeakObjectPtr<UMyDataAsset>> Objects) { for (auto It = Objects.CreateIterator(); It; ++It) { UMyDataAsset *MyDataAsset = (*It).Get(); if (MyDataAsset != nullptr) { MyDataAsset->Export(); } } } #undef LOCTEXT_NAMESPACE |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#pragma once #include "CoreMinimal.h" #include "Factories/Factory.h" #include "EditorReimportHandler.h" #include "MyDataAssetFactory.generated.h" UCLASS() class MYPROJECT_API UMyDataAssetFactory : public UFactory, public FReimportHandler { GENERATED_BODY() public: UMyDataAssetFactory(const FObjectInitializer& ObjectInitializer); virtual bool DoesSupportClass(UClass* Class) override; virtual UClass* ResolveSupportedClass() override; virtual UObject* FactoryCreateText(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, const TCHAR* Type, const TCHAR*& Buffer, const TCHAR* BuferEnd, FFeedbackContext* Warn) override; virtual bool CanReimport(UObject* Obj, TArray<FString>& OutFilenames) override; virtual void SetReimportPaths(UObject* Obj, const TArray<FString>& NewReimportPaths) override; virtual EReimportResult::Type Reimport(UObject* Obj) override; }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
#include "MyDataAssetFactory.h" #include "MyDataAsset.h" #include "EditorFramework/AssetImportData.h" #include "EditorReimportHandler.h" #include "JsonObjectConverter.h" UMyDataAssetFactory::UMyDataAssetFactory(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { SupportedClass = UMyDataAsset::StaticClass(); bCreateNew = false; bEditorImport = true; bText = true; Formats.Add(UMyDataAsset::FileExtension + TEXT(";My Data Asset")); } bool UMyDataAssetFactory::DoesSupportClass(UClass* Class) { return Class->IsChildOf(UMyDataAsset::StaticClass()); } UClass* UMyDataAssetFactory::ResolveSupportedClass() { return UMyDataAsset::StaticClass(); } UObject* UMyDataAssetFactory::FactoryCreateText(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, const TCHAR* Type, const TCHAR*& Buffer, const TCHAR* BuferEnd, FFeedbackContext* Warn) { UClass *Class = InClass; TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(Buffer); TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject()); FJsonSerializer::Deserialize(JsonReader, JsonObject); TSharedPtr<FJsonValue> *ClassName = (*JsonObject).Values.Find(TEXT("nativeClass")); if (ClassName != nullptr) { UClass *FoundClass = FindObject<UClass>(ANY_PACKAGE, *(*ClassName).Get()->AsString(), false); if (FoundClass != nullptr) { Class = FoundClass; } FStaticConstructObjectParameters Params(Class); Params.Outer = InParent; Params.Name = InName; Params.SetFlags = Flags; UMyDataAsset* NewMyAsset = CastChecked<UMyDataAsset>(StaticConstructObject_Internal(Params)); FJsonObjectConverter::JsonObjectToUStruct(JsonObject.ToSharedRef(), Class, (void*)(NewMyAsset), 0, 0); return NewMyAsset; } UE_LOG(LogTemp, Error, TEXT("UMyDataAssetFactory::FactoryCreateText: nativeClass was not found")); return nullptr; } bool UMyDataAssetFactory::CanReimport(UObject* Obj, TArray<FString>& OutFilenames) { UMyDataAsset* MyAsset = Cast<UMyDataAsset>(Obj); if (MyAsset != nullptr && MyAsset->AssetImportData != nullptr) { MyAsset->AssetImportData->ExtractFilenames(OutFilenames); return true; } return false; } void UMyDataAssetFactory::SetReimportPaths(UObject* Obj, const TArray<FString>& NewReimportPaths) { UMyDataAsset* MyAsset = Cast<UMyDataAsset>(Obj); if (MyAsset && ensure(NewReimportPaths.Num() == 1)) { MyAsset->AssetImportData->UpdateFilenameOnly(NewReimportPaths[0]); } } EReimportResult::Type UMyDataAssetFactory::Reimport(UObject* Obj) { UMyDataAsset* MyAsset = Cast<UMyDataAsset>(Obj); if (!MyAsset) { return EReimportResult::Failed; } const FString Filename = MyAsset->AssetImportData->GetFirstFilename(); if (!Filename.Len() || IFileManager::Get().FileSize(*Filename) == INDEX_NONE) { return EReimportResult::Failed; } EReimportResult::Type Result = EReimportResult::Failed; if (UFactory::StaticImportObject(MyAsset->GetClass(), MyAsset->GetOuter(), *MyAsset->GetName(), RF_Public | RF_Standalone, *Filename, NULL, this)) { if (MyAsset->GetOuter()) { MyAsset->GetOuter()->MarkPackageDirty(); } else { MyAsset->MarkPackageDirty(); } return EReimportResult::Succeeded; } return EReimportResult::Failed; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#pragma once #include "CoreMinimal.h" #include "Modules/ModuleManager.h" #include "MyProject/MyDataAsset/AssetTypeActions_MyDataAsset.h" class FAssetTypeActions_MyDataAsset; class FMyProjectModule : public IModuleInterface { public: virtual void StartupModule() override; virtual void ShutdownModule() override; TSharedPtr<FAssetTypeActions_MyDataAsset> MyDataAsset_AssetTypeActions; }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#include "MyProject.h" #define LOCTEXT_NAMESPACE "FMyProjectModule" void FMyProjectModule::StartupModule() { MyDataAsset_AssetTypeActions = MakeShareable(new FAssetTypeActions_MyDataAsset); FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools").Get().RegisterAssetTypeActions(MyDataAsset_AssetTypeActions.ToSharedRef()); } void FMyProjectModule::ShutdownModule() { if (MyDataAsset_AssetTypeActions.IsValid()) { if (FModuleManager::Get().IsModuleLoaded("AssetTools")) { FModuleManager::GetModuleChecked<FAssetToolsModule>("AssetTools").Get().UnregisterAssetTypeActions(MyDataAsset_AssetTypeActions.ToSharedRef()); } MyDataAsset_AssetTypeActions.Reset(); } } #undef LOCTEXT_NAMESPACE IMPLEMENT_MODULE(FMyProjectModule, MyProject) |
1 2 3 4 5 6 7 8 9 10 |
~略~ PrivateDependencyModuleNames.AddRange( new string[] { ~略~ "Slate", "SlateCore", "AssetTools", } ); |
これで、インポートができるようになりました。
自動エクスポートには事故もつきものですので、導入には慎重な判断が必要ですが、やってみる価値はあると思います。
ソースコードが多くなってしまったので、制作物をこちらからダウンロードできるようにしておきます。
UE4.27.0 です。
ありがとうございました。