Examples
Common workflows and use cases for Elys Asset Tools.
Example 1: Reorganizing Content Structure
Scenario: You want to move all character assets from scattered locations into a centralized /Game/Characters/ folder.
Steps:
-
Analyze existing structure
// Scan current character locations
Subsystem->ScanFolder("/Game/Content/OldCharacters");
Subsystem->ScanFolder("/Game/Legacy/Characters"); -
Check dependencies
- Right-click each folder → Analyze Dependencies
- Note external references (maps, blueprints using these characters)
-
Move assets
TArray<FString> Sources = {
"/Game/Content/OldCharacters",
"/Game/Legacy/Characters"
};
Subsystem->StartMoveAssets(Sources, "/Game/Characters"); -
Clean up
// Delete now-empty source folders
Subsystem->DeleteEmptyFolders("/Game/Content");
Subsystem->DeleteEmptyFolders("/Game/Legacy");
Result: All character assets are now in /Game/Characters/ with references automatically updated.
Example 2: Pre-Release Cleanup
Scenario: Before shipping, clean up development assets and test content.
Steps:
-
Identify unused test content
// Scan test folder
FERP_AssetDependencyScanResult Result = Subsystem->ScanFolder("/Game/Test");
// Check for external referencers
if (Result.Referencers.Num() == 0)
{
UE_LOG(LogElysAssetTools, Log, TEXT("Safe to delete Test folder"));
} -
Safe delete unused folders
// These will only delete if safe
Subsystem->SafeDeleteFolder("/Game/Test");
Subsystem->SafeDeleteFolder("/Game/Development");
Subsystem->SafeDeleteFolder("/Game/Experiments"); -
Clean up empty folders and redirectors
Subsystem->DeleteEmptyFolders("/Game");
Subsystem->FixRedirectorsInFolder("/Game");
Result: Project is clean, only shipping content remains.
Example 3: Safe Asset Migration
Scenario: Migrate assets from an old plugin to your game content.
Steps:
-
Analyze plugin assets
// Understand what the plugin assets depend on
FERP_AssetDependencyScanResult Result = Subsystem->ScanFolder("/MyPlugin/Content");
// Log dependencies
for (const FAssetData& Dep : Result.Dependencies)
{
UE_LOG(LogElysAssetTools, Log, TEXT("Depends on: %s"), *Dep.PackageName.ToString());
} -
Move to game content
// Move assets from plugin to game
TArray<FString> Sources = {"/MyPlugin/Content/Characters"};
Subsystem->StartMoveAssets(Sources, "/Game/MigratedContent"); -
Verify and clean up
- Test that all references work
- Remove the plugin if no longer needed
- Delete empty folders
Result: Assets successfully migrated to game content.
Example 4: Batch Folder Operations
Scenario: You have multiple folders to move to a new structure.
Blueprint Example:
// Create an Editor Utility Widget
UCLASS()
class UBatchFolderMoveWidget : public UEditorUtilityWidget
{
UFUNCTION(BlueprintCallable)
void BatchMoveToNewStructure()
{
UERP_AssetToolsEditorSubsystem* Subsystem =
GEditor->GetEditorSubsystem<UERP_AssetToolsEditorSubsystem>();
// Define moves
TMap<FString, FString> Moves;
Moves.Add("/Game/Old/Characters", "/Game/Core/Characters");
Moves.Add("/Game/Old/Weapons", "/Game/Core/Weapons");
Moves.Add("/Game/Old/Maps", "/Game/Core/Maps");
// Execute moves
for (const auto& Move : Moves)
{
TArray<FString> Source = {Move.Key};
Subsystem->StartMoveAssets(Source, Move.Value);
// Wait for completion (in real widget, use async)
while (IsMoving())
{
FPlatformProcess::Sleep(0.1f);
}
}
// Final cleanup
Subsystem->DeleteEmptyFolders("/Game/Old");
UE_LOG(LogElysAssetTools, Log, TEXT("Batch move complete"));
}
};
Example 5: Automated Weekly Cleanup
Scenario: Run automatic cleanup every week to keep the project tidy.
Editor Utility Widget:
UCLASS()
class UWeeklyCleanupWidget : public UEditorUtilityWidget
{
UFUNCTION(BlueprintCallable)
void RunWeeklyCleanup()
{
UERP_AssetToolsEditorSubsystem* Subsystem =
GEditor->GetEditorSubsystem<UERP_AssetToolsEditorSubsystem>();
UE_LOG(LogElysAssetTools, Log, TEXT("Starting weekly cleanup..."));
// 1. Delete empty folders
Subsystem->DeleteEmptyFolders("/Game");
UE_LOG(LogElysAssetTools, Log, TEXT("✓ Deleted empty folders"));
// 2. Fix redirectors
Subsystem->FixRedirectorsInFolder("/Game");
UE_LOG(LogElysAssetTools, Log, TEXT("✓ Fixed redirectors"));
// 3. Scan for unused test assets
FERP_AssetDependencyScanResult TestResult = Subsystem->ScanFolder("/Game/Test");
if (TestResult.Referencers.Num() == 0)
{
Subsystem->SafeDeleteFolder("/Game/Test");
UE_LOG(LogElysAssetTools, Log, TEXT("✓ Removed unused test content"));
}
UE_LOG(LogElysAssetTools, Log, TEXT("Weekly cleanup complete!"));
}
};
Example 6: Finding Circular Dependencies
Scenario: Detect circular dependencies that could cause issues.
void FindCircularDependencies(const FString& FolderPath)
{
UERP_AssetToolsEditorSubsystem* Subsystem =
GEditor->GetEditorSubsystem<UERP_AssetToolsEditorSubsystem>();
// Scan folder
FERP_AssetDependencyScanResult Result = Subsystem->ScanFolder(FolderPath);
// Check each asset
for (const FAssetData& Asset : Result.ScannedAssets)
{
FString AssetPath = Asset.PackageName.ToString();
// Does this asset depend on something that depends on it?
for (const FAssetData& Dependency : Result.Dependencies)
{
// Scan the dependency
FERP_AssetDependencyScanResult DepResult =
Subsystem->ScanAsset(Dependency.PackageName.ToString());
// Check if dependency references us back
for (const FAssetData& DepReferencer : DepResult.Referencers)
{
if (DepReferencer.PackageName == Asset.PackageName)
{
UE_LOG(LogElysAssetTools, Warning,
TEXT("Circular dependency: %s <-> %s"),
*Asset.AssetName.ToString(),
*Dependency.AssetName.ToString());
}
}
}
}
}
Example 7: Pre-Move Validation
Scenario: Validate a move operation before executing it.
bool ValidateMoveOperation(const TArray<FString>& Sources, const FString& Destination)
{
UERP_AssetToolsEditorSubsystem* Subsystem =
GEditor->GetEditorSubsystem<UERP_AssetToolsEditorSubsystem>();
// Check 1: Destination exists
if (!FPaths::DirectoryExists(Destination))
{
UE_LOG(LogElysAssetTools, Error, TEXT("Destination folder does not exist"));
return false;
}
// Check 2: No conflicts
for (const FString& Source : Sources)
{
FString FolderName = FPaths::GetCleanFilename(Source);
FString TargetPath = FPaths::Combine(Destination, FolderName);
TArray<FAssetData> ExistingAssets;
AssetRegistry.GetAssetsByPath(*TargetPath, ExistingAssets, false);
if (ExistingAssets.Num() > 0)
{
UE_LOG(LogElysAssetTools, Error, TEXT("Conflict: %s already exists at destination"), *FolderName);
return false;
}
}
// Check 3: Sources have no external critical dependencies
for (const FString& Source : Sources)
{
FERP_AssetDependencyScanResult Result = Subsystem->ScanFolder(Source);
// Check for engine content dependencies (can't be moved)
for (const FAssetData& Dep : Result.Dependencies)
{
if (Dep.PackageName.ToString().StartsWith("/Engine"))
{
// Engine dependencies are OK
continue;
}
}
}
UE_LOG(LogElysAssetTools, Log, TEXT("Move validation passed"));
return true;
}
More Examples
For more examples and community contributions, visit:
Next Steps
- User Guide - Step-by-step tutorials
- API Reference - Complete API documentation
- FAQ - Common questions and answers