Home > OS >  How can I create an instance from a UObject class?
How can I create an instance from a UObject class?

Time:11-20

I have a DataTable with a list of items that can be dropped by enemies, along with their rarities and min/max quantities:

USTRUCT(BlueprintType)
struct FItemDropRow : public FTableRowBase
{
    GENERATED_BODY()

    UPROPERTY(EditAnywhere, BlueprintReadOnly)
    TSubclassOf<UBattleItemBase> DropItemClass;

    UPROPERTY(EditAnywhere, BlueprintReadOnly)
    EItemRarity RarityTier;

    UPROPERTY(EditAnywhere, BlueprintReadOnly)
    int MinDrop;

    UPROPERTY(EditAnywhere, BlueprintReadOnly)
    int MaxDrop;
};

And here's the function on the character where the drops are selected:

// Pick a random entry from a list of items filtered by rarity
int SelectedIndex = FMath::RandRange(0, UsableRowIndexArray.Num() - 1);

// Retrieve that entry from the DataTable
FItemDropRow* SelectedRow = ItemDropDataTable->FindRow<FItemDropRow>(
    UsableRowIndexArray[SelectedIndex],
    ContextString
);

// Pick a random amount to drop from the min/max defined on the DataTable row
int DropQuantity = FMath::RandRange(
    SelectedRow->MinDrop,
    SelectedRow->MaxDrop
);

// Initialize the array with the item instance and the quantity to add
TArray<UBattleItemBase*> ItemsToReturn;
ItemsToReturn.Init(SelectedRow->DropItemClass, DropQuantity);
return ItemsToReturn;

The issue is that the DataTable is only storing references to the classes:

C2664   'void TArray::Init(UBattleItemBase *const &,int)':
    cannot convert argument 1 from 'TSubclassOf' to 'UBattleItemBase *const &'

But I need it as an instance so I can add it to the player's inventory and modify it's quantity. I've tried the Instanced flag in the FItemDropRow struct, but that causes the DropItemClass to no longer appear as an editable property in the DataTable

CodePudding user response:

DropItemClass is only the class of the item, not an instance of it.

If you want to create an instance from that class you can use NewObject() or one of the more advanced versions (NewNamedObject() / ConstructObject(), CreateObject(), etc...)

e.g.:

TArray<UBattleItemBase*> ItemsToReturn;
for(int i = 0; i < DropQuantity; i  )
    ItemsToReturn.Add(NewObject<UBattleItemBase>(
        (UObject*)GetTransientPackage(),
        SelectedRow->DropItemClass
    );

this would create DropQuantity instances of the specified DropItemClass.

The first parameter to NewObject() will be the outer for the newly created object, so if you want it to be owned by any object you should pass that one instead.

  • Related