-
First, just want to say that I've really been enjoying using DefaultEcs for the game that I'm developing! I have some situations where a component needs to refer to another entity. For example, in my game the player can breed plants. I have a Pollen component that tracks which plant Entity the pollen was extracted from. I've just been storing this as an Entity. I.e.
This has worked fine, except now I am trying to serialize/deserialize the game state. (I couldn't get the built-in TextSerializer to work and I'm doing my own JSON serialization). The problem is that after serializing and de-serializing everything, if I check
Thanks so much! |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
Hey great to know that DefaultEcs is doing it for you :) The is a recurring missing feature for which I don't have a complete solution yet. If you know what you are doing there is nothing wrong with storing entity in component, my goal is to have some kind of reference component that would allow you to reference an other entity component which would be automatically removed/disabled as the actual entity changes state so you don't have to do those checks yourself but it's not here yet :( Anyway on the serialization problem, this is why my serializers takes a |
Beta Was this translation helpful? Give feedback.
-
I too have run into this issue, thought I would share my work for this Use this EntityReference field inside any of your components (Not as a component) public struct EntityReference
{
private Entity _entityValue;
private Guid _entityId;
public static implicit operator Entity(EntityReference er)
{
return er._entityValue;
}
public Entity AsEntity()
{
return (Entity)this;
}
public static implicit operator EntityReference(Entity e)
{
var value = new EntityReference();
value.SetEntity(e);
return value;
}
private void SetEntity(Entity entity)
{
if (entity.Has<Guid>())
{
_entityId = entity.Get<Guid>();
}
else
{
_entityId = Guid.NewGuid();
entity.Set(_entityId);
}
_entityValue = entity;
}
public void Sync(EntityMap<Guid> map)
{
_entityValue = map[_entityId];
}
} Then after load var entityReferenceEntitiesMap = World.GetEntities().With<Guid>().AsMap<Guid>();
var entityReferenceEntities = World.GetEntities().AsEnumerable();
foreach (var entityReferenceEntity in entityReferenceEntities)
{
entityReferenceEntity.ReadAllComponents(new EntityReferenceReader(entityReferenceEntitiesMap));
} Finally the EntityReferenceReader will fixup the reference, this uses some reflection so probably isnt very fast public class EntityReferenceReader : IComponentReader
{
private readonly EntityMap<Guid> _entityReferenceEntitiesMap;
public EntityReferenceReader(EntityMap<Guid> entityReferenceEntitiesMap)
{
_entityReferenceEntitiesMap = entityReferenceEntitiesMap;
}
public void OnRead<T>(in T component, in Entity componentOwner)
{
var fields = typeof(T).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var fieldInfo in fields)
{
if (fieldInfo.FieldType == typeof(EntityReference))
{
var obj = (object)component;
if (fieldInfo.GetValue(obj) is EntityReference entityReferenceValue)
{
entityReferenceValue.Sync(_entityReferenceEntitiesMap);
fieldInfo.SetValue(obj, entityReferenceValue);
componentOwner.Set((T)obj);
}
}
}
}
} |
Beta Was this translation helpful? Give feedback.
Hey great to know that DefaultEcs is doing it for you :)
The is a recurring missing feature for which I don't have a complete solution yet. If you know what you are doing there is nothing wrong with storing entity in component, my goal is to have some kind of reference component that would allow you to reference an other entity component which would be automatically removed/disabled as the actual entity changes state so you don't have to do those checks yourself but it's not here yet :(
Anyway on the serialization problem, this is why my serializers takes a
Predicate<Type>
and a SerializationContext to marshal types. That way you can transform your non serializable component to something …