I am attempting to replace the visible component of a pawn with a different component at runtime (in my case a UCustomMeshComponent
with randomly generated vertices) and running into problems.
I set up my pawn like this in its constructor (where OurMesh
is a UCustomMeshComponent *
member variable):
ATestGeomPawn::ATestGeomPawn() : OurMesh(NULL)
{
PrimaryActorTick.bCanEverTick = false;
AutoPossessPlayer = EAutoReceiveInput::Player0;
// root is a scene component so this is placeable in the editor
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
// camera attached to root
UCameraComponent* Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("OurCamera"));
Camera->SetupAttachment(RootComponent);
Camera->SetRelativeLocation(FVector(-250.0f, 0.0f, 250.0f));
Camera->SetRelativeRotation(FRotator(-45.0f, 0.0f, 0.0f));
// create an initial visible component
RegenGeometry();
}
And RegenGeometry()
's intent is to set up the new component, destroying the old one if it exists (first time through it won’t). RegenGeometry()
may be called at any time (in my tests I have it bound to an action event):
void ATestGeomPawn::RegenGeometry() {
// destroy old mesh
if (OurMesh) {
OurMesh->DestroyComponent();
OurMesh = NULL;
}
TArray<FCustomMeshTriangle> tris;
// code for setting up tris omitted for brevity
// create and attach new mesh
OurMesh = NewObject<UCustomMeshComponent>(this);
OurMesh->SetCustomMeshTriangles(tris);
OurMesh->SetupAttachment(RootComponent);
}
However, this leads to all sorts of bad results. I’ve tried various hand-wavey iterations of this:
- The code as shown above just crashes the editor immediately, even if I don’t actually have an
ATestGeomPawn
placed in the map. - If I use the now-deprecated
NewNamedObject
instead, with the same name every time, it works initially but subsequent calls toRegenGeometry()
cause the mesh to disappear, with weird results shown in this video I made. - If I use
NewNamedObject
but generate a new name every time, it works initially but does not remove the initial component from the hierarchy, and has a similar visible outcome to the above, shown in this other video I made. - If I call
RegenGeometry()
inBeginPlay()
instead of the constructor, it is never visible.
How do I do this properly?
I’m super new to the Unreal SDK, as in yesterday morning I was doing a crash course through tutorials and docs to try and get this done. I eventually arrived at the above. I have a feeling that my mistake here is some misunderstanding of life-cycles, replication, or maybe e.g. reference counting due to say player input on the pawn or something:
Update: The player input theory is eliminated. I tried the exact same thing as above but with a regular actor instead of a pawn (camera eliminated, no player input, just RegenGeometry()
in constructor and nothing else), and the editor crashed in the same way. So it isn’t related to this being a pawn.
I’m not sure which direction to head in next.
(Full source, if relevant: TestGeomPawn.h and TestGeomPawn.cpp; the “grow” stuff I just threw in from the tutorial to make sure player input was working)