-
Notifications
You must be signed in to change notification settings - Fork 70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add processor phases feature #91
base: master
Are you sure you want to change the base?
Conversation
acinis
commented
Aug 15, 2023
- imports: Union and IntFlag
- Processor.phases instance variable: allows IntFlag and bare int for default ~0
- World.add_processor method: new optional arg _phases
- World._process method: new arg _phases
- World.process method: call to _process with ~0 (all flags set - all phases on)
- World.process_phase method: new method, like process, but accepts phases arg
- imports: Union and IntFlag - Processor.phases instance variable: allows IntFlag and bare int for default ~0 - World.add_processor method: new optional arg _phases - World._process method: new arg _phases - World.process method: call to _process with ~0 (all flags set - all phases on) - World.process_phase method: new method, like process, but accepts phases arg
Hi, (Sorry if PRs without prior issue are not welcome here.) This PR adds phases to world processing feature. It's usefull eg. when we have some logic systems that will be called at higher frequency than rendering system. Note: I chose name
|
A small usage example would be cool. I have a vague idea of skipping certain processors, but not 100% sure of a use case. |
# Example: Fixed update time step but with variable rendering
class Phase(enum.IntFlag):
PHYSICS = enum.auto()
RENDERING = enum.auto()
# TIME_PER_UPDATE is our fixed delta time
TIME_PER_UPDATE = 16 # Just an example, 16ms is about 60 FPS
acc = 0 # accumulator - how much time we are behind with simulation
while True:
elapsed = get_elapsed_time()
acc += elapsed
handle_input()
# Inner catch-up loop
# When eg. user PC can't do so much processing in certain in-game situation
# and we are behind with simulation, this loop will run few times...
while acc >= TIME_PER_UPDATE:
world.process_phase(Phase.PHYSICS, TIME_PER_UPDATE)
acc -= TIME_PER_UPDATE
# ... but rendering is run just once, so we lost few rendered frames,
# but game world is still intact (eg. no bullet will fly through the wall).
world.process_phase(Phase.RENDERING, TIME_PER_UPDATE) I feel like this example is too minimal, but I hope it's clear how processing phases will be useful. Also think about various supporting systems like caching, achievements, etc. So another example will be (with all systems at fixed time step):
Also, in some (most?) ECS implementations systems are run manually, so we have full control how and when our systems will run. In this PR, everything will work as before. But if someone needs more control, there are additional methods for running only certain processing phase. |
Is it like using multiple World instances (or multiple contexts in v3) but separate processors can share data ? |
Well, I think it's not like contexts. From https://github.com/benmoran56/esper/blob/esper3/esper/__init__.py
Phases will share everything, it's just a way to run some processors conditionally (less frequently or based on user setting, etc). I think phases will play nicely with multiple worlds/contexts. PS. Maybe I just choose bad name for phases. |
Sorry for the delay. I'm also not sure if |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basic concept is good.
I would say that it's better to replicate the process method, rather than sharing code. This will avoid the minor performance penalty for those who are not using this feature.