Changing component types causes corrupted BP

Just was wondering if this is a known issue:

1: create a class with a certain component type such as a skeletal mesh ect

2: connect a BP to the class

3: Change the component to something else like a static mesh via C++

4: Build

What happens:
When you click on the changed object in the bp, There are no object details so this forces you to create a new BP with the class

Is there a way to get around this without having to create a new BP?

I have the same problem.
I had to change my UBoxComponent to USphereComponent in my already component packed BP.

I don’t want to re-create the BP from scratch, I spent quite a bit of time on it.
Any ideas?

Or perhaps creating components in C++ and editing them in BP is not the way to go. Perhaps it’s better to create the components in the BP editor and bind them to the C++ variables using the Construction Graph.

The only thing that bothers me with creating components in the BP instead of code is that I’m not sure on the corrupt rate of blueprints. I’d have to redo even more stuff if that blueprint were to get corrupted my something else somehow

Very good argument. I think we need to wait for Epic’s answer. I am on holiday now, but I will submit a bug report when I go back home.
In the meantime, is there any way to fix that corrupt blueprint?

nope, you just have to recreate it :frowning:

There are definitely some issues with the robustness of the interaction between C++, Blueprint and CDOs. It can lead to some really awkward to solve problems. I’m not certain this is the issue you have, but the following may help.

I’m assuming you were initializing the component in C++ in the constructor. When you change the component type, the next time you load your BP it will fail to load the property, and probably sets it to null.

If you now put EditAnywhere in your component property specifiers rather than VisibleAnywhere, then build and run, in your Blueprint you should then see the yellow ‘reset to default’ arrow next to your component in the details panel. Hopefully if you click that, it will reinitialize the blueprint’s component back to whatever you assigned to the new component in your class constructor. If so, you can then just save the BP and then switch back to VisibleAnywhere again.

That didn’t work, sadly. I couldn’t see any arrow because the details panel is not rendering anything. For what it’s worth, here is how I declare my properties in the header and how I initialise them in my constructor:
(the CollisionBody has its type changed, this is the corrupted one)

public:
	UPROPERTY(Category = Weapons, BlueprintReadOnly, EditAnywhere)
	TSubclassOf<AActor> BulletsClass;

	UPROPERTY(Category = Pawn, BlueprintReadOnly, EditAnywhere)
	class UBoxComponent* CollisionBody;

    UPROPERTY(Category = Pawn, BlueprintReadOnly, EditAnywhere)
    class UStaticMeshComponent* ShipMesh;
    
    UPROPERTY(Category = Pawn, BlueprintReadOnly, EditAnywhere)
    class USCShipMovement* Movement;

And I initialise them as such:

ASCShip::ASCShip (const FObjectInitializer& FO): Super(FO)
{    
	CollisionBody = FO.CreateDefaultSubobject<UBoxComponent>(this, TEXT("CollisionBody"));
	CollisionBody->SetSimulatePhysics(true);
    CollisionBody->SetEnableGravity(false);

	RootComponent = CollisionBody;
	            
	SpringArm = FO.CreateDefaultSubobject<USpringArmComponent>(this, TEXT("SpringArm"));
	SpringArm->AttachTo(CollisionBody);

	ShipMesh = FO.CreateDefaultSubobject<UStaticMeshComponent>(this, TEXT("ShipMesh"));
	ShipMesh->AttachTo(SpringArm);
	ShipMesh->SetSimulatePhysics(false);

 
	Movement = FO.CreateDefaultSubobject<USCShipMovement>(this, TEXT("Movement"));

	CollisionBody->OnComponentHit.AddDynamic(this, &ASCShip::OnCollisionBodyHit);
    
    PrimaryActorTick.bCanEverTick = true;
}

This could also be a good chance to ask where to add collision callbacks. Would it be best to do in the BeginPlay, or the constructor? More specifically, what should be initialised in the constructor and what in the BeginPlay? It feels like only components should be initialised in the constructor, am I correct?

Hmm, I just did a quick test by making a component EditAnywhere (note that generally your components should be VisibleAnywhere, but maybe they were before my suggestion) and setting it to None in the blueprint editor. On reselecting the component the details panel was blank, as you say. I wonder if this is a bug introduced in a recent version - the way components and their properties are displayed in the blueprint editor has changed from when I solved my similar issue a while back. Not sure what else to suggest.

As for callbacks. This is not something I’ve had confirmed by anyone, but I now avoid registering delegates in constructors. I had an almighty bug hunt a while ago where I couldn’t work out why my overlap handler wasn’t getting called. It turned out that a delegate I’d registered in my constructor had somehow been stored (presumably within the blueprint CDO) and remained there even after I changed the code to use a different delegate - despite the fact the original method had been removed from the class entirely, it was still stored in the delegate by name. When I deleted and recreated the blueprint the issue went away.

The idea that blueprints can get into invalid states as a result of just making changes to their parent class really doesn’t sit well with me. Anyway, I concluded that registering the delegates in the constructor was the cause in that instance, but I can’t be sure.

I think that I will have to rebuild the blueprint from start, I don’t see another way :frowning:
This is really frustrating and feels very dodgy… especially in the case of prototyping/iterating where components and their types change almost daily. This can lead to enormous problems. The option of setting the components in the blueprint and linking them to tjhe C++ variables is not ideal either since my AShip class will be used to make dozens of blueprints, I’d like their components to be at least initialised in the order I set in C++.

Callbacks and anything that needs to be initialised when the game runs, I think I’ll just put them in BeginPlay. I am consulting the UT sourcecode for some things and following in their footsteps (although I am not sure about the callbacks and how they handle the aforementioned blueprint problem).

yep, me neither :frowning:

Okay, this is not a solution or an answer, however it seems that the detail panel is broken only in the full blueprint editor. If you drag your class blueprint in the scene view and inspect its components they are fine (including the previously broken one!).

I am using Unreal 4.7.5. Did this shed any light?

Hey everyone,

After reading through this post I noticed that the bug being reported (the details window being blank after changing a code component) has been fixed and tested on our internal 4.8 build. Please let me know if you’re still seeing this issue once 4.8 is released.

Cheers

Doug Wilson

That’s music to my ears. I will be testing this when 4.8 is released, thanks.

Hi Doug, this looks to be a very similar issue, with 4.8.

Doug, I’ve just upgraded to 4.8 and gave this a quick test, unfortunately the issue appears to exist just as it was before. Here are precise repro steps (probably including a number of things that aren’t strictly necessary):

  1. Create new blank project.
  2. Add new C++ class, derived from Actor.
  3. Add new blueprint, based on new C++ class.
  4. Close editor.
  5. Add in the header:

UPROPERTY(VisibleAnywhere, Category = “Components”)
class USphereComponent* PostBP_OriginallySphereComponent;

  1. Add in the cpp constructor:

PostBP_OriginallySphereComponent = CreateDefaultSubobject< USphereComponent >(“PostBP_OriginallySphereComponentName”);

  1. Compile and run project.
  2. Open blueprint, all should be fine, save blueprint, close editor.
  3. Replace ‘USphereComponent’ with ‘UBoxComponent’ in the header and cpp, but leaving the member variable name and the literal name unchanged.
  4. Compile and run project.
  5. Open blueprint. Select the component in the components list, in details panel it will show as ‘None’.

Note that instances of the blueprint subsequently added in the level editor work fine. Further, the box component will display in the blueprint editor viewport even though it is shown as ‘None’ in the details panel.

Also, if having reached step 11, you comment out the line in the header and in the cpp, then repeat 7 & 8, uncomment and compile/run again, the problem will go away. So it seems (at a guess) that the serialization of the blueprint/CDO can cope with a change to a component type if done in two steps (removal first, then reintroducing with a new type), but if it’s done in one step then it fails.

Edit: Sorry can’t fight anymore with the autonumbering!

Hey kamrann-

I was able to reproduce what you’re seeing using the code and steps you provided and have reported the bug (UE-18284) for investigation. I did find that this only occurs when using the “VisibleAnywhere” specifier inside the UPROPERTY() macro. Using EditAnywhere instead will set the component or provide the yellow reset arrow if not set automatically.

Just got this issue in 4.12

Hey AJQuick-

The Bug report mentioned (UE-18284) is still open for investigation by developers. Can you provide any information about your setup or the results you’re seeing? As mentioned, if you’re using VisibleAnywhere in the UPROPERTY() of your variable then this will occur and can be avoided by using EditAnywhere instead.

I have a custom character subclass with its own movement component. I am using the ‘SetDefaultSubobjectClass’ method in the constructor to assign my movement component class to the pawn in lieu of the default one. As you can see, I am doing the same with the Capsule component. The capsule component assignment works correctly, but the movement component, does not. The code compiles, but when I open any blueprint deriveded from my custom character, the movement component appears as ‘None’.

Unfortunately the workaround of using the ‘EditAnywhere’ specifier doesn’t help me , because the CharacterMovement UProperty is defined in Character, which is an engine class and I’d prefer not to change engine headers if it all possible.

1 Like

I’m trying to recreate the setup from your screenshot and want to make sure I’m doing the same thing you are. Are UME_CharacterCollisionComponent and UME_CharacterMovementComponent classes you’ve created? Also, are you able to use SetDefaultSubobjectClass inside the constructor rather than adding the code to the Super?