Hey, I am currently trying to make an inventory system using ECS. I posted a previous thread about the inventory, but this question is unrelated to the inventory so I have made a new thread.
At the start of the game, I load a bunch of Item ScriptableObjects using Addressables.
What’s the best way to store these ScriptableObjects using ECS? Normally, I would create a class called something like “DataManager” and just store a list of all the ScriptableObjects, then access them when I want to make new items.
How do I accomplish this using ECS?
If data immutable - blobs. But all depends on your data types inside SO.
The data is Immutable, things that the SO contains are strings, ints, doubles, and Meshes.
Could you elaborate on blobs?
siggigg
November 12, 2019, 11:39am
4
I recommend you watch this talk:
2 Likes
Thanks, after watching the video I came up with this.
public class Items {
private NativeHashMap<NativeString64, Item> _item_data;
public async void Load() {
var item_data_list = await ScriptableObjectLoader.Load<ItemData>(AddressableConstants.ITEM);
_item_data = new NativeHashMap<NativeString64, Item>(item_data_list.Count, Allocator.Persistent);
foreach (var item in item_data_list) {
var item_data = ItemDataBlob.BuildItem(item);
_item_data[item_data.Value.Id] = new Item {
Data = item_data
};
}
}
public Item GetItem(NativeString64 id) { return _item_data[id]; }
public void Dispose() { _item_data.Dispose(); }
}
public class ItemSystem : ComponentSystem {
private Items _items;
protected override void OnCreateManager() {
_items = new Items();
_items.Load();
CreateEntity("test");
}
protected override void OnUpdate() { }
public void CreateEntity(string id) {
var entity = EntityManager.CreateEntity();
EntityManager.AddSharedComponentData(entity, _items.GetItem(new NativeString64(id)));
}
protected override void OnDestroy() { _items.Dispose(); }
}
public struct ItemDataBlob {
public NativeString64 Id;
public NativeString64 Name;
public NativeString512 Description;
public int MaxStackSize;
public static BlobAssetReference<ItemDataBlob> BuildItem(ItemData item_data) {
using (var builder = new BlobBuilder(Allocator.Temp)) {
ref var root = ref builder.ConstructRoot<ItemDataBlob>();
root.Id = new NativeString64(item_data.Id);
root.Name = new NativeString64(item_data.Name);
root.Description = new NativeString512(item_data.Description);
root.MaxStackSize = item_data.MaxStackSize;
return builder.CreateBlobAssetReference<ItemDataBlob>(Allocator.Persistent);
}
}
}
public struct Item : ISharedComponentData {
public BlobAssetReference<ItemDataBlob> Data;
}
Please let me know if this is the correct way to do this
1 Like
For a slightly cleaner use of blobs, I find this extension really useful:
https://github.com/periodyctom/Hydrogen.Entities
Thanks for the recommendation, but I would like to learn the underlying system before I start using a library for it.
siggigg
November 12, 2019, 1:59pm
8
At a quick glance this seems ok. Normally I would use a conversion system + a subscene, but since you are loading this via Addressables I’m not sure there is a dynamic path for that.
Also you could use the singleton entity pattern to more easily find your data again from an ECS system/job.
1 Like
siggigg:
At a quick glance this seems ok. Normally I would use a conversion system + a subscene, but since you are loading this via Addressables I’m not sure there is a dynamic path for that.
Also you could use the singleton entity pattern to more easily find your data again from an ECS system/job.
I didn’t even know about Get/Set Singleton, I will definitely use that over my current implementation.
1 Like