Import basic Assets
Importing assets using UBlueprintFunctionLibrary
class works in the editor mode only. While we use it in the editor, we need to add 2 additional modules into project's .Build.cs
file. However, as it's editor only, those modules must be removed from the .Build.cs file before packaging the project (e.g. building the Windows app).
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules - Editor Only
"AssetTools",
"UnrealEd",
}
);
Importing various types of Assets
Import of basic data types (textures, sounds...) (Editor based
)
As mentioned, we work in an inherited class from UBlueprintFunctionLibrary
, thus our header file should look like below:
UCLASS()
class UExampleClass : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
/**
* Editor Only - Will not work in packaged build.
*
* Create and process a basic import task.
* Will work for the basic asset types like textures and sounds.
* Can also be used for meshes, but you might not have all the control you want.
*
* @param SourcePath The path of the source file: "C:/Temp/MyTexture.png"
* @param DestinationPath The path of the imported asset: "/Game/Folder/MyTexture"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The imported asset
*/
UFUNCTION(BlueprintCallable, Category = "Import Basic Assets")
static UObject* ImportAsset(FString SourcePath, FString DestinationPath, bool& bOutSuccess, FString& OutInfoMsg);
// CreateImportTask help function
// ProcessImportTask help function
};
#include "Editor/UnrealEd/Public/AssetImportTask.h" // UnrealEd (Editor Only)
#include "AssetToolsModule.h" // AssetTools (Editor Only)
UObject* UExampleClass::ImportAsset(FString SourcePath, FString DestinationPath, bool& bOutSuccess, FString& OutInfoMsg)
{
// Create the import task
UAssetImportTask* Task = CreateImportTask(SourcePath, DestinationPath, nullptr, nullptr, bOutSuccess, OutInfoMsg);
if (!bOutSuccess) return nullptr;
// Import the asset
UObject* RetAsset = ProcessImportTask(Task, bOutSuccess, OutInfoMsg);
if (!bOutSuccess) return nullptr;
// Return the imported asset
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Import Asset Succeeded - '%s'"), *DestinationPath);
return RetAsset;
}
Within the UExampleClass::ImportAsset
, we link at 2 help custom functions - CreateImportTask
and ProcessImportTask
that can be defined within the same UExampleClass
.
CreateImportTask
custom help function
/**
* Editor Only - Will not work in packaged build.
*
* Create an import task that you can then process to import any kind of assets
*
* @param SourcePath The path of the source file: "C:/Temp/MyTexture.png"
* @param DestinationPath The path of the imported asset: "/Game/Folder/MyTexture"
* @param ExtraFactory Optional. Some asset types require a special factory to import them
* @param ExtraOptions Optional. Some asset types have some extra settings you can set
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The import task
*/
UFUNCTION(BlueprintCallable, Category = "Import Basic Assets")
static class UAssetImportTask* CreateImportTask(FString SourcePath, FString DestinationPath, UFactory* ExtraFactory, UObject* ExtraOptions, bool& bOutSuccess, FString& OutInfoMsg);
#include "Editor/UnrealEd/Public/AssetImportTask.h" // UnrealEd (Editor Only)
#include "AssetToolsModule.h" // AssetTools (Editor Only)
UAssetImportTask* UExampleClass::CreateImportTask(FString SourcePath, FString DestinationPath, UFactory* ExtraFactory, UObject* ExtraOptions, bool& bOutSuccess, FString& OutInfoMsg)
{
// Create task object
UAssetImportTask* Task = NewObject<UAssetImportTask>();
if (Task == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Create Import Task Failed - Was not able to create the import task object. That shouldn't really happen. - '%s'"), *SourcePath);
return nullptr;
}
// Set path informations - fill with function parameters
Task->Filename = SourcePath;
Task->DestinationPath = FPaths::GetPath(DestinationPath);
Task->DestinationName = FPaths::GetCleanFilename(DestinationPath);
// Set basic options
Task->bSave = false; // save file once task completed?
Task->bAutomated = true; // automated = no popups for the user
Task->bAsync = false;
Task->bReplaceExisting = true;
Task->bReplaceExistingSettings = false;
// Optional extra factory and options
Task->Factory = ExtraFactory;
Task->Options = ExtraOptions;
// Return the task
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Create Import Task Succeeded - '%s'"), *SourcePath);
return Task;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules - Editor Only
"UnrealEd",
}
);
In the configuration above, imported assets are not saved automatically due to Task->bSave = false
setup.
ProcessImportTask
custom help function
/**
* Editor Only - Will not work in packaged build.
*
* Process the import task to import the assets
*
* @param ImportTask The task you want to process
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The imported asset
*/
UFUNCTION(BlueprintCallable, Category = "Import Basic Assets")
static UObject* ProcessImportTask(UAssetImportTask* ImportTask, bool& bOutSuccess, FString& OutInfoMsg);
UObject* UExampleClass::ProcessImportTask(UAssetImportTask* ImportTask, bool& bOutSuccess, FString& OutInfoMsg)
{
if (ImportTask == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Process Import Task Failed - The task was invalid. Cannot process."));
return nullptr;
}
// Get the AssetTools module
FAssetToolsModule* AssetTools = FModuleManager::LoadModulePtr<FAssetToolsModule>("AssetTools");
if (AssetTools == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Process Import Task Failed - The AssetTools module is invalid. - '%s'"), *ImportTask->Filename);
return nullptr;
}
// Import the asset
AssetTools->Get().ImportAssetTasks({ Task });
// Check if anything was imported during the process
if (ImportTask->GetObjects().Num() == 0)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Process Import Task Failed - Nothing was imported. Is your file valid? Is the asset type supported? - '%s'"), *ImportTask->Filename);
return nullptr;
}
// Because some import tasks actually create multiple assets (e.g. SkeletalMesh), we manually get the right asset
UObject* ImportedAsset = StaticLoadObject(UObject::StaticClass(), nullptr, *FPaths::Combine(ImportTask->DestinationPath, ImportTask->DestinationName));
// Return the asset
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Process Import Task Succeeded - '%s'"), *ImportTask->Filename);
return ImportedAsset;
}
In the similar way, there's possible:
Reimport Asset (Editor based
)
The code below is a C++ way of following manual operation: "Selecting an asset in Content
window" → Right mouse click → Selecting Reimport
option or alternatively Reimport With New File
option.
/**
* Editor Only - Will not work in packaged build.
*
* Reimport an already imported asset
*
* @param AssetPath The path of the asset to reimport: "/Game/Folder/MyTexture"
* @param SourcePathOverride (Optional) The path of the source file (if you want to use a new file): "C:/Temp/MyTexture.png"
* @param OutInfoMessage More information about the action's result
* @param return If the action was a success or not
*/
UFUNCTION(BlueprintCallable, Category = "Reimport Asset")
static bool ReimportAsset(FString AssetPath, FString SourcePathOverride, FString& OutInfoMsg);
#include "EditorReimportHandler.h" // UnrealEd
bool UExampleClass::ReimportAsset(FString AssetPath, FString SourcePathOverride, FString& OutInfoMsg)
{
// Load existing asset
UObject* ExistingAsset = StaticLoadObject(UObject::StaticClass(), nullptr, *AssetPath);
if (ExistingAsset == nullptr)
{
OutInfoMsg = FString::Printf(TEXT("Reimport Asset Failed - Asset isn't valid. '%s'"), *AssetPath);
return false;
}
// Update path
if (SourcePathOverride != "" && !UExampleClass::SetAssetImportPath(AssetPath, SourcePathOverride, OutInfoMsg)) return false;
// Reimport
if (FReimportManager::Instance()->Reimport(ExistingAsset))
{
OutInfoMsg = FString::Printf(TEXT("Reimport Asset Succeeded - '%s'"), *AssetPath);
return true;
}
bool bOutSuccess;
FString Path = UExampleClass::GetAssetImportPath(AssetPath, bOutSuccess, OutInfoMsg);
OutInfoMessage = FString::Printf(TEXT("Reimport Asset Failed - Is the source path valid? \n'%s'"), *Path);
return False;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules - Editor Only
"UnrealEd",
}
);
Get / Set Asset Import Source Path (Editor based
)
The import path (File Path
) is the path of the file that was used to import the asset to Unreal Engine. The code below allows to get File Path of any asset as well as change it to link at another file.
Get Asset Import Path
/**
* Editor Only - Will not work in packaged build.
*
* Get the path used to import his asset
*
* @param AssetPath The path of the asset: "/Game/Folder/MyTexture"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The path used to import this asset
*/
UFUNCTION(BlueprintCallable, Category = "Modify Asset Import Path")
static FString GetAssetImportPath(FString AssetPath, bool& bOutSuccess, FString& OutInfoMsg);
#include "EditorReimportHandler.h" // UnrealEd
#include "EditorFramework/AssetImportData.h" // Engine
FString UExampleClass::GetAssetImportPath(FString AssetPath, bool& bOutSuccess, FString& OutInfoMsg)
{
// Load asset
UObject* Asset = StaticLoadObject(UObject::StaticClass(), nullptr, *AssetPath);
if (Asset == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Get Asset Import Path Failed - Asset isn't valid. '%s'"), *AssetPath);
return "";
}
// Can we use the ReimportManager to get the import path?
TArray<FString> Paths = TArray<FString>();
if (FReimportManager::Instance()->CanReimport(Asset, &Paths) && Paths.Num() > 0)
{
FString Path = Paths[0];
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Get Asset Import Path Succeeded [ReimportManager] - '%s'\n'%s'"), *AssetPath, *Path);
return Path;
}
else
{
// Get the path manually
UAssetImportData* AssetImportData = GetAssetImportData(Asset);
if (AssetImportData != nullptr)
{
FString Path = AssetImportData->GetFirstFilename();
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Get Asset Import Path Succeeded - '%s'\n'%s'"), *AssetPath, *Path);
return Path;
}
}
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Get Asset Import Path Failed - Asset class not in GetAssetImportData: '%s'"), *AssetPath);
return "";
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules - Editor Only
"UnrealEd",
}
);
Set Asset Import Path
/**
* Editor Only - Will not work in packaged build.
*
* Set the path used to import his asset
*
* @param AssetPath The path of the asset: "/Game/Folder/MyTexture"
* @param NewImportPath The path of the new source files: "C:/Temp/MyTexture.png"
* @param OutInfoMsg More information about the action's result
* @param return If the action was a success or not
*/
UFUNCTION(BlueprintCallable, Category = "Modify Asset Import Path")
static bool SetAssetImportPath(FString AssetPath, FString NewImportPath, FString& OutInfoMsg);
#include "EditorReimportHandler.h" // UnrealEd
#include "EditorFramework/AssetImportData.h" // Engine
bool UExampleClass::SetAssetImportPath(FString AssetPath, FString NewImportPath, FString& OutInfoMsg)
{
// Load asset
UObject* Asset = StaticLoadObject(UObject::StaticClass(), nullptr, *AssetPath);
if (Asset == nullptr)
{
OutInfoMsg = FString::Printf(TEXT("Set Asset Import Path Failed - Asset isn't valid. '%s'"), *AssetPath);
return false;
}
// Can we use the ReimportManager to set the import path?
if (FReimportManager::Instance()->CanReimport(Asset, nullptr))
{
FReimportManager::Instance()->UpdateReimportPath(Asset, NewImportPath, 0);
OutInfoMsg = FString::Printf(TEXT("Set Asset Import Path Succeeded [ReimportManager] - '%s'\n'%s'"), *AssetPath, *NewImportPath);
return true;
} else {
// Set the path manually
UAssetImportData* AssetImportData = GetAssetImportData(Asset);
if (AssetImportData != nullptr)
{
AssetImportData->SetSourceFiles({ NewImportPath });
OutInfoMsg = FString::Printf(TEXT("Set Asset Import Path Succeeded - '%s'\n'%s'"), *AssetPath, *NewImportPath);
return true;
}
}
OutInfoMsg = FString::Printf(TEXT("Set Asset Import Path Failed - Asset class not in GetAssetImportData: '%s'"), *AssetPath);
return false;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules - Editor Only
"UnrealEd",
}
);
- Setting
Source File
path forMeshes
works only when setting a path with unreal-supported asset type endings (.fbx, and so on). - Setting
Source File
forTexture
does not care about extension of the source path - Setting
Source File
forSound
does not care about extension of the source path
Get the Asset Import Data based on the asset class
/**
* Editor Only - Will not work in packaged build.
*
* Get the Asset Import Data based on the asset class
*
* @param Asset The asset
*
* @return Asset import data
*/
UFUNCTION(BlueprintCallable, Category = "Modify Asset Import Path")
static class UAssetImportData* GetAssetImportData(UObject* Asset);
#include "Engine/StaticMesh.h" // Engine
#include "Engine/SkeletalMesh.h" // Engine
#include "Engine/Texture.h" // Engine
#include "Animation/AnimSequence.h" // Engine
#include "Engine/DataTable.h" // Engine
#include "Sound/SoundWave.h" // Engine
UAssetImportData* UExampleClass::GetAssetImportData(UObject* Asset)
{
if (Cast<UStaticMesh>(Asset) != nullptr) // UStaticMesh
{
return Cast<UStaticMesh>(Asset)->AssetImportData;
}
else if (Cast<USkeletalMesh>(Asset) != nullptr) // USkeletalMesh
{
return Cast<USkeletalMesh>(Asset)->GetAssetImportData();
}
else if (Cast<UTexture>(Asset) != nullptr) // UTexture
{
return Cast<UTexture>(Asset)->AssetImportData;
}
else if (Cast<UAnimSequence>(Asset) != nullptr) // UAnimSequence
{
return Cast<UAnimSequence>(Asset)->AssetImportData;
}
else if (Cast<UDataTable>(Asset) != nullptr) // UDataTable
{
return Cast<UDataTable>(Asset)->AssetImportData;
}
else if (Cast<USoundWave>(Asset) != nullptr) // USoundWave
{
return Cast<USoundWave>(Asset)->AssetImportData;
}
// Add all other asset types you want to support.
return nullptr;
}