Be cool if SceneObjects could throw an onArrive event...
by Bryan Edds · in Torque Game Builder · 05/05/2005 (6:12 pm) · 18 replies
I think it'd be cool if sceneObjects could throw an onArrive() event when they reach a certain position in the world. Say you have a sceneObject sitting at 0,0, and then you want to move it to 0, 100 with a setLinearVeloocity. When it arrives at 0, 100, it would throw an onArrive event so the programmer can set it at rest or whatever.
The current work-around I'm using is kinda ugly :)
Just another idea :)
The current work-around I'm using is kinda ugly :)
Just another idea :)
#2
I'd like to modify this request to throw an event when an object travels a given distance, to save having to determine the actual destination (though a destination could also be useful). We can already receive an event on elapsed time, so why not distance travelled? Or even when a given velocity is reached, when an acceleration is applied? Basically, any changing physical parameter should have associated events. Such threshold events are very useful when animating objects in realtime.
05/06/2005 (12:42 pm)
The tutorial is awesome, but I think this is still a very worthwhile request for the scripting language. Keeps things standard.I'd like to modify this request to throw an event when an object travels a given distance, to save having to determine the actual destination (though a destination could also be useful). We can already receive an event on elapsed time, so why not distance travelled? Or even when a given velocity is reached, when an acceleration is applied? Basically, any changing physical parameter should have associated events. Such threshold events are very useful when animating objects in realtime.
#3
You could even devise a simple callback system that accepts a bit of script code to run every frame, and if it returns "true", then it calls the callback.
05/06/2005 (1:44 pm)
There's a certain point when event-driven design mechanics break down, and suggesting that every physical parameter needs events associated with it is approaching that point, if it is not already past it. There are pretty obvious places where you want events to fire, but if you're needing arbitrary events, it would be more reasonable to just add appropriate checks on every frame advance of the object.You could even devise a simple callback system that accepts a bit of script code to run every frame, and if it returns "true", then it calls the callback.
#4
Very good requests, though these are sort of venturing into game systems, like movement systems...
to calculate how much distance an object has traveled you would then need to store the position it starts at... then a function to set (or save) the position its at to reference that.
In fact my thoughts went down the same road... onSceneUpdate is a callback that already does what you speak... my moveTo tutorial does a similar thing, it does a schedule that constantly checks if the objects reached its destination...
something like this could be ported to the C++ side, a moveTo type system... would just check its position in the integrateObject step, if that position matches the destination then its reached... then you make a setDestination function... but you would need to keep s peed variable as well so it knows how fast to go, which means a setSpeed function and the variable... things like this grow as you think of the practical application of them...
very good suggestions, though not as simple as they would seem at first. More like game systems too.
If you want to I could put that on a list to create tutorials for... a C++ moveTo function, and a distance traveled (that is if you don't want to attempt it yourself)
05/06/2005 (1:51 pm)
Smaug put it well.Very good requests, though these are sort of venturing into game systems, like movement systems...
to calculate how much distance an object has traveled you would then need to store the position it starts at... then a function to set (or save) the position its at to reference that.
Quote:You could even devise a simple callback system that accepts a bit of script code to run every frame, and if it returns "true", then it calls the callback.
In fact my thoughts went down the same road... onSceneUpdate is a callback that already does what you speak... my moveTo tutorial does a similar thing, it does a schedule that constantly checks if the objects reached its destination...
something like this could be ported to the C++ side, a moveTo type system... would just check its position in the integrateObject step, if that position matches the destination then its reached... then you make a setDestination function... but you would need to keep s peed variable as well so it knows how fast to go, which means a setSpeed function and the variable... things like this grow as you think of the practical application of them...
very good suggestions, though not as simple as they would seem at first. More like game systems too.
If you want to I could put that on a list to create tutorials for... a C++ moveTo function, and a distance traveled (that is if you don't want to attempt it yourself)
#5
there is one way to do a script side moveTo function
I have a script callback "onReachDestination()" in there that would function like onArrive()
05/06/2005 (1:52 pm)
T2D Tutorial moveTo - Creating a moveTo Functionthere is one way to do a script side moveTo function
I have a script callback "onReachDestination()" in there that would function like onArrive()
#6
Smaug, I feel you are making a straw man, which is why I disagree with your argument -
I never argued for every physical parameter to have events associated with it. Nor would the association of events to one type of physical parameter necessarily lead to others.
onArrive and onMoveDistance would be great callbacks to have in the standard engine because they help avoid unecessary and design-detrimental ticking.
But why are we arguing? I figure Melv should give a thumbs up or thumbs down (or even a thumbs I'll think about it) and that should be that.
EDIT: for clarity and content
05/06/2005 (4:15 pm)
I come from the school that says unnecessary ticking is a sign of bad design. Programs should be event driven except in the circumstance where an event is necessarily time-driven.Smaug, I feel you are making a straw man, which is why I disagree with your argument -
Quote:There's a certain point when event-driven design mechanics break down, and suggesting that every physical parameter needs events associated with it is approaching that point, if it is not already past it.
I never argued for every physical parameter to have events associated with it. Nor would the association of events to one type of physical parameter necessarily lead to others.
onArrive and onMoveDistance would be great callbacks to have in the standard engine because they help avoid unecessary and design-detrimental ticking.
But why are we arguing? I figure Melv should give a thumbs up or thumbs down (or even a thumbs I'll think about it) and that should be that.
EDIT: for clarity and content
#7
just pointing out that with
onArrive
you would need setDestination or something of the sorts... so you can tell when to send back onArrive
onMoveDistance
would require a setStartPoint or something similar, to reference when to start recording the distance, otherwise it would be a one shot deal from when the item starts :)
I'll extend an offer again to help integrate them -at least a temporary fix for now-(that is if Melv doesn't have time to and/or if it doesn't rank high on the priorities)
05/06/2005 (4:18 pm)
Btw I'm not arguing the point of it (not sure if you were referring to me also)...just pointing out that with
onArrive
you would need setDestination or something of the sorts... so you can tell when to send back onArrive
onMoveDistance
would require a setStartPoint or something similar, to reference when to start recording the distance, otherwise it would be a one shot deal from when the item starts :)
I'll extend an offer again to help integrate them -at least a temporary fix for now-(that is if Melv doesn't have time to and/or if it doesn't rank high on the priorities)
#8
It would would be helpful if you did a tut or a resource on this subject :) And it would give Melv an example implementation if he wanted to go ahead and add it into the engine :D But this is kinda beside the point of my suggestion :) The thing I'm trying to acheive with this suggestion though is to make the T2D engine better right out of the box for everybody.
EDIT: Basically rewrote the whole darn post :)
05/06/2005 (4:27 pm)
Matt, you are definitely the man for helping, and nah, I wasn't arguing with you :)It would would be helpful if you did a tut or a resource on this subject :) And it would give Melv an example implementation if he wanted to go ahead and add it into the engine :D But this is kinda beside the point of my suggestion :) The thing I'm trying to acheive with this suggestion though is to make the T2D engine better right out of the box for everybody.
EDIT: Basically rewrote the whole darn post :)
#9
05/06/2005 (5:02 pm)
Smaug, I've never seen event-driven programming 'break down'. I am curious as to what that entails and what that actually means when you say that.
#10
A design paradigm, be it event-driven models or whathaveyou, exists to make the job of the programmer easier. However, this only exists to the extent that your problem corresponds with the solutions provided by the design paradigm. Let's take the two models mentioned here (event-driven and frameloop) and see what happens when they are applied to different problems.
Let's say we need to write a GUI. We all know what that entails: windows, widgets, mouse and keyboard response, etc.
If each window has some kind of frameloop, you create a nightmare of code, let alone some performance issues. Each frame, every window must check to see if the mouse is over it, if the mouse button was pressed, which keys were pressed, etc. This is a performance problem and spawns some pretty ugly Window::FrameAdvance code. Clearly, the frameloop paradigm is a poor fit for this problem. If you started to implement a GUI under this paradigm, you would quickly find it breaking down. Meaning that you would be spending far too much time debugging spagetti code and dealing with the web of interconnections between windows to create effective code.
However, an event-driven system fits a GUI almost perfectly. Windows that aren't receiving events receive no processing time. You may want to pass events to other windows, but since every window can process events, this is trivial at best. If you need to derive a new window and extend the messages it processes, while changing how it processes some of its base messages, this too is trivial through inhieritance and polymorphism. The code you get is clean, maintainable, lucid, and quite debuggable.
Of course, just like the frameloop system as mentioned before, there are problem domains where the event-driven system breaks down. Complex AI, for example.
Let's say you have ships in space. And these ships move in an Asteroids fashion, and they shoot at one another. An FPS in space, if you will.
An event driven model can be made to work here. However, it is hardly a natural fit and generates any number of problems. Indeed, to get good response, each frame quite a few events are going to be handed to each AI entity. It needs to be told when its current target (if any) moves so that it can update its facing; it needs to be told when nearby objects move (and when I move) so that it can check to see if it needs to avoid them. Take just those two separate and distinct events. Facing determines thrust direction, but it also determines where you can shoot. So, now you have two events whose responses are competing for the same resources, which is a situation that event-driven models handle poorly if at all. Of course, you also need to deal with pathfinding, who needs to use both facing and thrust to get from place to place. And if you detect that an enemy has locked on to you, you have another event that needs to start evading. Clearly, the event-driven model is not well suited to this problem domain; it leads to event resolutions whose results are not ultimately separate and distinct from one another.
A frameloop model, however, is just fine. You can determine contention situations and devise ways to determine which behavior should be used in which circumstances (targetting gets first crack, followed by pathfinding, but if there is a dangerous object ahead, evasion gets top priority, etc). Because the AI is being called every frame without the event-driven model's notion of why it is being called, it is capable of going out and finding any of the information it needs to do its job.
It's all about using the right tool for the right job. Don't beat a square peg into a round hole just because the square peg fit into the square hole.
05/06/2005 (7:36 pm)
When a design "breaks down", it means, in the most extreme extent, that it is no longer useful to solve the current programming problem. However, a break down in a paradigm can happen long before that.A design paradigm, be it event-driven models or whathaveyou, exists to make the job of the programmer easier. However, this only exists to the extent that your problem corresponds with the solutions provided by the design paradigm. Let's take the two models mentioned here (event-driven and frameloop) and see what happens when they are applied to different problems.
Let's say we need to write a GUI. We all know what that entails: windows, widgets, mouse and keyboard response, etc.
If each window has some kind of frameloop, you create a nightmare of code, let alone some performance issues. Each frame, every window must check to see if the mouse is over it, if the mouse button was pressed, which keys were pressed, etc. This is a performance problem and spawns some pretty ugly Window::FrameAdvance code. Clearly, the frameloop paradigm is a poor fit for this problem. If you started to implement a GUI under this paradigm, you would quickly find it breaking down. Meaning that you would be spending far too much time debugging spagetti code and dealing with the web of interconnections between windows to create effective code.
However, an event-driven system fits a GUI almost perfectly. Windows that aren't receiving events receive no processing time. You may want to pass events to other windows, but since every window can process events, this is trivial at best. If you need to derive a new window and extend the messages it processes, while changing how it processes some of its base messages, this too is trivial through inhieritance and polymorphism. The code you get is clean, maintainable, lucid, and quite debuggable.
Of course, just like the frameloop system as mentioned before, there are problem domains where the event-driven system breaks down. Complex AI, for example.
Let's say you have ships in space. And these ships move in an Asteroids fashion, and they shoot at one another. An FPS in space, if you will.
An event driven model can be made to work here. However, it is hardly a natural fit and generates any number of problems. Indeed, to get good response, each frame quite a few events are going to be handed to each AI entity. It needs to be told when its current target (if any) moves so that it can update its facing; it needs to be told when nearby objects move (and when I move) so that it can check to see if it needs to avoid them. Take just those two separate and distinct events. Facing determines thrust direction, but it also determines where you can shoot. So, now you have two events whose responses are competing for the same resources, which is a situation that event-driven models handle poorly if at all. Of course, you also need to deal with pathfinding, who needs to use both facing and thrust to get from place to place. And if you detect that an enemy has locked on to you, you have another event that needs to start evading. Clearly, the event-driven model is not well suited to this problem domain; it leads to event resolutions whose results are not ultimately separate and distinct from one another.
A frameloop model, however, is just fine. You can determine contention situations and devise ways to determine which behavior should be used in which circumstances (targetting gets first crack, followed by pathfinding, but if there is a dangerous object ahead, evasion gets top priority, etc). Because the AI is being called every frame without the event-driven model's notion of why it is being called, it is capable of going out and finding any of the information it needs to do its job.
It's all about using the right tool for the right job. Don't beat a square peg into a round hole just because the square peg fit into the square hole.
#11
Obviously, once such general events exist, they can be used to create robust movement systems. But these events are the tools with which that system can be built, not the system itself.
But again, I REALLY appreciate the guidance toward ways to do this without changing the engine. Before long, I hope to be able to make all of these kinds of changes myself for my personal hacked up version of the engine. So much to learn!
05/06/2005 (7:46 pm)
I understand the point about sticking to basic building blocks rather than creating game systems. But a major point to consider in regard to any function is whether it needs to integrate tightly with the physics engine. Since, if a game is designed properly, the vast majority of actual motion will take place under the hood, within the engine, tests on things like position and velocity are best handled at the engine level.Obviously, once such general events exist, they can be used to create robust movement systems. But these events are the tools with which that system can be built, not the system itself.
But again, I REALLY appreciate the guidance toward ways to do this without changing the engine. Before long, I hope to be able to make all of these kinds of changes myself for my personal hacked up version of the engine. So much to learn!
#12
But in general, I don't disagree with you. Clearly we need to be careful how we implement our solutions. My point in this case, though, is that it's easy for the physics engine to test and throw the event at the appropriate time, so that would be more efficient than polling for the threshold at a higher level.
When updating the position of a given object, the physics engine has all of the relevant data at hand. This is the best possible time to test for a state that depends on this data. The high level engine has no way of knowing when to test, and so it must test frequently and continually until the state exists. This results in so much unnecessary processing. So far, I've avoided any kind of polling in my T2D designs. Instead, I've relied on those things that the engine does so well, events and callbacks. This is an event driven engine, so why not extend that capacity?
But as Bryan said, Melv is in the best position to decide whether such a feature would add unnecessarily to engine overhead.
05/06/2005 (8:06 pm)
@Smaug: Actually, it's best to allow a high level object to request certain events, rather than expect it to handle every one. That way, it's up to the high level code design to avoid breaking the system. One must make sparing use of the events to be handled or it becomes impossible to maintain framerate. But that's no reason for the engine to not provide a wide range of possible events for a given object to support.But in general, I don't disagree with you. Clearly we need to be careful how we implement our solutions. My point in this case, though, is that it's easy for the physics engine to test and throw the event at the appropriate time, so that would be more efficient than polling for the threshold at a higher level.
When updating the position of a given object, the physics engine has all of the relevant data at hand. This is the best possible time to test for a state that depends on this data. The high level engine has no way of knowing when to test, and so it must test frequently and continually until the state exists. This results in so much unnecessary processing. So far, I've avoided any kind of polling in my T2D designs. Instead, I've relied on those things that the engine does so well, events and callbacks. This is an event driven engine, so why not extend that capacity?
But as Bryan said, Melv is in the best position to decide whether such a feature would add unnecessarily to engine overhead.
#13
One could selectively override the physics engine with such a callback. It would be very powerful. If there is such an event, I could greatly improve much of the code I've already written in T2D. Please tell me there is ;)
Just as an example, in another post I requested the ability to have the mount point shift according to a given velocity. Using an OnRender callback with scene time passed directly would allow me to update my mount point on the fly, simulating this kind of functionality. This is an example of a function that really must be processed with each frame.
Basically, I'm using schedule to take care of all of my animation needs, but it's inefficient to stuff the scheduler with callbacks for ever little movement I want to generate. Plus, I'd just have so much more control over these movements in an OnRender event.
05/06/2005 (8:24 pm)
Another point on this subject. In other game engines I've worked in, it's common to have a basic OnRender event so you can capture the object just before it's displayed. Does T2D provide this kind of callback for sprites? If so, there isn't much functionality I can think of that couldn't be handled in this way. It would provide a just-in-time hook that would make these kinds of tests easy to implement at the script level.One could selectively override the physics engine with such a callback. It would be very powerful. If there is such an event, I could greatly improve much of the code I've already written in T2D. Please tell me there is ;)
Just as an example, in another post I requested the ability to have the mount point shift according to a given velocity. Using an OnRender callback with scene time passed directly would allow me to update my mount point on the fly, simulating this kind of functionality. This is an example of a function that really must be processed with each frame.
Basically, I'm using schedule to take care of all of my animation needs, but it's inefficient to stuff the scheduler with callbacks for ever little movement I want to generate. Plus, I'd just have so much more control over these movements in an OnRender event.
#14
05/06/2005 (8:27 pm)
Theres onSceneUpdate() for the scenegraph which occurs every frame
#15
Thanks!
05/06/2005 (8:47 pm)
Yes. Just found that ;) I read that in practice it hasn't been as efficient as extensive use of schedule, but I'll do some benchmarking and see for myself.Thanks!
#16
But does the inclusion of onArrive and onMoveDistance constitute a design break down? Well, if we can use the term 'design breakdown' to describe something that puts a burden on the library vendor (Melv) without benefitting the client (me) just to be consistant with a given design / paradigm, then I think that -
a) an onArrive and onMoveDistance IS beneficial and therefore,
b) the inclusion of these events does not constitute a 'breakdown' of any sort IMO.
So, I believe it is consistant with what I consider to be t2d design / paradigm as well as beneficial.
But like you said, if every single possible physical attribute were to be associated with all possible events, there would most definitely be a break down, the first breakdown being with poor Melv's nerves having to write all that stuff :). Fortunately, this is not what I propose.
05/06/2005 (8:54 pm)
Cool Smaug, good way to explain design break downs :)But does the inclusion of onArrive and onMoveDistance constitute a design break down? Well, if we can use the term 'design breakdown' to describe something that puts a burden on the library vendor (Melv) without benefitting the client (me) just to be consistant with a given design / paradigm, then I think that -
a) an onArrive and onMoveDistance IS beneficial and therefore,
b) the inclusion of these events does not constitute a 'breakdown' of any sort IMO.
So, I believe it is consistant with what I consider to be t2d design / paradigm as well as beneficial.
But like you said, if every single possible physical attribute were to be associated with all possible events, there would most definitely be a break down, the first breakdown being with poor Melv's nerves having to write all that stuff :). Fortunately, this is not what I propose.
#17
05/06/2005 (9:02 pm)
What you want for your example isn't onRender; you want to get each object's physics frame advance tick. These are two separate actions; the world can be updated without being rendered, and the screen can be rendered without updating the world. Depending on settings, the world can be updated several times before a rendering advance happens, particularly if you are vsync'd. If you're doing positional work, you need something that gets called post-physics advance, while if you're doing sprite animation work, it needs to be done before the sprite is rendered.
#18
I'd love to have the option to use either ;)
In the engine, code like this:
if ( pSceneObject2D->getOnRender() )
pSceneObject2D->onScriptRender( mSceneTime );
or
if ( pSceneObject2D->getOnCompute() )
pSceneObject2D->onScriptCompute( mSceneTime );
has very little overhead when not used, and that leaves it up to us designers to decide how much we can afford to use it before the system breaks.
Getting back to this discussion, the request for onArrive and onMoveDistance, both could easily be implemented within the more general onCompute. It's not so easy to implement such a general system using onUpdateScene, because it would be necessary to maintain a list of all objects with an interest in this event. Tossing the event from the object itself at the appropriate time saves so much work and is more efficient, vs iterating through a list of objects at the script level with each onUpdateScene call.
05/06/2005 (9:38 pm)
You're right, my mistake. What I'm talking about is actually something like onCompute, which gets called with each state update iteration. This doesn't necessarily correspond to a render pass. onRender has its uses for low-priority control, but for high precision control, onCompute would be necessary.I'd love to have the option to use either ;)
In the engine, code like this:
if ( pSceneObject2D->getOnRender() )
pSceneObject2D->onScriptRender( mSceneTime );
or
if ( pSceneObject2D->getOnCompute() )
pSceneObject2D->onScriptCompute( mSceneTime );
has very little overhead when not used, and that leaves it up to us designers to decide how much we can afford to use it before the system breaks.
Getting back to this discussion, the request for onArrive and onMoveDistance, both could easily be implemented within the more general onCompute. It's not so easy to implement such a general system using onUpdateScene, because it would be necessary to maintain a list of all objects with an interest in this event. Tossing the event from the object itself at the appropriate time saves so much work and is more efficient, vs iterating through a list of objects at the script level with each onUpdateScene call.
Torque 3D Owner Matthew Langley
Torque
my latest tutorial covers creating a sub object of fxSceneObject and putting some things in integrate object so it will follow the mouse when notified to do so...
your idea could easily be added to fxSceneObjects integrate object