Hello fellow UE4 programmers,
I am using 4.9.1 and having trouble adding components to my Actor derived Blueprint in Construction Script as desired.
The components I am trying to add (and attach) are of a custom SceneComponent derived (C++) class. This class is supposed to contain an optional MeshComponent attached as a child.
Brief description and overview of the problem and the questions:
- Adding StaticMeshComponents with Add Component node works as expected.
- Adding SceneComponents with Add Component node and manually attaching StaticMeshComponents created with Add Component nodes to the SceneComponents works as expected.
- Custom SceneComponents created with Add Component node and manually attaching StaticMeshComponents created with Add Component nodes to them does not work. While the meshes are visible in the level editor viewport and Play Standalone Game, they aren’t visible in Play In Editor. This problem occured after I added PostDuplicate to the custom SceneComponent class.
- Adding custom SceneComponents with Add Component node and specifying instanced StaticMeshComponents automatically attached aren’t visible in Play In Editor and don’t have the intended hierarchy. Why and how do I fix this?
I’ve uploaded a small zip file to my Dropbox which contains the Blueprint asset, test level, source code, config and uproject: https://dl.dropboxusercontent.com/u/16914081/UE4/ComponentTrouble.zip
Would be nice if you could have a look. You can comment PostDuplicate in both header and source and see for yourself (note though that in the editor the attachment hierarchy will not be as intended anymore but once PIE or Play Standalone Game has had BeginPlay called).
Detail information:
Here is the code for the custom SceneComponent class
.h
#pragma once
#include "Components/SceneComponent.h"
#include "MySceneComponent.generated.h"
/**
* basic SceneComponent that comes with a customizable MeshComponent attached to it
*/
UCLASS(Blueprintable, ClassGroup = (Custom), EditinlineNew, meta = (BlueprintSpawnableComponent))
class MYPROJECT_API UMySceneComponent : public USceneComponent
{
GENERATED_BODY()
public:
// Sets default values for this component's properties
UMySceneComponent();
// Called when the game starts
virtual void BeginPlay() override;
virtual void PostDuplicate(bool bDuplicateForPIE) override;
UPROPERTY(BlueprintReadWrite, Category = "Mesh", EditAnywhere, Instanced)
UMeshComponent* MeshComponent;
};
.cpp
#include "MyProject.h"
#include "MySceneComponent.h"
UMySceneComponent::UMySceneComponent()
: Super()
{
bWantsBeginPlay = true;
MeshComponent = nullptr;
}
void UMySceneComponent::BeginPlay()
{
Super::BeginPlay();
if (MeshComponent)
{
//ensure it is both registered and attached if it isn't already attach
MeshComponent->RegisterComponent();
if (!(MeshComponent->IsAttachedTo(this)))
{
MeshComponent->AttachTo(this);
}
}
}
void UMySceneComponent::PostDuplicate(bool bDuplicateForPIE)
{
//does not make a difference whether this is called first or last
Super::PostDuplicate(bDuplicateForPIE);
if (MeshComponent)
{
//registration would fail without a valid owner (and world)
if (MeshComponent->GetOwner())
{
MeshComponent->RegisterComponent();
}
MeshComponent->AttachTo(this);
}
}
What I started with in Blueprint is a simple Add Component node for my custom SceneComponent, then an Add Component node for a StaticMeshComponent with the basic Floor StaticMesh assigned and finally the StaticMeshComponent is attached to the custom SceneComponent. This happens in a loop where the SceneComponents are manually attached to the DefaultSceneRoot later. Here’s a screenshot for the Blueprint graph:
This works as expected, except in Play In Editor the meshes aren’t visible. As I said above this started after adding the PostDuplicate override and I can’t figure out why. I’m calling Super::PostDuplicate so I shouldn’t be overriding anything of the regular behaviour unless I’m overlooking something? PostDuplicate will be needed for the next step below otherwise I would just remove it. Unless there’s a more appropriate function I’m unaware of that can be used instead of PostDuplicate to ensure the MeshComponent is attached to the custom SceneComponent (in editor after Construction Script)?
Now what I wanted to do is to skip the (unnecessary) step of manually adding and attaching the StaticMeshComponent in Blueprint everytime and have this done in the custom C++ SceneComponent. Since the Mesh property in my custom SceneComponent is Instanced (see code above) it is possible to select the first Add Component node for this and in the Details panel directly assign a new StaticMeshComponent instance with the Floor StaticMesh assigned to it. Again the custom SceneComponents are manually attached to the DefaultSceneRoot. Here’s a screenshot of the new Blueprint:
While this may look ok at first having an instance of this Blueprint placed in a level, the components list/hierarchy changes after selecting something else placed in the same level and then reselecting the Blueprint instance again. The same happens after starting and stopping Play In Editor. See this before-after image:
BEFORE
AFTER
As before the meshes are visible in the level editor viewport as well as when playing as Standalone Game. However in Play In Editor the meshes are not visible again. Why would it do that?
When I enable Editor Preferences -> Content Editors / Blueprint Editor -> Workflow / Hid Construction Script Components In Details View one of the custom SceneComponents created from the loop disappears from the components list, all others stay there. The one SceneComponent that disappears from the list (it still exists in the world) is the one that no longer has a StaticMeshComponent child. This also spams the log with the following warning if the Blueprint instance is selected: “LogSCSEditor:Warning: Calling UpdateTree() from Tick() more frequently than expected due to invalid tree node state. This might be a performance issue”. You may also notice the StaticMeshComponents all have the same name.
Thank you very much for your time and suggestions.