Content¶
Overview¶
Beamable's Content feature is a read-only (at runtime) arbitrary data store that you can use to define your game's data. Several of Beamable's own managed features also use content in some way or another.
UBeamContentObject
and Sub-types¶
In Unreal, you define content schemas as sub-classes of UBeamContentObject
or any
of its sub-types available in the SDK ( UBeamItemContent
, UBeamGameTypeContent
, etc...). Every
content type must define a unique string id for that particular type and a function that
returns it.
The following example of UBeamCurrencyContent
shows how that can be done:
UCLASS(BlueprintType)
class BEAMABLECORE_API UBeamCurrencyContent : public UBeamContentObject
{
GENERATED_BODY()
public:
// Define the ContentTypeId for this type.
UFUNCTION()
void GetContentType_UBeamCurrencyContent(FString& Result){ Result = TEXT("currency"); }
// Define the properties you wish
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FBeamClientPermission clientPermission;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int64 startingAmount;
UPROPERTY(EditAnywhere, BlueprintReadWrite, DisplayName="Federation")
FOptionalBeamFederation external;
};
Please remember to annotate your UPROPERTY
with EditAnywhere
and either:
BlueprintReadOnly
if you are not writing utilities to create the objects for you.BlueprintReadWrite
if you are writing utilities to create the objects for you.
Microservices
In a lot of cases, you will want to access these content objects in Microservices. For all of Beamable's own content-types ( UBeamCurrencyContent
, etc...) you will find equivalents in the Microservice SDK. For your own custom types, you'll need to declare them in C#. To do so, use the serialization table below as reference to know how to map types from C++ to C#.
Supported Content Serialization¶
Serializable Type | In C# Microservices | Notes |
---|---|---|
Primitive Types | ||
uint8 , int32 , and int64 |
byte , int and long . |
|
float and double . |
||
bool |
||
Unreal Types | ||
FString , FText , FName |
string |
These get serialized as JSON strings. |
FGameplayTag |
string |
FGameplayTag::RequestGameplayTag for deserialization. |
FGameplayTagContainer |
string |
FGameplayTagContainer::FromExportString for deserialization. |
UClass* |
string |
Gets converted to FSoftObjectPath when serializing. Deserializing will first create the FSoftObjectPath and then resolve it. |
TSoftObjectPtr |
string |
Gets converted to FSoftObjectPath when serializing. When None serializes as an empty string . |
TArray<> |
List<> or T[] |
Any TArray<SomeType> will serialize normally as long as SomeType is also supported. |
TMap<FString, > |
Dictionary<string,> |
We only support maps with FString as keys. The values can be any supported type. |
Beamable Types | ||
FBeamOptional |
Optional____ |
Any property of a type implementing FBeamOptional doesn't get serialized if IsSet==false but does get serialized otherwise.For example, FOptionalInt32 serializes to nothing OR an int32 . |
FBeamSemanticType |
string OR semantic type equivalent in C# |
This always gets serialized as a JSON blob when inside UBeamContentObject . |
FBeamArray and FBeamMap |
ArrayOf and MapOf |
Any implementation of these wrappers are serialized correctly as JSON arrays and JSON objects respectively. These are only used when you want to nest TArray<TArray<>> / TMap<,TMap<>> and still have Blueprint Support. |
FBeamJsonSerializableUStruct |
Any C# class that maps to your struct | Any type inheriting from this type gets serialized as a JSON object. |
IBeamJsonSerializableUObject |
Any C# class that maps to your class | UObject in content should have their classesannotated with DefaultToInstanced ,EditInlineNew since you shouldn't referenceassets directly inside content objects. For that, use TSoftObjectPtr<> . |
Take a look at UMockBeamContentObject
to see the supported types.
Beamable's Content System¶
Beamable Content System allows you to define arbitrary JSON-serialized data for use at runtime. The system is manifest-based and has no server-side schema enforcing (which means you are solely responsible for maintaining backward compatibility for your custom content objects).
Each individual content object in each manifest is identified by an ID with the format below:
ContentTypeId.ContentName
ContentType
expands to the hierarchy of UBeamContentObject
types, starting from the root type. For example:
UMyGameItemContent
inherits fromUBeamItemContent
items.mygameitem.MyGameItemName
The last part of the id is the only one you should edit through the Content Window.
Content Window¶
The content window is how you can create and edit content inside the editor. Here's what it looks like:
Where can I find the content files?
While you edit the content objects as UObject
and a details panel, these are not stored as UDataAsset
or anything inside Unreal itself. These are stored as individual JSON objects inside ProjectRoot/.beamable/content/global
folder. This makes it more VCS-friendly.
Creating and Deleting Content¶
To create a new piece of content, you should:
- Select a content type from the Content Type dropdown.
- Type in a name for the content; it cannot contain whitespaces or
.
. - Click the
Create
button.
After that you should see a new content of that type which you can edit. Deleting content can be done simply by selecting one and pressing Del
on your keyboard.
Visualizing Content¶
The list of content objects displayed in the content window is very similar to a "Status" window in Git or some other VCS system. It isn't just showing you your local state; it is showing you the differences between your local state and the state in your currently targeted Realm
.
These differences are represented by the [+]
, [M]
, [NC]
and [-]
signs.
[+]
: Means the content exists locally but NOT in the realm.[M]
: Means the content exists BOTH locally and in the realm AND that it is modified relative to the one in the realm.[NC]
: Means the content exists BOTH locally and in the realm AND that it has no changes relative to the one in the realm.[-]
: Means the content DOES NOT exists locally but DOES exist in the realm.
The window will display these sorted by these status types in the following order: [+]
first, then [M]
and [NC]
, followed by [-]
last.
Changing Realm
Changing Realms does NOT auto-sync your local content with that realm's content. This means that you will see changes to these ([+]
, [M]
, [NC]
, [-]
) signs to reflect their new status against the new target realm.
Download & Publish¶
Download is pretty straight-forward, it'll fetch the content in the realm, replacing any [M]
and restoring any [-]
values to match the ones in the realm. It is similar to selecting all non-new files in a version control and "discarding changes".
Publish is similar to a commit. This will make the content in the realm the same as your local content. After publish, all pieces of content will match the realm and [-]
content should disappear. Unless you publish your content, Beamable system's won't be able to see changes made to them; so don't forget to publish before testing your changes.
Sharing Realms between Designers
At the moment, we recommend each designer working in content have their own realm. This is because publishing is an atomic process. It'll replace the entire content in the realm with whatever is being published.
This means designers might accidentally override their changes if they don't Download before publishing and/or are editing the same objects.
At Runtime¶
The SDK fetches the content manifest before the OnBeamableStarted
callback is
triggered. By default, it downloads the content manifest and each individual piece of content. You can enable and disable this behavior it can be configured to do so inside Project Settings -> Beamable Runtime
.
The SDK also supports automated content updates.
While signed into Beamable, UBeamContentSubsystem
listens for notifications that the realm's content manifest has been updated. If that happens, we will re-download the manifest. If the SDK is configured to download individual content pieces automatically, we do so for all changed content.
If you disable this setting and want to control fetching the actual content objects yourself, there are APIs you can use to manually download individual content pieces: FetchIndividualContentBatchOperation
and FetchIndividualContentOperation
.
Baking Content¶
In a couple of cases, you might want to bake content to distribute it with your build:
- If you plan to release a new build every time you want to update your game.
- If you want to trade-off some binary size for spending less time waiting for the individual content download at initialization time.
To enable those cases, we provide an editor utility that will bake your local content into a UBeamContentCache
; this is a special asset type that has the UBeamContentObject
instances serialized using UE's serialization as opposed to JSON. Keep in mind that this utility uses your local content; so make sure your content matches the realm's content before running it.
The utility is called EBP_BakeContent
and can be found in Beamable Core's plugin folder under /Editor/Utility/EBP_BakeContent.EBP_BakeContent
. Running this utility goes through your local content and bakes them into a BCC_
assets ( UBeamContentCache
) stored in /Game/Beamable/Content/Manifests/Cooked/
directory. This directory is configured, by default, to be included in packaged games.
I can't find the Beamable Core Content in the Content Browser
UE's Content Browser does not show Plugin content folders by default. If you want to see these, you need to turn it on at Content Browser -> Settings -> Show Plugin Content
.
At runtime, any UBeamContentCache
is loaded automatically by the UBeamContentSubsystem
if it exists and is configured correctly; so you don't have to do anything to have it work.