Property of custom [C++] class "doesn't work" properly in BP

I am not sure if it is a bug, but it seems like…

Here is the code sample for Pickup.h:

#pragma once

#include "Public/Interact/InteractObj.h"
#include "Pickup.generated.h"

// For preventing circular dependency...
class AItem;

UCLASS()
class RC2_API APickup : public AInteractObj
{
	GENERATED_BODY()
	
protected:
	APickup();

public:
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Item")
	AItem* Item;
};

When I try to assign this field to some existed-in-level objects, I see only “None” in this field (look a picture below). It seems nothing was happend, but the trick is that assigning works, actually.

98439-bug_2.png

What I’ve tried to do:

  • Rebuild the project (with and without deleting temporary files)
  • Use header instead of forward declaration
  • Change UPROPERTY parameters

This code works completely fine, however:

UPROPERTY(EditDefaultsOnly, Category = "Item")
TSubclassOf< class AItem > Item;

With the way you’ve set it up, any object instances have to derive from your AItem class.

They are. The hierarchy is: AItem → AItem_BP.
And I see the list of the object on the level. Well, as it said, the functionality works as it meant to.

Does it work in the editor if you change the TSubClassof AItem to TSubClassof AActor?

note: this isn’t an answer/solution, just an investigatory question to narrow down the problem.

Well, if it is working with AItem it definitely works with AActor.

It sounds like you have Blueprintable but forgot to add the BlueprintType specifier in your class declaration? I.e.

UCLASS(Blueprintable, BlueprintType)
class RC2_API AItem : public AActor

https://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/Reference/Classes/Specifiers/BlueprintType/

UPDATE:

It seems the issue is that you are trying to refer to an Actor instance from a Blueprint Class Default Object. This is not possible by design. A Blueprint can be instantiated in any world but an Actor exists in a specific world, so it wouldn’t actually make sense anyway. If you want to set up the default object at the class level, you can add custom logic in the Construction Script to set the field at the instance level.

It sounds (and it really is), but adding BlueprintType didn’t help.

Hey WHSolv-

Can you elaborate on what the issue is that you’re having? When I add the UPROPERTY and TSubclassOf from your code snippet (I changed AItem to AActor since my project does not have an Item class) I see all available actor types in the dropdown menu inside my blueprint. As mentioned, using AItem will mean that only classes/blueprints that derive from the Item class will appear in the list.

And to be clear, you’re editing the value within the blueprint that subclasses APickup? (not on an instance of APickup, since you have EditDefaultsOnly, not EditAnywhere on the propetry)

Yes, I edit the values in Pickup_BP, child of Pickup.

The original issue topic here

I see them all as well, the “bug” is when I assign it (choose one from the list) I see no visual changes in field (picture), “None” still exists. But… the change actually has its place.

What do you mean? When you select a new class is the new class name displayed? Is the class thumbnail image not changing? Before/after pictures would help

We are not talking about classes, but instances. And they are listed correctly.
Before AND after picture is the same.

TSubclassOf can be assigned the class AItem, not an instance of AItem.
E.g.

UPROPERTY(...)
TSubclassOf<AItem> Item;
...
Item = AItem::StaticClass();
Item = ASwordItem::StaticClass();

If the intent is to have Item be an instance of AItem or any subclass, the proper declaration is:
E.g.

UPROPERTY(...)
AItem *Item;
...
Item = NewObject();
Item = ASwordItem();

So?.. I know it.
The code above was a quite incorrect (just messed up with changing Subclass\pointer_to), I updated it.

It’s quite confusing when the question keeps changing…

The question is the same.

Hey WHSolv-

I believe the issue you’re having is related to the difference between using a pointer such as AItem* MyItem versus using TSubClassOf < class AItem> MyItem. In the first case with the pointer, when you try to set the property in the editor (blueprint default or level instance), the dropdown menu will only show instances of the specified class (AItem or AItem subclasses/blueprints) that are already placed in the level. Using TSubClassOf` allows you to set the variable to the class/blueprint instance in the content browser that matches the correct type.

If this information doesn’t help, please restate what your issue is. What exactly do you mean that the property “doesn’t work”? What code are you using and what is the outcome that code provides? What is your expected outcome? The more detailed you can be the easier it will be to understand what is happening.

I know the difference between those two. The problem is that when I use pointer to some instance (e.g. AItem*) I can actually change the value in the field, but I don’t see the visual difference in options (see picture, there is always “None” in this field).