Content System¶
Beamable Content System is a read-only (at runtime) arbitrary data store that allows you to define arbitrary JSON-serialized content objects for use at runtime. Several of Beamable's own managed features also use content in some way or another.
Overview¶
The system is manifest-based. This means:
- That a manifest is an list of published content objects in a realm indexed by their content ids.
- That publishing a manifest means first uploading all the individual content objects to Beamable and, after that, uploading a manifest that knows all where each content lives.
- That downloading a manifest does not necessarily imply downloading the individual content object jsons (more information below).
We don't provide 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:
UMyGameItemContentinherits fromUBeamItemContentitems.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 the main tool to create, edit and publish new content to your project.
The list of content objects displayed in the content window is very similar to a "Status" window in Git or some other version control systems. Beside show your local content it also present the differences between your local state and the state in your currently targeted Realm.
These differences are represented by the [+],[-] and [M] 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.
- [-]: Means the content DOES NOT exists locally but DOES exist in the realm.
If the content is not marked with any of these signs, it means it is in sync with the realm.
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.
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 friendly for version control systems.
Creating and Deleting Content¶
To create a new piece of content Locally:
- Select a content type from the Type dropdown.
- Type in a name for the content; it cannot contain whitespaces or ..
- Click the Createbutton.
Deleting content can be done simply by pressing Del on your keyboard with a item selected or clicking the Delete button in the Item Details.
Items created locally will have a [+] sign next to them informing that they are not in the realm yet and will be added in the next publish.
Items deleted locally that have counterparts on the realm will have a [-] sign next to them informing that they will be removed from the realm in the next publish.
Downloading and Publishing¶
To sync your local content with the realm, you have to Download and Publish.
Download will collect all content from the realm, adding new content, 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.
Publishing is a Destructive Operation
Publishing replace all the content in the Realm with your local content. This means that if you have multiple users (Designers for example) working on the same realm, you might override each other's changes if you don't Download before Publishing. We highly recommend each user working in content to work in your own realm.
Workflow for Working as a Team
Here is a sample worklow for a team of multiple developers:
- Each developer has it own Realm (Example: Realm1, Realm2, Realm3)
- The DevBranch (If using Git) of the project is the Source of Truth shared for all developers, and each developer is working on this branch
- Each Developer tests their changes on their own realm and when done commits those changes to the DevBranch so the rest of team can have access to this.
- After pulling the DevBranch, each developer should publish the new version of the content to their realms,so here can keep working in sync with the Dev branch.
UBeamContentObject and Custom Content 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:
- BlueprintReadOnlyif you are not writing utilities to create the objects for you.
- BlueprintReadWriteif 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, andint64 | byte,intandlong. | |
| floatanddouble. | ||
| bool | ||
| Unreal Types | ||
| FString,FText,FName | string | These get serialized as JSON strings. | 
| FGameplayTag | string | FGameplayTag::RequestGameplayTagfor deserialization. | 
| FGameplayTagContainer | string | FGameplayTagContainer::FromExportStringfor deserialization. | 
| UClass* | string | Gets converted to FSoftObjectPathwhen serializing. Deserializing will first create theFSoftObjectPathand then resolve it. | 
| TSoftObjectPtr | string | Gets converted to FSoftObjectPathwhen serializing. WhenNoneserializes as an emptystring. | 
| TArray<> | List<>orT[] | Any TArray<SomeType>will serialize normally as long asSomeTypeis also supported. | 
| TMap<FString, > | Dictionary<string,> | We only support maps with FStringas keys. The values can be any supported type. | 
| Beamable Types | ||
| FBeamOptional | Optional____ | Any property of a type implementing FBeamOptionaldoesn't get serialized ifIsSet==falsebut does get serialized otherwise.For example, FOptionalInt32serializes to nothing OR anint32. | 
| FBeamSemanticType | stringOR semantic type equivalent in C# | This always gets serialized as a JSON blob when inside UBeamContentObject. | 
| FBeamArrayandFBeamMap | ArrayOfandMapOf | 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 | UObjectin content should have their classesannotated with DefaultToInstanced,EditInlineNewsince you shouldn't referenceassets directly inside content objects. For that, use TSoftObjectPtr<>. | 
Take a look at UMockBeamContentObject to see the supported types.
Runtime LifeCycle¶
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 live content updates (if you publish content while the game client is running):
- While signed in to Beamable, UBeamContentSubsystemlistens 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.- These updates are cached locally inside the Saveddirectory in binary form such that a user does not need to re-download content in subsequent runs of your game unless the published manifest changes.
 
- These updates are cached locally inside the 
- If you disable this setting, you'll have to control fetching the actual content objects yourself.- There are APIs you can use to manually download individual content pieces: FetchIndividualContentBatchOperationandFetchIndividualContentOperation.
- Caching will still occur when manually downloading content.
 
- There are APIs you can use to manually download individual content pieces: 
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 binary 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.
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.
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.
Notes on Binary Serialization¶
Unreal's Binary serialization of UObject types works mostly out of the box without any need for you to write any code.
However, in cases where you have inlined (DefaultToInstanced, EditInlineNew) IBeamJsonSerializableUObject types inside your UBeamContentObject subtype's schema, you'll need to write two things to support caching content of these types:
- Override the virtual void Serialize(FArchive& Ar) overridefunction of the inlinedIBeamJsonSerializableUObjecttype.
- Override the virtual void SerializeUObjects(FArchive& Ar) overridefunction of theUBeamContentObjectsubtype that contains in its schema the inlinedIBeamJsonSerializableUObject.
In most cases, you should prefer using FBeamJsonSerializableUStruct subtypes UBeamContentObject as these will automatically support binary serialization.
It is only in cases where you need a recursive type that we recommend the use of inlined IBeamJsonSerializableUObject.
For examples of handling this edge case, you can look at the UBeamGameTypeContent and UBeamStatComparisonRule types shipped with the SDK.


