A Dataless Customizable Object is a normal Customizable Object whose input nodes are in-game changeable Parameter Nodes.
You can convert any Customizable Object to dataless by replacing the following nodes:
| Constant Nodes | Parameter Nodes |
|---|---|
Texture Node | Texture Parameter Node |
Skeletal Mesh Node | Skeletal Mesh Parameter Node |
Material Node | Material Parameter Node |
Table Node | T / SK / M Node |
It is not a requirement to replace all nodes. You can mix and match Constant and Parameter nodes. In short, you will only take advantage of dataless on those inputs which are Parameter nodes.
Improvements Over Customizable Objects
Faster compilation time: Inputs from Parameter nodes are not compiled, instead they are converted at runtime.
Encryption: Now encryption works out of the box. Since inputs are no longer compiled (they are normal UObjects), they can now be encrypted as usual.
Regular UE workflow: With the old Constant nodes, you had to keep in mind that meshes and parameters would be embedded in the Customizable Object in a special cook process, and the original assets would be editor-only. With the new dataless system, it works just like any other UE system-like materials.
Possibly smaller packages: Previously if an input was referenced outside of Mutable, it was included in the package twice: once as a compiled Mutable Resource and once as a UObject, which is why it wasn’t recommended. Since Parameter inputs are no longer compiled, this is no longer the case.
Limitations
Less performant: Runtime conversions and some optimizations, like generating constants, cannot be applied at compilation time.
No available options: Input parameters do not have a list of available options. This means that gameplay programmers are now responsible for restricting which inputs can be passed in the parameters.
New Parameters
As regular parameters, the new Texture, Skeletal Mesh and Material Parameters can be set by creating a Customizable Object Instance and calling the following functions (Blueprint or C++):
UFUNCTION(BlueprintCallable, Category = CustomizableObjectInstance)
void SetTextureParameterSelectedOption(
const FString& TextureParamName,
UTexture* TextureValue);
UFUNCTION(BlueprintCallable, Category = CustomizableObjectInstance)
void SetSkeletalMeshParameterSelectedOption(
const FString& SkeletalMeshParamName,
USkeletalMesh* SkeletalMeshValue);
UFUNCTION(BlueprintCallable, Category = CustomizableObjectInstance)
void SetMaterialParameterSelectedOption(
const FString& MaterialParamName,
UMaterialInterface* MaterialValue);
In addition, in each Parameter node you can specify a Default Value. This Default Value is optional and if it is not specified it will be nullptr. You can get these Default Values in the Customizable Object:
UFUNCTION(BlueprintCallable, Category = CustomizableObject)
UTexture* GetTextureParameterDefaultValue(
const FString& InParameterName) const;
UFUNCTION(BlueprintCallable, Category = CustomizableObject)
USkeletalMesh* GetSkeletalMeshParameterDefaultValue(
const FString& ParameterName) const;
UFUNCTION(BlueprintCallable, Category = CustomizableObject)
UMaterialInterface* GetMaterialParameterDefaultValue(
const FString& ParameterName) const;
Keep in mind that if a Default Value is set, the referenced objects will be cooked. Also the lifecycle of these objects is the same as the Customizable Object since they are strong references.
Once all parameters have been set. To see the results, you need to call:
UFUNCTION(BlueprintCallable, Category = CustomizableObjectInstance)
void UpdateSkeletalMeshAsync(
bool bIgnoreCloseDist = false,
bool bForceHighPriority = false);
Example
Regular Nodes: Skeletal Mesh references are shown in the Reference Viewer due to having an Editor-Only reference.
In a packaged game, they are not included as UObjects but as Mutable Resources:
Dataless Nodes: Notice that only the Skeletal Mesh nodes have been converted to dataless.
The Material is still a constant (not a parameter):