Data Oriented Behaviour - Struct inheritance?

Hey there, I want to use a Data Oriented approach for my game.
I have a DataTable that should contain the enemies my game has to offer.
And I am struggling to come up with a structure to implement the Behaviour in a Data-Oriented way.
The Game is turn based, soI think using BlackBoards and Behaviour Trees is way too much.

What I want:

The Struct “Monster” should contain another DataContainer called “Behaviour”
A Behaviour should contain one or more “Conditions”.
Conditions could be:
“Monster HP <= X amount”
“Party contains X member”
“The Current Battle Turn No. is X”
etc.

The Behaviour should then contain the actual Behaviour like
“Attack regularly”
“Attack Party Member with Health lower than X”
“Use Skill X”

How would I set this up so I can have it completely contained within the DataTable?

A class-like approach would be great (Condition could be a class with an abstract function that returns a bool), but using UObject would mean I have to create an UObject in the Content browser for every condition and I could not parametrize it uniquely and put it into the DataTable

Wht not use Data Assets?
They exist to solve exactly what you’re trying to achieve.

I wouldnt be able to define the Behaviour in the DataTable. It would mean I have to create the Data outside of it.
And I also fail to see how I can create different behaviours with UDataAsset. it would mean the same thing I suggested. Different classes for every condition and the Behaviour would be a different class aswell. The DataAsset would be a collection of Conditions and the actual behaviour (Use Skill X, Attack X) would be a different class, too.

I meant data asset instead of data table.
I’m not sure why so many like to use tables lol

Anyway, I would make the skills to be an Enum to define in a behavior data asset.

Then the conditions I would make them also an Enum, but a bitmask enum. Bitmasked enums allows for multiple conditions to be set at once, defining multiple conditions for the same behavior.

Comparing flags of a bitmask enum is clunky at first, but soon it shows its usefulness, specially for RPG stuff.


Or make it even better:
Use Gameplay Tags. ^^

Everything is in one place instead of scattered in hundreds of separate files and simply text representation maybe.

DataAssets seem to be the correct way to go though. Is there a way to have the DataAsset “inline” instead of separate, basically an instance of it directly in it?

Try adding “EditInlineNew” to your data class:

Hm, It doesnt seem to work.
I still have to select an asset when having a UPROPERTY() of this type



UCLASS(EditInlineNew)
class UMonsterBehaviour : public UDataAsset {
 GENERATED_BODY()

public:
 UPROPERTY(EditInstanceOnly)
  bool bCondition;
 UPROPERTY(EditInstanceOnly)
  int Parameter;

};


Edit:

I now have this in my Struct:


 UPROPERTY(Instanced,EditAnywhere)
 UMonsterBehaviour* Behaviour;

and it results in that:

See my updated post above.
I only receive see “None” …

If I remember correctly, the UProperty declaration also have to be marked as “Instanced”.

And class something like:
UCLASS(DefaultToInstanced, EditInlineNew)

I already did that and that doesnt help :frowning:

You are doing this UProperty on the data table class?!
If so I don’t think it would work.

I already tried it in a Blueprint. It shows “None”, too.

At this point I would fall back to UObject instead of UDataAsset.
If still doesn’t work I have no idea what might be happening in your Editor.

Hopefully you’re not using hot reloading btw.

I’d just say Instanced and EditInline simply doesnt work?
Using UObject doesnt help either

I’m on my phone so I cannot look up codes here, but they surely do work.

There might be something I’m missing, but the times I had to use EditInlineNew, editing instances in editor worked correctly.


I noticed there’s no XXXX_API macro to your
UMonsterBehaviour declaration, that could be a root to the problem.

Also always give UProperty a category when exposing to the Editor.

Anyway if you feel like not going forward with the data asset scheme…

You could make your FMonsterBehavior house a FGameplayTagContainer to use as a “Conditions” system and a FGameplayTag to function as the actual skill the behavior activates:

https://api.unrealengine.com/INT/API…ner/index.html

They most definitely do work - I use that pattern rather often. Like Bruno said, I think the root issue is you aren’t exporting those classes so the Editor can’t find them.

Here’s a working example:



UCLASS(EditInlineNew)
class MYGAME_API UMovementState : public UObject
{
    GENERATED_BODY()
public:
    UMovementState();
    virtual ~UMovementState();

   // ...
};

class MYGAME_API UGameMovementComponent : public UMovementComponent
{
    GENERATED_BODY()
public:
    UGameMovementComponent();
    virtual ~UGameMovementComponent();

protected:
    UPROPERTY(EditAnywhere, Instanced, Category = "Movement", meta = ( DisplayName = "States" ))
    TArray<UMovementState*> m_MovementStates;
};



could it be because i am not using a Component?



#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "MonsterBehaviour.generated.h"

UCLASS(DefaultToInstanced,EditInlineNew)
class TURNBASEDRPG_API UMonsterBehaviour : public UDataAsset {
 GENERATED_BODY()

public:
 UPROPERTY(EditAnywhere)
  bool bCondition;
 UPROPERTY(EditAnywhere)
  int Parameter;

};




USTRUCT()
struct TURNBASEDRPG_API FMonster : public FTableRowBase{
 GENERATED_BODY()

 UPROPERTY(EditInstanceOnly)
 FText Name;
 UPROPERTY(EditInstanceOnly)
 FText Description;
 UPROPERTY(meta=(EditCondition = "!bIsImmortal"), EditInstanceOnly)
 uint32 MaximumHP;
 UPROPERTY(EditInstanceOnly)
 bool bIsImmortal;
 UPROPERTY(EditInstanceOnly)
 uint16 MaximumMP;
 UPROPERTY(meta = (EditCondition = "!bIsImmortal"), EditInstanceOnly)
 uint32 Experience;
 UPROPERTY(meta = (EditCondition = "!bIsImmortal"), EditInstanceOnly)
 FMonsterReward Reward;
 UPROPERTY(EditInstanceOnly)
 FAttribute Attributes;
 UPROPERTY(EditDefaultsOnly)
 TSoftObjectPtr<USkeletalMesh> SkeletalMesh;
 UPROPERTY(EditDefaultsOnly)
 TArray<TSoftObjectPtr<UMaterialInterface>> MaterialOverrides;
 UPROPERTY(Instanced,EditAnywhere)
 UMonsterBehaviour* Behaviour;
};


this is my full code

Yea I don’t think you can have “instanced” fields work within the Editor with non-UObjects. FTableRowBase is just a simple struct.

Okay. I switched from struct to DataAsset and it works now.
Thank you!