Reference given by entity.Get<T> sometimes is not sync'ed with it's EnitytSet counterpart
Another weird bug i stumbled on. So here is the code. Component:
public struct CommandsComponent {
public CommandsComponent(Queue<ICommand> queue) {
Commands = queue;
CurrentCommand = null;
}
public Queue<ICommand> Commands;
public ICommand CurrentCommand;
public void AddCommand(ICommand newCommand, in Entity ownEntity) {
Commands.Enqueue(newCommand);
if (CurrentCommand == null) {
CurrentCommand = newCommand;
CurrentCommand.Activate(ownEntity);
}
}
}
And the system:
[With(typeof(CommandsComponent))]
public class CheckCommandCompletedSystem : AEntitySetSystem<float> {
public CheckCommandCompletedSystem(World world) : base(world) { }
protected override void Update(float state, in Entity entity) {
ref var commandsComponent = ref entity.Get<CommandsComponent>();
if (commandsComponent.CurrentCommand != null) {
if (commandsComponent.CurrentCommand.IsCompleted(entity)) {
commandsComponent.CurrentCommand.Complete(entity);
if (commandsComponent.Commands.Count > 0) commandsComponent.Commands.Dequeue();
commandsComponent.CurrentCommand = commandsComponent.Commands.FirstOrDefault();
commandsComponent.CurrentCommand?.Activate(entity);
}
}
}
}
This is something i was able to nail, more or less.
When i debugged this code, what i saw is that data i recorded to commandsComponent variable declared inside the system's updates normally. BUT when i browsed private fields of the system and opened system's internal set, and then same entity which i was updating at the time, what i saw is same component, completely unchanged. And also, changing component to class fixes the issue.
So it looks like there is some value-types data copy happening in the middle, and the reference that i've got points to that copy.
You mean in the debug view? then yes the components are copied if you look at the components of an entity through the debugger. I am not sure this can be worked around as we can't store a ref as a field/property. This is the culprit code https://github.com/Doraku/DefaultEcs/blob/2e0479a37d2f6405eaa42e94b642c7b3db0259a9/source/DefaultEcs/Technical/Debug/EntityDebugView.cs#L37 This only impact the debugging view, I will try a quick idea just in case this can be worked around.
Well the problem is that i'm getting this behavior even when i'm not debugging anything.
Tried to completely remove any debug related code and compile framework dll in that state. It didn't help.
I thought you were seeing the copy inside the debug view, if you are experiencing a different value than expected when doing a Entity.Get<T> then that means you are not updating your component value correctly somewhere because no copy is done anywhere else in the framework. Are you always calling methods and field on your CommandsComponent from a ref CommandsComponent variable? never passed as a method parameter?
No, i dont pass it anywhere. Yet i'm getting the problem when i'm writing to the ref given by Get<T>