With the below code I can’t seem to be able to create/assign instances of the UObjectChild class to the Objects TArray in the Editor:
UCLASS(BlueprintType, Blueprintable, EditInlineNew, DefaultToInstanced)
class PROJECT_API UObjectChild : public UObject
[...]
UCLASS( EditInlineNew, meta=(BlueprintSpawnableComponent))
class PROJECT_API UContainerComponent : public UActorComponent
[...]
UPROPERTY(EditAnywhere, Instanced)
TArray<UObjectChild*> Objects;
UCLASS()
class PROJECT_API AMyContainerTestActor : public AStaticMeshActor
[...]
UPROPERTY(EditAnywhere)
class UContainerComponent* Component;
AMyContainerTestActor::AMyContainerTestActor(const FObjectInitializer& ObjectInitializer)
{
Component = ObjectInitializer.CreateDefaultSubobject<UContainerComponent>(this, TEXT("Container"));
}
It shows the available classes as None or UObjectChild, but when choosing the latter nothing happens.
I don’t see what I’m doing wrong here, though it’s possible this is not the intended behavior, but I’d like to know in that case.
Anybody have an idea or a possible solution?
Edit:
It looks like that when I instead use a pointer to UObject instead of its subclass, I get the same behavior with the added weirdness with for example a SphereComponent, it won’t get assigned to the index of the TArray, but it will get added as a child of the parent component (a StaticMeshComponent in this case), but ONLY after going into PIE.
Hi @ZeroParadigm, first of all: great name!
I have seen my approach on the forums as the suggested route and according to others it should work, yet it doesn’t.
I have tried removing the Instanced keyword, but that only removed the possibility of seeing, let alone select, any classes from the dropdown list.
Changing it to a TSubclassOf<> requires the removal of the Instanced keyword as you describe, but to the best of my understanding it has now become a TArray of class-references. I’m not entirely sure if this is what I wanted, I can no longer assign instances, only class-references of that class and it’s subclasses.
Since your example of an Inventory is close to my purpose for the code, how do you deal with setting up instances of objects that should sit inside it, from the Editor Properties window?
Let me try and wrap my head around it and see if I understand your workflow:
You assign Class Default Objects of your specified subclass in the TArray and then can then change the default properties in the window? Is that about right?
Never ever create your components with an FName that has a space inside it!!! (using CreateDefaultSubobject<>())
Lesson learned… Hours wasted over one single space, a single invisible character… Breaking everything.
I’m pretty sure this should be unintended behavior…
Surprised, although not entirely, that this is the issue. Nice job tracking it down @ZeroComfort
Yeah, so in my case, I assign the default objects which will be spawned in the container. This is just the class types which will be created when the inventory is spawned. So the main implementation difference between what you’re trying to do, and what I’m doing, is that I have two separate TArrays. One which defines the default classes for the inventory, and the other which actually tracks the instances of the objects.
For me, I use the default inventory list to spawn the object with it’s default inventory, and a second list to track the actual instances
@ZeroParadigm Thanks for sharing your approach, it’s an interesting one! If you don’t mind telling me: do you assign Blueprint assets or C++ (sub)classes (with properties applied)?
I use blueprint classes which define all of the default properties and meshes for the objects. Typically, I only use C++ classes for abstract classes (and non-content based systems) to ensure that content references are not defined in code. Otherwise they tend to break if they are moved between folders.
Have you tried removing the ‘instanced’ specifier? After looking at the UPROPERTY page it looks like that specifier may be a little misleading. If that doesn’t work, try using TSubclassOf I have a similar container which works in this fashion, but it is declared as such. I’m using an actor, but it should work for your purposes also
UPROPERTY(EditAnywhere, Category = "Container")
TArray<TSubclassOf<AActor>> Inventory;