x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

How to swap out the visual mesh component of a pawn at run-time.

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 to RegenGeometry() 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() in BeginPlay() 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)

Product Version: UE 4.14
Tags:
more ▼

asked Feb 12 '17 at 05:38 PM in C++ Programming

avatar image

JCipriani
46 2 5 9

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

1 answer: sort voted first

So after a lot of hunting I stumbled on somebody else's code, and it turns out the problem is in the component creation. SetupAttachment isn't the right thing to do for runtime-created components. Instead of:

 OurMesh = NewObject<UCustomMeshComponent>(this);
 OurMesh->SetCustomMeshTriangles(tris);
 OurMesh->SetupAttachment(RootComponent);

I changed it to:

 OurMesh = NewObject<UCustomMeshComponent>(this);
 OurMesh->RegisterComponent();
 OurMesh->SetCustomMeshTriangles(tris);
 OurMesh->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform, NAME_None);

And it seems to be working, aside from the component initially created in the constructor sticking around in the object tree the whole time (which seems to be related to "default" values, but it doesn't seem to be having any bad effects, so...).

I'm not sure if I just missed this in the documentation, or if Epic felt like only developers who hunted the vast plains of the internet for it were worthy of the knowledge. The tutorials could be improved by mentioning clearly that the frequently used SetupAttachment isn't useful for runtime components.

more ▼

answered Feb 12 '17 at 08:46 PM

avatar image

JCipriani
46 2 5 9

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question