I managed to possibly figure it out for now. I haven’t seen any problems yet. I put a breakpoint in NewObject and managed to capture it at just the right moment when creating an instanced inline class in the editor.
It’s based on this code: https://github.com/EpicGames/UnrealEngine/blob/c3caf7b6bf12ae4c8e09b606f10a09776b4d1f38/Engine/Source/Editor/PropertyEditor/Private/UserInterface/PropertyEditor/SPropertyEditorEditInline.cpp#L224
This is my real code, and it seems to work.
EObjectFlags MaskedOuterFlags = GetMaskedFlags(RF_PropagateToSubObjects);
if (HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
{
MaskedOuterFlags |= RF_ArchetypeObject;
}
URDBaseHierarchicalRotationController* Controller = NewObject<URDBaseHierarchicalRotationController>(this, ControllerClass, NAME_None, MaskedOuterFlags);
This is based on my modified forum post code:
EObjectFlags MaskedOuterFlags = SomeManager->GetMaskedFlags(RF_PropagateToSubObjects);
if (SomeManager->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
{
MaskedOuterFlags |= RF_ArchetypeObject;
}
SomeObject* SomeObjectInstance= NewObject<SomeObject>(SomeManager, SomeObject::StaticClass(), NAME_None, MaskedOuterFlags);
SomeManager->SomeObjects.Add(SomeObjectInstance);
This is code that ultimately gets called from the constructor of an actor that has a component that manages instances of an object. It’s basically for a system that lets me control how different body parts of a character face the world depending on AI focus modes and NPC states and other such things.
template <typename T>
T* CreateRotationController(TSubclassOf<URDBaseHierarchicalRotationController> ControllerClass = T::StaticClass(), int32 Index = -1)
{
return Cast<T>(CreateRotationController(ControllerClass, Index));
}
UFUNCTION(BlueprintCallable, Category = "Rotation")
URDBaseHierarchicalRotationController* CreateRotationController(TSubclassOf<URDBaseHierarchicalRotationController> ControllerClass, int32 Index = -1);
URDBaseHierarchicalRotationController* URDBaseHierarchicalRotationControlManager::CreateRotationController(TSubclassOf<URDBaseHierarchicalRotationController> ControllerClass, int32 Index)
{
if (!ControllerClass)
{
return nullptr;
}
EObjectFlags MaskedOuterFlags = GetMaskedFlags(RF_PropagateToSubObjects);
if (HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
{
MaskedOuterFlags |= RF_ArchetypeObject;
}
URDBaseHierarchicalRotationController* Controller = NewObject<URDBaseHierarchicalRotationController>(this, ControllerClass, NAME_None, MaskedOuterFlags);
SetRotationControllerIndex(Controller, Index);
return Controller;
}
ANewRotationTestCharacter::ANewRotationTestCharacter(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
bUseControllerRotationPitch = true;
bUseControllerRotationYaw = true;
bUseControllerRotationRoll = true;
HierarchicalRotationControlComponent = CreateDefaultSubobject<URDBaseHierarchicalRotationControlComponent>("HierarchicalRotationControlComponent");
HeadRotationController = HierarchicalRotationControlComponent->GetRotationControlManager()->CreateRotationController<URDBaseHierarchicalRotationController>();
HeadRotationController->PitchAxisInfo.RelativeLimitMax = 45.f;
HeadRotationController->PitchAxisInfo.RelativeLimitMin = 50.f;
HeadRotationController->YawAxisInfo.RelativeLimitMax = 70.f;
HeadRotationController->YawAxisInfo.RelativeLimitMin = 70.f;
HeadRotationController->RollAxisInfo.RelativeLimitMax = 30.f;
HeadRotationController->RollAxisInfo.RelativeLimitMin = 30.f;
TorsoRotationController = HierarchicalRotationControlComponent->GetRotationControlManager()->CreateRotationController<USFCharacterTorsoHierarchicalRotationController>();
TorsoRotationController->PitchAxisInfo.RelativeLimitMax = 45.f;
TorsoRotationController->PitchAxisInfo.RelativeLimitMin = 50.f;
TorsoRotationController->YawAxisInfo.RelativeLimitMax = 70.f;
TorsoRotationController->YawAxisInfo.RelativeLimitMin = 70.f;
TorsoRotationController->RollAxisInfo.bFaceRotationAxisEnabled = false;
TorsoRotationController->RollAxisInfo.RelativeLimitMin = 30.f;
TorsoRotationController->RollAxisInfo.RelativeLimitMax = 30.f;
ActorRotationController = HierarchicalRotationControlComponent->GetRotationControlManager()->CreateRotationController<USFCharacterActorHierarchicalRotationController>();
ActorRotationController->PitchAxisInfo.bFaceRotationAxisEnabled = false;
ActorRotationController->PitchAxisInfo.RelativeLimitMax = 22.5f;
ActorRotationController->PitchAxisInfo.RelativeLimitMin = 22.5f;
ActorRotationController->RollAxisInfo.bFaceRotationAxisEnabled = false;
ActorRotationController->RollAxisInfo.RelativeLimitMin = 22.5f;
ActorRotationController->RollAxisInfo.RelativeLimitMax = 22.5f;
}
I have properties in my actor for HeadRotationController, TorsoRotationController, and ActorRotationController and they all point to the same instance that’s in the array managed by the manager. That way when I put my actor in a level I can also make my characters have customizeable limits and modes on how they rotate to face their focus. This way a monster, shop keeper, or other NPC can have easily customizeable modes for how different parts of their body turn towards their targets. This is the system I’m trying to build and it’s just a matter of getting the right combination of UPROPERTY flags and C++ code to get it working right.
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Rotation")
URDBaseHierarchicalRotationControlComponent* HierarchicalRotationControlComponent;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Instanced, Category = "Rotation")
URDBaseHierarchicalRotationController* HeadRotationController;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Instanced, Category = "Rotation")
USFCharacterTorsoHierarchicalRotationController* TorsoRotationController;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Instanced, Category = "Rotation")
USFCharacterActorHierarchicalRotationController* ActorRotationController;