What’s the proper way to use class variables and actually create objects from the variable?
My specific problem appears to be that I’m trying to create an object in a constructor; NewObject() gives the error “NewObject can’t be used to create default subobjects (inside of UObject derived class constructor) as it produces inconsistent object names. Use ObjectInitializer.CreateDefaultSuobject<> instead.”. However, CreateDefaultSuobject is not an option because the class is passed in through the template, meaning it must be a specific type, and I can’t use a class for dynamic object creation.
What I’m trying to accomplish with this is streamlining the mesh components. Right now I have mesh component declared in the abstract class Weapon, however since it’s abstract, Weapon itself will not have a mesh. What I want to do is basically, in Weapon, “Create a mesh specified by a variable, attach to root, set properties on that mesh”. It looks like if I can’t do this, I would need to copy/paste this code into every single subclass that I make.
I’m still new to this so it’s possible that my approach is completely off. Any assistance would be appreciated. Thanks.
Yeah, I had this same problem and couldn’t find a way to do this in the constructor.
I ended up creating a virtual function (which can be overridden by subclasses) which was called from OnConstruction().
OnConstruction() doesn’t technically form part of the construction routine (it’s execution doesn’t originate from the constructor - it is called later by some other Unreal-specific code, similar to BeginPlay()).
I do have a question for you:
Is the component you’re trying to create always e.g. a SkeletalMeshComponent?
If so, you can always still create the component in the constructor, but use the OnConstruction() approach to set the actual mesh (i.e. MeshComponent->SetSkeletalMesh(yourmesh). You can use ObjectFinder to find the mesh from a text reference.
I also wrote a fairly detailed forum post about my findings here if you’re interested in some more details.
The component is always the same class, i.e. UStaticMeshComponent. I considered that, but I don’t think it will work for the same reason I can’t just set it while NULL.
It’d be something like:
Mesh = GetSomePlaceholderMesh();
Mesh->bCastDynamicShadow = false;
Mesh->AttachParent = RootComponent;
//...
Mesh = GetTheRealMesh();
I’d like to be able to assign variables on the mesh without setting it, but since it’s an actual object, GetTheRealMesh() would just “overwrite” any changes I had made.
If you do it in the constructor, yes. The reason is that you have no control over when parent constructors are called, it always goes:
- Execute Base Class Constructor from start to finish
- Execute First Child Class Constructor from start to finish
- Execute Second Child Class Constructor from start to finish
- Etc
When you do it in a virtual function (which is not part of the formal construction routine, like OnConstruction() or BeginPlay()), you do have control over when Superclass functions are called. E.g.
In YourParentClass.cpp:
void ParentClass::OnConstruction()
{
Super::OnConstruction();
CustomInit();
}
void ParentClass::CustomInit()
{
// Get the mesh to use
UStaticMeshComponent* meshToUse = GetMesh();
// Set mesh
Mesh->SetStaticMesh(meshToUse);
// Set attributes
SetMeshAttributes();
}
UStaticMeshComponent* ParentClass::GetMesh()
{
return someDummyMesh;
}
void ParentClass::SetMeshAttributes()
{
Mesh->bCastDynamicShadow = false;
...
}
Now, in YourChildClass.cpp:
void ChildClass::SetMeshAttributes()
{
// Not calling Super here!
Mesh->bCastDynamicShadow = true;
...
}
UStaticMeshComponent* ChildClass::GetMesh()
{
// You can also use a class reference here, as the child class value of such a property would be in effect at this point in time.
return theRealMesh;
}
Or am I missing this entirely?
I think this would work, but wouldn’t reflect the changes fully in the editor, which is what I was hoping to accomplish by putting it in the constructor in the first place.
I’m just going to assume that I’m doing this wrong, and try to find a completely different approach for this.
Thanks.