Tutorial 9 - Set Data in Editor Using Script Assets
Summary
Use script assets to store configurable data as an asset, similar to Unity's scriptable objects.
Requirements
- Reactor Requirements
- Completion of Tutorial 1.
Setup
Create a Room
- Right click in the hierarachy window and create a 'Reactor->Room' game object.
- In the 'Add Component' menu, add a ksSampleConnect script.
- The sample connect script has two connection methods: 'Direct' and 'Online'. Use 'Direct' with host 'localhost' and port 8000 for local testing.
Scripting
Create a Script Asset
Script assets are scripts that can store data saved as assets and be loaded on the server or client. Proxy scripts that inherit from ScriptableObject are generated for script assets so they can be saved in Unity as scriptable objects, similar to how proxy scripts that inherit from Monobehaviour are generated for server scripts.
Our script asset will store a dictionary mapping strings to int values, and will have a function for logging the contents of the dictionary.
- Select the 'Assets/ReactorScripts/Common' folder in the project window and right click. Select 'Create->Reactor->Script Asset' to create a script asset and name it 'CommonAsset'.
- Script assets can only be created in 'Assets/ReactorScripts/Common' or 'Assets/ReactorScripts/Editor/Server', or other common or server folders.
- Script assets in server folders are server-only and cannot be loaded on the client.
- Script assets cannot contain Unity references.
CommonAsset.cs
using System.Collections.Generic;
using KS.Reactor;
// This attribute keeps the proxy data in builds so the asset can be loaded from the proxy in client builds.
[ksSharedData]
public class CommonAsset : ksScriptAsset
{
[ksEditable]
public Dictionary<string, int> Stats;
// Log the stats from the dictionary.
public void LogStats()
{
string str = "{";
foreach (KeyValuePair<string, int> stat in Stats)
{
if (str.Length > 1)
{
str += ", ";
}
str += stat.Key + ": " + stat.Value;
}
str += "}";
// Log the asset id and asset path.
ksLog.Info("Id: " + AssetId + ", Path: " + AssetPath);
// AssetName is the last part of the AssetPath.
// Eg. if AssetPath is ScriptAssets/SomeAsset, then AssetName is SomeAsset.
ksLog.Info(AssetName + ": " + str);
}
}
Create Two Assets From Your Script Asset
- In a 'Resources' folder, right-click and navigate to 'Create->Reactor'. At the bottom you should see a new option 'CommonAsset'. Select it and name your asset 'CommonData1'. This creates a proxy asset from the proxy SciptableObject that was created for your asset script.
Script assets must be in 'Resources' or asset bundles to be loaded on the client using
Assets.Get
orAssets.CreateInstance
. References assigned to script assets in the editor usingksScriptAssetReference<T>
do not need to be in 'Resources' or asset bundles. Before script assets can be loaded from asset bundles, you must callksReactor.RegisterAssetBundle
with the asset bundle.
- In the inspector for your new asset you will set a 'Stats' list of key values. The keys are strings and values are ints. Assign some keys and values.
- In the same 'Resources' folder, create a second asset from your 'CommonAsset' script and name it 'CommonData2'.
- Assign it some different keys and values in the inspector.
Create a Server Room Script to Load Script Assets
Our server room script will demonstrate two different ways to load script assets. It will load one asset programmatically by name. It will load the other by assigning a ksEditable reference to it in the inspector. It will log the keys and values of both assets, and their asset ids and paths.
- Select the 'Room' object.
- In the 'Add Component' menu, select 'Reactor->New Server Room Script'.
- Name the script 'ServerRoom'.
Instead of calling
Assets.Get
you could callAssets.CreateInstance
. All calls toGet
return the same object called a prefab, whereas calls toCreateInstance
create a new copy of the asset prefab. If you modify the prefab returned byAssets.Get
, subsequent calls toAssets.CreateInstance
will create a copy with the modified values. Exising instances will not have their values changed. ksEditable asset references also reference the prefab returned byAssets.Get
. You can check if a script asset instance is the original prefab or a copy by checkingksScriptAsset.IsPrefab
. You can pass a prefab toAssets.Unload
to unload a prefab, which turns the prefab into an asset instance (ksSciptAsset.IsPrefab
becomes false) and future calls toAssets.Get
orAssets.CreateInstance
will reload a new prefab asset with the original asset values.If you are not in a Reactor server, client, or asset script, to access the asset loader use
ksScriptAsset.Assets
instead of justAssets
.
ServerRoom.cs
using KS.Reactor.Server;
using KS.Reactor;
public class ServerRoom : ksServerRoomScript
{
[ksEditable]
public CommonAsset AssetReference;
// Called when the script is attached.
public override void Initialize()
{
if (AssetReference != null)
{
AssetReference.LogStats();
}
// Load an asset by name or path. We are loading by name.
CommonAsset asset = Assets.Get<CommonAsset>("CommonData2");
if (asset != null)
{
asset.LogStats();
}
}
}
Create a Client Room Script to Load Script Assets
Like the server room script, our client room script will also demonstrate how to load script assets by name any by assigning a reference in the inspector. To get a serialized reference to
a script asset in Unity, you must create a ksScriptAssetReference<T>
field.
- Select the 'Room' object.
- In the 'Add Component' menu, select 'Reactor->New Client Room Script'.
- Name the script 'ClientRoom'.
ClientRoom.cs
using KS.Reactor.Client.Unity;
public class ClientRoom : ksRoomScript
{
public ksScriptAssetReference<CommonAsset> AssetReference;
// Called after properties are initialized.
public override void Initialize()
{
CommonAsset asset = AssetReference;// Implicit cast to the asset type.
if (asset != null)
{
asset.LogStats();
}
// Load an asset by name or path. We are loading by name.
asset = Assets.Get<CommonAsset>("CommonData2");
if (asset != null)
{
asset.LogStats();
}
}
}
Assign References to CommonData1
- Select the 'Room' object.
- Assign the 'Asset Reference' in the ClientRoom and ServerRoom scripts to 'CommonData1'.
Testing
- Build your scene config (CTRL + F2).
- Start a local server.
- Enter play mode.
In both the server and Unity logs you should see CommonData1's id and asset path followed by the keys and values you entered for it, then CommonData2's id and asset path followed by its keys and values.