You can implement the ISceneMetadata
interface in any Component that has data you'd like saved to Metadata. Metadata is data that can be accessed without needing to load a Scene or clone a Prefab
(accessed via either the SceneFile
or PrefabFile
)
public class MySceneInfo : Component, ISceneMetadata
{
[Property] public string Title { get; set; }
[Property] public string Group { get; set; }
[Property, TextArea] public string Description { get; set; }
[Property] public int Difficulty { get; set; } = 1;
public Dictionary<string, string> GetMetadata()
{
// Any data that can be serialized to a string can be stored here
return new Dictionary<string, string>
{
{ "Title", Title },
{ "Group", Group },
{ "Description", Description },
{ "Difficulty", Difficulty.ToString() }
};
}
}
This Component has Title
, Group
, and Description
properties which are included in the returned Dictionary.
If you now save the Scene or Prefab containing this Component, it will serialize this information to the file.
Now we can call GetMetadata(key, fallback)
on any SceneFile, so let's create a simple UI that lists out all our Scenes by Title and Group, showing the Description on hover:
@foreach( var group in ResourceLibrary.GetAll<SceneFile>().GroupBy( x => x.GetMetadata( "Group", "None" ) ) )
{
<div class="group">
<h1>@group.Key</h1>
<div class="scenes">
@foreach( var scene in group )
{
<div Tooltip=@( x.GetMetadata("Description") )>@( x.GetMetadata( "Title" ) )</div>
}
</div>
</div>
}
This is done identically to SceneFiles. If we had an "EnemyInfo" ISceneMetadata
Component with Difficulty
and SpawnWeight
values, we could also spawn any PrefabFile in the current difficulty based on its weight (higher weight has a higher chance of spawning)
void SpawnEnemy( Vector3 position, int difficulty )
{
var allEnemies = ResourceLibrary.GetAll<PrefabFile>().Where( x => int.Parse( x.GetMetadata( "Difficulty", "0" ) ) <= difficulty );
float totalChance = allEnemies.Sum( x => float.Parse( x.GetMetadata( "SpawnWeight", "0" ) ) );
float randomChance = Random.Shared.Float( 0, totalChance );
float runningChance = 0f;
foreach( var enemy in allEnemies )
{
runningChance += float.Parse( enemy.GetMetadata( "SpawnWeight", "0" ) );
if( randomChance <= runningChance )
{
var prefab = SceneUtility.GetPrefabScene( enemy );
prefab.Clone( position );
break;
}
}
}