DefaultEcs icon indicating copy to clipboard operation
DefaultEcs copied to clipboard

Reference given by entity.Get<T> sometimes is not sync'ed with it's EnitytSet counterpart

Open nrader95 opened this issue 4 years ago • 5 comments

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.

nrader95 avatar Jun 14 '21 14:06 nrader95

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.

Doraku avatar Jun 15 '21 07:06 Doraku

Well the problem is that i'm getting this behavior even when i'm not debugging anything.

nrader95 avatar Jun 15 '21 08:06 nrader95

Tried to completely remove any debug related code and compile framework dll in that state. It didn't help.

nrader95 avatar Jun 15 '21 10:06 nrader95

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?

Doraku avatar Jun 15 '21 11:06 Doraku

No, i dont pass it anywhere. Yet i'm getting the problem when i'm writing to the ref given by Get<T>

nrader95 avatar Jun 15 '21 13:06 nrader95