sschmid / Entitas

Entitas is a super fast Entity Component System (ECS) Framework specifically made for C# and Unity
MIT License
7.03k stars 1.11k forks source link

What system or attributes should I write to stop the timer, when remove component? #1002

Closed atkdefender closed 2 years ago

atkdefender commented 2 years ago

I place a timer in component. After component remove, or entity destroy, it still ticking, rising a error. What system or attributes should I write to stop it?

I have try ReactiveSystem, CreateCollector(GameMatcher.Timer.Removed()); But when Removed() happen, the timer is already deleted, even entity deleted, I can't get the timer to Stop().

public class TimerRemoveSystem : ReactiveSystem<GameEntity>
{
    public TimerRemoveSystem(Contexts contexts) : base(contexts.game) { }
    protected override ICollector<GameEntity> GetTrigger(IContext<GameEntity> context)
        => context.CreateCollector(GameMatcher.Timer.Removed());

    protected override bool Filter(GameEntity entity)
        => entity.hasTimer;

    protected override void Execute(List<GameEntity> entities)
    {
        foreach (var e in entities)
        {
            Utility.singleton.Print(e.id.value);
            e.timer.Stop();
        }
    }
}
mchamplain commented 2 years ago

If you remove the component, then at this point the entity should still be present but without the TimerComponent. Your current filter makes it that you never have anything in the Execute method. If you change the filter to always return true, then you'll get the entity in the Execute method. But yeah, if the timer is in that component, then you can't access it.

I'm guessing you are using System.Timer? You could design you own timer system I'm thinking something like

TimerComponent { float value }
TimerActive{}  
TimerEnded{}  

an ExecuteSystem that substract the deltatime from the active timer value, then you can do e.isTimerEnded=true; when <=0

Then a reactive system for TimerEnded.Added() will get you the timers that are finished.

atkdefender commented 2 years ago

If you remove the component, then at this point the entity should still be present but without the TimerComponent. Your current filter makes it that you never have anything in the Execute method. If you change the filter to always return true, then you'll get the entity in the Execute method. But yeah, if the timer is in that component, then you can't access it.

I'm guessing you are using System.Timer? You could design you own timer system I'm thinking something like

TimerComponent { float value }
TimerActive{}  
TimerEnded{}  

an ExecuteSystem that substract the deltatime from the active timer value, then you can do e.isTimerEnded=true; when <=0

Then a reactive system for TimerEnded.Added() will get you the timers that are finished.

I'm using Dotween's Sequence as timer actually. Reactive system can't get in the moment just before component remove, so I can't get the timer_value. ExecuteSystem is the good way. If Entitas has something like ~ClassName, that will be great.