Hello,
Just starting out learning ECS and trying to wrap my head around not being able to use arrays in IComponentData structs. I wrote this to try to mimic array functionality using a bunch of ints and functions that link the variable to a fake index since I only have a handful of elements. Is this a stupid way of doing this? What’s the proper method?
public struct VoxelElements : IComponentData {
public int water;
public int smoke;
public int fog;
public int arcane;
public int Read(int index) {
switch (index) {
case 0: return water;
case 1: return smoke;
case 2: return fog;
case 3: return arcane;
default: return -1;
}
}
public void Write(int index, int value) {
switch (index) {
case 0: water = value; break;
case 1: smoke = value; break;
case 2: fog = value; break;
case 3: arcane = value; break;
}
}
}
}
Thanks for the article. I am now trying to convert to FixedList. Is there a difference between what can be used in IComponentData and what can be used in OnUpdate? I’m running into this: The type ‘AtmosphereSystem.AtmoNeed’ must be non-nullable value type, along with all fields at any level of nesting, in order to use it as a parameter ‘T’ in the generic type or method ‘NativeList’
public partial class AtmosphereSystem : SystemBase
{
protected override void OnUpdate() {
NativeList<AtmoNeed> needs = new NativeList<AtmoNeed>(Allocator.TempJob);
}
}
public struct AtmoNeed {
public FixedList64Bytes<int> elemDiff;
}
Still trying to understand what can be used where, thanks for your help.
Can’t have native collections inside native collections as a general idea.
Can’t have native collections inside structs as part of components.
Nobody stops you to have pointers or indexes for collections that are stored elsewhere though.
Stored unsafe collections are pointers basically, but its a whole diffent can of worms.
This way, you’d still have separate int values, but will be able to do
int value = voxel[i];
// or
voxel[i] = *somevalue*;
instead of respective Read / Write methods
Alternatively, if you only need one bit to determine wheter element is set, 4 bytes is a bit a of a waste.
Perhaps bitmask would be a better option? Then you can use single int / enum value to determine if element is set.
Thanks for the clarification. So it looks like I cant use FixedList either if I intend to store multiple in another list.
The “elements” are going to value 1-100, they represent how much of an “element” is in a voxel of space at any time in order to do a spreading simulation. So 86 units of smoke would spread some to its neighbors. So int is correct for this usage?
Can you elaborate further on how to use “this” with fixed array? I read the doc you linked but failed to see how it applied to the example. Also, would this still be illegal if its struct were to be stored in an array?
Sorry for the handhold request!
I see. In that case byte is better. Less memory wasted.
As for the indexer:
→ SmallBuffer example, pretty much covers it. Its similar how FixedStringXBytes work.
Idea is to make sequentially layed out memory block that acts as an array. Then provide access to parts of it by the pointer offset based on index. If your total amount of elements does not change by design often, then it might be a valid solution.