For engines written by you in native code
- Separate your render logic out. Every cycle, run all your game / simulation logic in one phase, and once that's all complete, run all rendering logic -- this includes animation.
Since rendering and animation are separate, run game logic timers that use the same duration as the animations, but only have game logic react to the completion of the logic timer, not the animation timer. Example follows:
- (1st tick)
gameLogic.startProcess(myDuration). remainingDuration is in the data model.
- (1st tick)
renderer.startAnimation(myDuration).
- (all ticks between 1st and final) game logic checks whether process is ready to expire by comparing time remaining against duration.
- (all ticks between 1st and final) animation proceeds.
- (final tick) Game Logic completes. Take game logic actions accordingly.
- (final tick) Animation completion coincides with logic completion. No callback is required because completion was already handled in model. (You'll need to know what the animation's duration is in order to achieve this.)
...Thus because you've smiultaneously started a game logic process and a render process with the same duration, they will finish at the same time, but you don't need render logic to notify game logic that the animation is complete, because the game logic already knows by looking at myDuration in the model.
For existing engines / platforms like Unity
...or Flash, where render and game logic is mixed and events are common, best stick with the approach that is most commonly used, by chaining render logic back to game logic using an event. It is not worth the effort to go against the architectural paradigms inherent in the core language / platform, it will simply make your life difficult.
About animation
Again depending on language / platform, animation may or may not be handled automagically for you. Flash MovieClips, for instance, will handle this.. Unity works similarly if you use out-of-box solutions for animation, JS also whenever you use setInterval or requestAnimationFrame. Nevertheless, bear in mind that at some fundamental level, usually in native code, there is always a loop that is running and doing all of this for you, whether it is animation or your main game loop updates on GameObjects, Sprites or whatever. If you are already writing native code, then you will know this from working with your main application loop.