ObjectManager
The ObjectManager is a specialized library component that handles the creation, management, and cleanup of preview objects, overlay visuals, and directional arrows during the placement process. It manages the visual representation of objects being placed and provides seamless actor lifecycle management.
Overview
ObjectManager coordinates all visual elements during placement mode, including preview actors (with materials and opacity), placement overlay indicators, outline materials, and directional arrow components. It ensures proper cleanup and handles the complex interactions between different visual elements.
Key Features
- ✅ Preview Actor Management - Creates and manages translucent preview objects
- ✅ Overlay System - Handles placement indicator overlays with dynamic sizing
- ✅ Material Management - Manages dynamic materials for outline and overlay effects
- ✅ Arrow Integration - Coordinates with DirectionalArrowComponent for visual feedback
- ✅ Lifecycle Management - Proper creation and cleanup of all visual elements
- ✅ Performance Optimized - Efficient actor management with minimal overhead
Core Methods
Initialization
Initialize
void Initialize(UWorld* World);
Initializes the ObjectManager with a world context.
Parameters:
World
- The world context for spawning actors
Preview Actor Management
CreatePreviewActor
void CreatePreviewActor(TSubclassOf<AActor> ObjectClass, UMaterialInterface* SelectedOutlineMaterial);
Creates a preview actor for the specified object class with visual modifications.
Parameters:
ObjectClass
- The actor class to create a preview forSelectedOutlineMaterial
- Material for outline effect
Process:
- Destroys any existing preview actor
- Spawns new actor with no collision
- Applies preview opacity (0.5) to base material
- Creates dynamic outline material with initial color
- Applies outline material as overlay
Usage:
ObjectManager->CreatePreviewActor(ChairClass, SelectedOutlineMaterial);
DestroyPreviewActor
void DestroyPreviewActor();
Safely destroys the current preview actor and clears material references.
GetPreviewActor
AActor* GetPreviewActor() const;
Returns the current preview actor (can be null).
Overlay Actor Management
CreateOverlayActor
void CreateOverlayActor(UMaterialInterface* OverlayMaterial);
Creates a placement overlay actor (visual indicator on surfaces).
Parameters:
OverlayMaterial
- Material for the overlay plane
Process:
- Destroys any existing overlay actor
- Creates new actor with StaticMeshComponent
- Uses engine plane mesh as base geometry
- Creates dynamic material instance for color changes
- Disables collision and shadows
Usage:
if (bShowPlacementOverlay)
{
ObjectManager->CreateOverlayActor(OverlayMaterial);
}
DestroyOverlayActor
void DestroyOverlayActor();
Destroys the overlay actor and hides any associated arrows.
GetOverlayActor
AActor* GetOverlayActor() const;
Returns the current overlay actor (can be null).
GetOverlayMeshComponent
UStaticMeshComponent* GetOverlayMeshComponent() const;
Returns the mesh component of the overlay actor.
GetOverlayDynamicMaterial
UMaterialInstanceDynamic* GetOverlayDynamicMaterial() const;
Returns the dynamic material instance used for overlay color changes.
Material Management
GetOutlineDynamicMaterial
UMaterialInstanceDynamic* GetOutlineDynamicMaterial() const;
Returns the dynamic material instance used for outline effects on preview objects.
Arrow Management
SetupCurrentObjectArrow
void SetupCurrentObjectArrow(AActor* InPreviewActor, AActor* InEditingTarget);
Configures arrow visualization for the current object.
Parameters:
InPreviewActor
- The preview actor being placedInEditingTarget
- The object being edited (can be null for new placement)
Process:
- Checks preview actor first, then editing target for arrow component
- Gets arrow component via IPlaceableObjectInterface
- Shows arrow with current overlay material if available
- Hides arrow if no overlay material exists
UpdateArrowMaterial
void UpdateArrowMaterial();
Updates the arrow material to match the current overlay material.
GetCurrentArrowComponent
UDirectionalArrowComponent* GetCurrentArrowComponent() const;
Returns the currently active arrow component (can be null).
Settings
SetShowPlacementOverlay
void SetShowPlacementOverlay(bool bShow);
Controls whether placement overlays are created.
Parameters:
bShow
- Whether to show placement overlays
Cleanup
CleanupActors
void CleanupActors();
Destroys both preview and overlay actors. Called during mode transitions.
Material System
Preview Materials
ObjectManager manages multiple material layers for preview objects:
- Base Material: Modified with transparency (50% opacity)
- Outline Material: Applied as overlay material for visual feedback
// Base material opacity modification
if (UMaterialInterface* Material = MeshComp->GetMaterial(0))
{
UMaterialInstanceDynamic* DynamicMat = UMaterialInstanceDynamic::Create(Material, this);
if (DynamicMat)
{
DynamicMat->SetScalarParameterValue(TEXT("Opacity"), PREVIEW_OPACITY); // 0.5f
MeshComp->SetMaterial(0, DynamicMat);
}
}
Outline Materials
// Outline material setup
if (SelectedOutlineMaterial)
{
OutlineDynamicMaterial = UMaterialInstanceDynamic::Create(SelectedOutlineMaterial, this);
if (OutlineDynamicMaterial)
{
FLinearColor InitialColor = FLinearColor(0.5f, 0.5f, 0.5f, 1.0f);
OutlineDynamicMaterial->SetVectorParameterValue(TEXT("BaseColor"), InitialColor);
MeshComp->SetOverlayMaterial(OutlineDynamicMaterial);
}
}
Overlay Materials
// Dynamic overlay material for color changes
if (OverlayMaterial)
{
OverlayDynamicMaterial = UMaterialInstanceDynamic::Create(OverlayMaterial, this);
OverlayMeshComponent->SetMaterial(0, OverlayDynamicMaterial);
FLinearColor InitialColor = FLinearColor(0.5f, 0.5f, 0.5f, 1.0f);
OverlayDynamicMaterial->SetVectorParameterValue(TEXT("BaseColor"), InitialColor);
}
Integration with PlacementSystemComponent
ObjectManager is automatically configured and used by PlacementSystemComponent:
Configuration
// In PlacementSystemComponent::ConfigureComponents()
if (ObjectManager)
{
ObjectManager->SetShowPlacementOverlay(bShowPlacementOverlay);
}
Object Selection Process
// When selecting object to place
if (ObjectManager)
{
ObjectManager->CleanupActors();
ObjectManager->CreatePreviewActor(ObjectClass, SelectedOutlineMaterial);
if (bShowPlacementOverlay)
{
ObjectManager->CreateOverlayActor(OverlayMaterial);
}
ObjectManager->SetupCurrentObjectArrow(ObjectManager->GetPreviewActor(), EditingTarget);
}
Visual Updates
// During placement updates
if (ObjectManager)
{
ObjectManager->UpdateArrowMaterial(); // Sync arrow with overlay colors
}
Usage Examples
Basic Preview Creation
// Create preview for furniture placement
ObjectManager->Initialize(GetWorld());
ObjectManager->SetShowPlacementOverlay(true);
// Create preview with outline
ObjectManager->CreatePreviewActor(ChairClass, OutlineMaterial);
// Add overlay indicator
ObjectManager->CreateOverlayActor(OverlayMaterial);
Material Color Updates
// Update colors based on placement validity
void UpdateVisualFeedback(EPlacementValidity Validity)
{
FLinearColor TargetColor;
switch (Validity)
{
case EPlacementValidity::Valid:
TargetColor = FLinearColor::Green;
break;
case EPlacementValidity::Invalid:
TargetColor = FLinearColor::Red;
break;
default:
TargetColor = FLinearColor(0.5f, 0.5f, 0.5f, 1.0f);
break;
}
// Update overlay color
if (UMaterialInstanceDynamic* OverlayMaterial = ObjectManager->GetOverlayDynamicMaterial())
{
OverlayMaterial->SetVectorParameterValue(TEXT("BaseColor"), TargetColor);
}
// Update outline color
if (UMaterialInstanceDynamic* OutlineMaterial = ObjectManager->GetOutlineDynamicMaterial())
{
OutlineMaterial->SetVectorParameterValue(TEXT("BaseColor"), TargetColor);
}
// Update arrow color
ObjectManager->UpdateArrowMaterial();
}
Arrow Integration
// Setup arrow for object with directional component
if (AActor* PreviewActor = ObjectManager->GetPreviewActor())
{
ObjectManager->SetupCurrentObjectArrow(PreviewActor, nullptr);
// Check if arrow was found and configured
if (UDirectionalArrowComponent* Arrow = ObjectManager->GetCurrentArrowComponent())
{
UE_LOG(LogTemp, Log, TEXT("Arrow component configured for preview"));
}
}
Cleanup During Mode Changes
// When exiting placement mode
void CleanupPlacementMode()
{
if (ObjectManager)
{
ObjectManager->CleanupActors(); // Removes all visual elements
}
}
Constants
PREVIEW_OPACITY
static constexpr float PREVIEW_OPACITY = 0.5f;
Opacity value applied to preview objects (50% transparency).
Error Handling
ObjectManager includes comprehensive null-checking and validation:
void SafeCreatePreviewActor(TSubclassOf<AActor> ObjectClass)
{
if (!ObjectClass)
{
UE_LOG(LogTemp, Warning, TEXT("ObjectManager: Cannot create preview for null ObjectClass"));
return;
}
if (!CachedWorld)
{
UE_LOG(LogTemp, Error, TEXT("ObjectManager: World context not initialized"));
return;
}
ObjectManager->CreatePreviewActor(ObjectClass, SelectedOutlineMaterial);
// Verify creation
if (AActor* PreviewActor = ObjectManager->GetPreviewActor())
{
UE_LOG(LogTemp, Log, TEXT("Preview actor created successfully: %s"), *PreviewActor->GetName());
}
else
{
UE_LOG(LogTemp, Error, TEXT("Failed to create preview actor"));
}
}
Performance Considerations
Efficient Actor Management
- Reuse Prevention: Always destroys existing actors before creating new ones
- Minimal Components: Overlay actors use minimal component setup
- Collision Disabled: Preview and overlay actors have no collision
- Shadow Disabled: Overlay actors don't cast shadows
Memory Management
// Proper cleanup prevents memory leaks
void SafeDestroy(AActor* Actor)
{
if (Actor && IsValid(Actor))
{
Actor->Destroy();
}
}
Material Optimization
// Reuse material instances when possible
UMaterialInstanceDynamic* GetOrCreateDynamicMaterial(UMaterialInterface* BaseMaterial)
{
if (!BaseMaterial) return nullptr;
// Create new instance each time to ensure clean state
return UMaterialInstanceDynamic::Create(BaseMaterial, this);
}
Troubleshooting
Common Issues
"Preview actor not showing"
- Verify ObjectClass implements IPlaceableObjectInterface
- Check that CreatePreviewActor completed successfully
- Ensure world context is valid during creation
"Overlay not appearing"
- Verify bShowPlacementOverlay is true
- Check that overlay material is assigned
- Ensure overlay actor creation succeeded
"Colors not updating"
- Verify dynamic material instances exist
- Check parameter names match material expectations ("BaseColor")
- Ensure UpdateArrowMaterial is called after color changes
"Arrow not showing"
- Verify object implements IPlaceableObjectInterface
- Check that object has DirectionalArrowComponent
- Ensure overlay material exists before setting up arrow
Debug Commands
// Debug actor state
void DebugObjectManager()
{
UE_LOG(LogTemp, Log, TEXT("=== ObjectManager Debug ==="));
// Preview actor status
AActor* PreviewActor = ObjectManager->GetPreviewActor();
UE_LOG(LogTemp, Log, TEXT("Preview Actor: %s"),
PreviewActor ? *PreviewActor->GetName() : TEXT("None"));
// Overlay actor status
AActor* OverlayActor = ObjectManager->GetOverlayActor();
UE_LOG(LogTemp, Log, TEXT("Overlay Actor: %s"),
OverlayActor ? *OverlayActor->GetName() : TEXT("None"));
// Material status
UMaterialInstanceDynamic* OverlayMat = ObjectManager->GetOverlayDynamicMaterial();
UMaterialInstanceDynamic* OutlineMat = ObjectManager->GetOutlineDynamicMaterial();
UE_LOG(LogTemp, Log, TEXT("Overlay Material: %s"), OverlayMat ? TEXT("Valid") : TEXT("None"));
UE_LOG(LogTemp, Log, TEXT("Outline Material: %s"), OutlineMat ? TEXT("Valid") : TEXT("None"));
// Arrow status
UDirectionalArrowComponent* Arrow = ObjectManager->GetCurrentArrowComponent();
UE_LOG(LogTemp, Log, TEXT("Arrow Component: %s"), Arrow ? TEXT("Valid") : TEXT("None"));
}
ObjectManager provides comprehensive visual management for the placement system, ensuring smooth creation, updates, and cleanup of all visual elements while maintaining excellent performance and reliability.