How to access buffer within ICompData?

Hello everyone. I’ve spent the last hour or so trying to find an answer to this to no avail.

This CompData has 3 buffers and 1 normal CompData. Accessing “Parents” is no issue but getting the dynamic buffer for the rest is something I’m not sure how to do.

Doing this gives me an error on the first line.

family.parents.Mother is 100% set and not null because I can see it in the debugger. Therefore I assume the error is because bufferFromEntity can’t tell that Children is underneath Family. Is there anyway to make it known where the children buffer is so that BFE can find it?

You doing it wrong. Your IBufferElement shouldn’t be in ICD, it’s separate type which you associate with entity.

That’s how I had it prior. I wanted to eliminate some of the clutter in the debugger. It’s a shame this couldn’t be done, but thank you for your answer.

Is there no alternative way to do what I’m trying to do? It would help with my code’s organization I feel to be able to call family.x instead of individually calling siblings, cousins, aunts/uncles, etc.

Depends on your need. Could you maybe have nativearrays of person struct, for both lovers, children and siblings? Whats in those specific structs today?

Here’s what they look like. So for example when I add a sister I would do sibings.Add(new Siblings{ sibling = entity, opinion = 100, brother = false});

A suggestion to restructure the data below.

This way you will have an array (dynamic buffer) of relations, and you can specify what relation that person is.

Also see this thread where I got help from @tertle on dynamic buffers, with links to docs.

I’m trying to learn myself, so if someone can confirm this is good idea, it’d be nice. :slight_smile:

public enum Relationship
{
    lover, parent, child, sibling
};

public struct Person : IComponentData
{
    public Entity entity;
    public Relationship relationship;
    public int opinion;
}

public struct ConnectedPersons : IBufferElementData
{
    public Person relations;
}
1 Like

^ That’s a good way. I would only change it to look like this:

public enum Relationship
{
    lover, parent, child, sibling
};

public struct ConnectedPersonElement : IBufferElementData
{
    public Entity entity;
    public Relationship relationship;
    public int opinion;
}

An IBufferElementData is just a single element in an array. It’s not something that holds an array. So it doesn’t make sense to give it a plural name. DynamicBuffer is the array that would hold, in this case, an array of ConnectedPersonElement.

4 Likes

Thanks ya’ll I appreciate the help and this seems like a better system! My only question though is what would be the best way to, for example, talk to a random aunt, or brother, etc. In the original system I could randomize the index of the respective relation buffer. Not sure how to do this with enums without iterating over each connected person just to pick randomly between two or three brothers. Or in another case, when someone is born, iterate over all the kids of the mother and add the baby to the connectedperson buffer as a sibling.

To talk to a random aunt you could get all the aunts of a character from DynamicBuffer and put them in a NativeArray and then randomly select which one you want the character to talk to.

Alternatively you could just ditch the Relationship enum and structure your data layout more granularly so it’s easier to access, add to, and remove relationships from a character based on the examples you gave. So something like this might suits your needs better:

public struct Parents : IComponentData
{
    public Entity motherEntity, fatherEntity;
    public int motherOpinion, fatherOpinion;
}

// Convert to IBufferElementData if your game has characters that are polyamorous :)
public struct Lover : IComponentData
{
    public Entity entity;
    public int opinion;
}

public struct ChildElement : IBufferElementData
{
    public Entity entity;
    public int opinion;
}

public struct SiblingElement : IBufferElementData
{
    public Entity entity;
    public int opinion;
}

One solution is not necessarily better than the other. In this case, the disadvantage would be that it’s harder to access all relationships of a given character, but would be easier with the previous data layout solution. So which data layout is better entirely depends on your data access patterns based on the problem you are trying to solve.