Players and Doors (And Collision)
by Glenn Bermingham · in Torque 3D Professional · 08/27/2014 (7:40 pm) · 25 replies
Been a while since I've been active here, just wanted to get other peoples ideas and opinions on going about players and doors (Collision specifically).
So one of the fundamental flaws you find working with the base(Full) First Person T3D, is when you want to implement a simple swinging door and then have the collision not affect the players position and most likely permanently lodge the player inside. To clarify, this is talking about solutions that don't require major engine changes.
Simple fix would be not to have swinging doors... While Sci-fi and shopping mall games could get away with this, its not really an acceptable answer.
Taking a look from another games point of view is Half Life 2(Source Engine), the Source engines doors system is actually quite cleaver but you probably wouldn't notice it. On a surface level the doors do not have and collision problems as the door and physics engine work in conjunction with the player and the door simply pushes the player away. However the next time you play Half Life 2, take note that every time you open a door, the door will always open away from you and never towards you. This is intentional to stop any unwanted issues like being stuck in the door or pushed away annoyingly.
So the initial problem with a T3D door system is that it'll likely have an open and close function(s) which consist of an Open and Closed state. These states would be done through animation and same with the collision. The Door then only swings open in one direction, so unless you're really nit picky with your level flow and tunnel your players direction, you're going to have some backwards doors. Which they'll open and likely get stuck in it. So what can we do about that...
So my first attempt at fixing the problem was to create a literal PhysicalZone's that would spawn and destroy itself inside of the door location to push the player in the doors swinging direction. Here's my code for it if people are interested: (This was in my door "open" function)
The problem with it is that if a player immediately started to walk into the doorway as the door was swinging away from the player, they'd get sucked through the doorway. While I did add an offset to the position the zone spawned in to be center of the door swing area; the problem is still there just not quite as obvious. Also note I had a function for closing of the door too which had the same effect only sucked plays into a closed door briefly. So while I think this was a good step in the right direction, it still felt cheap and a hack than a real fix.
Another option I consider was teleporting the player away from the door, but I quickly dismissed the idea as it'd be jolting and feel extremely cheap.
Now I'm thinking for a swinging door to work, its going to need several mechanics working in conjunction with each other. My simple physical Zone, while it does the job, its extremely... time consuming to get right for each door, there is not automatic direction of which way the physical zone actually pushes and the zone cannot be setup for one direction and simply rotated. In an ideal situation you'd want to simply be able to spawn the door object and have all of its fields automatically filled in whenever the door is used. That would take some good amount of maths to convert the rotation to the forces (1000 -1000 0 etc).
Despite that, the next viable step for me is to enhance my doors with double directions, have an open and close state for both swinging directions and have the door always open away from the player.
If you've got an idea of a way to go about this or any suggestions go into as much detail as you want.
It might seem like an excessive amount of time on a (What seems to be) a simple system, but we're in an age where people will quickly discredit a game because of things that seem "simple" but in reality take quite a complex bit of thinking to make it function in a way people expect.
So one of the fundamental flaws you find working with the base(Full) First Person T3D, is when you want to implement a simple swinging door and then have the collision not affect the players position and most likely permanently lodge the player inside. To clarify, this is talking about solutions that don't require major engine changes.
Simple fix would be not to have swinging doors... While Sci-fi and shopping mall games could get away with this, its not really an acceptable answer.
Taking a look from another games point of view is Half Life 2(Source Engine), the Source engines doors system is actually quite cleaver but you probably wouldn't notice it. On a surface level the doors do not have and collision problems as the door and physics engine work in conjunction with the player and the door simply pushes the player away. However the next time you play Half Life 2, take note that every time you open a door, the door will always open away from you and never towards you. This is intentional to stop any unwanted issues like being stuck in the door or pushed away annoyingly.
So the initial problem with a T3D door system is that it'll likely have an open and close function(s) which consist of an Open and Closed state. These states would be done through animation and same with the collision. The Door then only swings open in one direction, so unless you're really nit picky with your level flow and tunnel your players direction, you're going to have some backwards doors. Which they'll open and likely get stuck in it. So what can we do about that...
So my first attempt at fixing the problem was to create a literal PhysicalZone's that would spawn and destroy itself inside of the door location to push the player in the doors swinging direction. Here's my code for it if people are interested: (This was in my door "open" function)
if (%this.getFieldValue(pushEnabled))
{
%pos = VectorAdd(%this.getPosition(), %this.getFieldValue(pushOffset));
%openpush = %this.getFieldValue(pushOpen);
%scalepush = %this.getFieldValue(pushScale);
//echo(%pos);
%pushZone = new PhysicalZone(Door_pushZone)
{
position = %pos;
scale = %scalepush;
velocityMod = "1";
gravityMod = "1";
appliedpush = %openpush;
polyhedron = "-0.5 0.5 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 -1.0 0.0";
};
%this.pushZone = %pushZone;
}Then had this code in a OnAnimationEnd function// Delete push Zones
if(isObject(%this.pushZone))
%this.pushZone.delete();The problem with it is that if a player immediately started to walk into the doorway as the door was swinging away from the player, they'd get sucked through the doorway. While I did add an offset to the position the zone spawned in to be center of the door swing area; the problem is still there just not quite as obvious. Also note I had a function for closing of the door too which had the same effect only sucked plays into a closed door briefly. So while I think this was a good step in the right direction, it still felt cheap and a hack than a real fix.
Another option I consider was teleporting the player away from the door, but I quickly dismissed the idea as it'd be jolting and feel extremely cheap.
Now I'm thinking for a swinging door to work, its going to need several mechanics working in conjunction with each other. My simple physical Zone, while it does the job, its extremely... time consuming to get right for each door, there is not automatic direction of which way the physical zone actually pushes and the zone cannot be setup for one direction and simply rotated. In an ideal situation you'd want to simply be able to spawn the door object and have all of its fields automatically filled in whenever the door is used. That would take some good amount of maths to convert the rotation to the forces (1000 -1000 0 etc).
Despite that, the next viable step for me is to enhance my doors with double directions, have an open and close state for both swinging directions and have the door always open away from the player.
If you've got an idea of a way to go about this or any suggestions go into as much detail as you want.
It might seem like an excessive amount of time on a (What seems to be) a simple system, but we're in an age where people will quickly discredit a game because of things that seem "simple" but in reality take quite a complex bit of thinking to make it function in a way people expect.
About the author
I spend most of my time working on games.
#2
Deathball Arena has no need of them, for instance.
Ken Finney's 3D Game Programming All-in-One talks about this, but unless you have the latest edition you'll be looking at TGE scripts. They should put you on the right track, though.
09/06/2014 (10:14 am)
Well, doors are not in every game...Deathball Arena has no need of them, for instance.
Ken Finney's 3D Game Programming All-in-One talks about this, but unless you have the latest edition you'll be looking at TGE scripts. They should put you on the right track, though.
Quote:Don't sell doors short - depending on the game type, expected door behavior can be quite different. See The Door Problem to see what I mean.
It might seem like an excessive amount of time on a (What seems to be) a simple system, but we're in an age where people will quickly discredit a game because of things that seem "simple" but in reality take quite a complex bit of thinking to make it function in a way people expect.
#3
09/07/2014 (2:30 pm)
I don't think Glenn is necessarily suggesting the engine should have a built-in door object (nor am I). The lack of door-ability is an underlying issue with, for example, stock physics, the lack of moving colliders, etc.
#4
General stock physics needs some love, true - and as a general statement you are absolutely correct. I've never been sure why collision geometry animations have always been so wonky.
09/07/2014 (8:07 pm)
Actually, my point was more that this hasn't gotten more attention because there aren't many people making games that use doors.General stock physics needs some love, true - and as a general statement you are absolutely correct. I've never been sure why collision geometry animations have always been so wonky.
#5
The collision issue is twofold, as far as I understand it. First you have lots of classes caching collision data (and cache invalidation is famously one of the two hardest problems in programming, along with naming things and off-by-one errors), though when I say 'lots' I mean 'Player', which is the important one. Second, from what I remember, Player doesn't perform collision against moving objects, nor account for other objects' movement. It just collides against everything else assuming it's all static.
Honestly I'm not sure these are problems we can easily solve - we just need more fine-grained control over physics objects using Bullet or PhysX. For example, adding joints/constraints from script, applying forces continuously rather than just impulses, and collision callbacks.
09/08/2014 (2:49 am)
Ah, I see, that makes sense! But I actually believe it's just that enough people aren't making games with Torque period, doors or not :P.The collision issue is twofold, as far as I understand it. First you have lots of classes caching collision data (and cache invalidation is famously one of the two hardest problems in programming, along with naming things and off-by-one errors), though when I say 'lots' I mean 'Player', which is the important one. Second, from what I remember, Player doesn't perform collision against moving objects, nor account for other objects' movement. It just collides against everything else assuming it's all static.
Honestly I'm not sure these are problems we can easily solve - we just need more fine-grained control over physics objects using Bullet or PhysX. For example, adding joints/constraints from script, applying forces continuously rather than just impulses, and collision callbacks.
#6
And it would be awesome to see more people using Torque to make games. Too many people convinced that if you don't have HDR, bloom, etc. then you can't make a game with it. And with UE4 and CryEngine both at crazy low prices I can see why the crowd would shift that way instead - all the bling and only a small bite in the wallet. I guess "free and unencumbered" just isn't as attractive as I thought it was - or people are suspicious because TANSTAAFL....
09/08/2014 (8:13 am)
Well, Projectiles collide with Player and they're certainly moving objects. I believe you're right in that "static" objects are expected to be static. Perhaps we need another GameBase object that is intended for use with animated collision shapes and what not. And there we go with the "bunch of work" issue... lol. Not enough hands to do what needs doing.And it would be awesome to see more people using Torque to make games. Too many people convinced that if you don't have HDR, bloom, etc. then you can't make a game with it. And with UE4 and CryEngine both at crazy low prices I can see why the crowd would shift that way instead - all the bling and only a small bite in the wallet. I guess "free and unencumbered" just isn't as attractive as I thought it was - or people are suspicious because TANSTAAFL....
#7
To be honest (and I'm wary of dragging this thread off-topic) I think the main factor that makes people use (and stick with) UE and Unity is because they have large full-time well-respected dev teams working on them. You get support. We have... 6 guys who do this part time? Plus several prolific and proficient community members, of course, and I don't mean to demean their significant contributions. But these other engines have large communities that produce learning material, resources, plugins, etc. "Free and unencumbered" means nothing to your average game developer who just wants to make a game and have access to help while doing so, or the assurance that they'll see bugs fixed and features improved.
EDIT: I feel like we should probably make an effort to pull this thread back on-topic. I was planning on doing a doors implementation in Walkabout at some point, but I think this sort of thing would be best done in the open. I think the simplest case to focus on is making a collision object that can switch its collision on/off dynamically with no hangups. If we can make that happen, we'll be well on the way to simple doors - throw an animated shape over it and bang, you're away.
The only part about this, I think, that can't currently be done is the collision info change notification. We need to catalogue the various ways collisions are cached in the engine (the first place to look will be Player::updateWorkingCollisionSet, I think), and come up with a strategy for forcing those caches to be invalidated when relevant collision information changes.
Ideally we'd hook into the container/bin system so we don't need to notify everybody when somebody's collision changes, but that might be a valid first pass. Create a tSignal in ShapeBase, give it a script binding, and when a Player is notified of the signal, nuke the current collision set and recalculate.
09/08/2014 (3:40 pm)
Projectiles just raycast, and critically, they only raycast against collision geometry at the start of each tick. They don't account for, for example, the Player's velocity during the tick that the raycast represents. But my point was more like, consider two Players moving nearby each other. The engine freaks out a little bit in those cases because both Players treat the other as stationary, AFAIR.To be honest (and I'm wary of dragging this thread off-topic) I think the main factor that makes people use (and stick with) UE and Unity is because they have large full-time well-respected dev teams working on them. You get support. We have... 6 guys who do this part time? Plus several prolific and proficient community members, of course, and I don't mean to demean their significant contributions. But these other engines have large communities that produce learning material, resources, plugins, etc. "Free and unencumbered" means nothing to your average game developer who just wants to make a game and have access to help while doing so, or the assurance that they'll see bugs fixed and features improved.
EDIT: I feel like we should probably make an effort to pull this thread back on-topic. I was planning on doing a doors implementation in Walkabout at some point, but I think this sort of thing would be best done in the open. I think the simplest case to focus on is making a collision object that can switch its collision on/off dynamically with no hangups. If we can make that happen, we'll be well on the way to simple doors - throw an animated shape over it and bang, you're away.
The only part about this, I think, that can't currently be done is the collision info change notification. We need to catalogue the various ways collisions are cached in the engine (the first place to look will be Player::updateWorkingCollisionSet, I think), and come up with a strategy for forcing those caches to be invalidated when relevant collision information changes.
Ideally we'd hook into the container/bin system so we don't need to notify everybody when somebody's collision changes, but that might be a valid first pass. Create a tSignal in ShapeBase, give it a script binding, and when a Player is notified of the signal, nuke the current collision set and recalculate.
#8
[EDIT]
Really? My interpretation (reading it, not stepping through) is that if you're standing next to the door and it moves the collision doesn't happen right because it's already within the working query box and isn't updated correctly (updateSet isn't set to true). Am I reading that correctly?
09/08/2014 (4:35 pm)
Wait - what about basing a door on RigidShape? Still don't think it will work quite right when shoving a player out of its way though....[EDIT]
Really? My interpretation (reading it, not stepping through) is that if you're standing next to the door and it moves the collision doesn't happen right because it's already within the working query box and isn't updated correctly (updateSet isn't set to true). Am I reading that correctly?
#9
The working query box is part of the problem, but it's not the only reason we don't have animated collisions. The working collision set is used when the Player checks for collisions against other objects, i.e. when the Player is trying to move itself. If you want full door physics, you need to worry about what happens when another object, during its own move, comes into contact with the player.
Anyway, I think it'd be useful to have a full-on useful 'collision geometry update' system in place. It could be useful for a variety of situations. For example, the terrain modification resource I used in T3D has trouble with Player's cached collision info - if you dug a hole under a Player, they wouldn't notice unless they walked away and came back.
EDIT: also, this general collisiony problem stuff is the reason we don't have elevators, moving platforms, etc. in the engine, and why whenever anyone asks about it the response is 'well... uh... there was that old resource...?'
09/08/2014 (5:05 pm)
Yeah I'm pretty sure RigidShape doesn't apply any forces to Player. I did some work with this in TGE, but it was kind of wonky because what if, for example, a RigidShape pushes a Player into a wall? applyImpulse ain't gonna cut it.The working query box is part of the problem, but it's not the only reason we don't have animated collisions. The working collision set is used when the Player checks for collisions against other objects, i.e. when the Player is trying to move itself. If you want full door physics, you need to worry about what happens when another object, during its own move, comes into contact with the player.
Anyway, I think it'd be useful to have a full-on useful 'collision geometry update' system in place. It could be useful for a variety of situations. For example, the terrain modification resource I used in T3D has trouble with Player's cached collision info - if you dug a hole under a Player, they wouldn't notice unless they walked away and came back.
EDIT: also, this general collisiony problem stuff is the reason we don't have elevators, moving platforms, etc. in the engine, and why whenever anyone asks about it the response is 'well... uh... there was that old resource...?'
#10
That'd match my findings after tinkering with github.com/Azaezel/Torque3D/tree/Collission_Lods for a bit, yeah.
Presumably that'd also be why github.com/GarageGames/Torque3D/blob/69838bdc8c9bc055b9b1ae76f42b0f28d2a33909/En... is nonfunctional for all practical purposes.
09/08/2014 (5:27 pm)
Quote:Really? My interpretation (reading it, not stepping through) is that if you're standing next to the door and it moves the collision doesn't happen right because it's already within the working query box and isn't updated correctly (updateSet isn't set to true). Am I reading that correctly?
That'd match my findings after tinkering with github.com/Azaezel/Torque3D/tree/Collission_Lods for a bit, yeah.
Presumably that'd also be why github.com/GarageGames/Torque3D/blob/69838bdc8c9bc055b9b1ae76f42b0f28d2a33909/En... is nonfunctional for all practical purposes.
#11
09/08/2014 (5:50 pm)
Well, there's a big step between detecting collision of animated meshes and actually responding to them. For example, IIRC, if Player isn't moving in a tick, it won't really respond to being penetrated by another moving collider. It assumes other colliders will sort themselves out.
#12
edit: but yeah. just checking the state in time, while beneficial, would only be the first step. would also need to interpolate verts and derive the motion vectors to apply impulses.
09/08/2014 (6:02 pm)
Yep. That's why I used the term practical purposes. some shots of the problem for those playing the home game: imgur.com/WVJcIvF,f4VaEZB,XtVt4mO (note: set to visual collision, doesn't alter until you move the detection box out and back in)edit: but yeah. just checking the state in time, while beneficial, would only be the first step. would also need to interpolate verts and derive the motion vectors to apply impulses.
#13
09/09/2014 (10:19 am)
Well, we already have a "dirty list" attached to all NetObjects and this is the only place I can see an enum that defines dirty bits:// in tsShapeInstance.h, line 556
enum
{
TransformDirty = BIT(0),
VisDirty = BIT(1),
FrameDirty = BIT(2),
MatFrameDirty = BIT(3),
ThreadDirty = BIT(4),
AllDirtyMask = TransformDirty | VisDirty | FrameDirty | MatFrameDirty | ThreadDirty
};
U32 * mDirtyFlags;So, of the 32 bits available it looks like we're only using 5 and TransformDirty is one of them. Perhaps if we were to hook into this part of the system we could make this a little easier.
#14
Just a quick idea, didn't test it yet;
If you get the rotation of the door object and the rotation of player you could compare those two and play either animation thread. Especially when using collision you're already kind of bind to that 180 degrees.
Edit; and if the player is walking backwards you can switch that around...
09/10/2014 (2:14 am)
Good to see you back @Glennn,Just a quick idea, didn't test it yet;
If you get the rotation of the door object and the rotation of player you could compare those two and play either animation thread. Especially when using collision you're already kind of bind to that 180 degrees.
Edit; and if the player is walking backwards you can switch that around...
#15
I've honestly started to consider other engine alternatives as I continually run into issues with the engine (Whether it be collision or materials not functioning as intended). I've always believed that the Torque (Game) Engine since.. forever ago is a very powerful and dynamic engine and you can do quite a lot, but as a single developer I don't have the time to 'fix' what other engines do out of the box (I specialize in art, my coding isn't up to scratch to fix some of these issues)
I'm not suggesting that its a bad engine or the people working on it are lazy. But I personally feel that the engine is starting to fall behind which is unfortunate.
(Back on the subject)
Ironically, I found a fatal fall in my doors collision in its open and closed state, I found a way to basically walk through it via mashing the keyboard. So any improvements that I was hoping to 'move the player away from the door functionality' has stopped and go back to my original collision issues which I may or may not start a thread in the appropriate board.
09/10/2014 (5:40 am)
I've been meaning to reply to this thread but haven't for some reason. I think everything discussed is on point or close enough. I've honestly started to consider other engine alternatives as I continually run into issues with the engine (Whether it be collision or materials not functioning as intended). I've always believed that the Torque (Game) Engine since.. forever ago is a very powerful and dynamic engine and you can do quite a lot, but as a single developer I don't have the time to 'fix' what other engines do out of the box (I specialize in art, my coding isn't up to scratch to fix some of these issues)
I'm not suggesting that its a bad engine or the people working on it are lazy. But I personally feel that the engine is starting to fall behind which is unfortunate.
(Back on the subject)
Ironically, I found a fatal fall in my doors collision in its open and closed state, I found a way to basically walk through it via mashing the keyboard. So any improvements that I was hoping to 'move the player away from the door functionality' has stopped and go back to my original collision issues which I may or may not start a thread in the appropriate board.
#16
mmm, yes, you're right. It's pretty hard to really get things done on your own; but I believe that counts for any other game engine. It's very hard to make a game on your own... I tried to port the project to other game engines but bumped onto lots of issues with others as well. But that's for another thread I guess ;-)
The collision mesh needs to be thick enough, if it fits perfect around your door mesh and you can run through it (or get stuck in it), it probably isn't.
09/10/2014 (7:32 am)
Quote:but as a single developer I don't have the time to 'fix' what other engines do out of the box (I specialize in art, my coding isn't up to scratch to fix some of these issues)
mmm, yes, you're right. It's pretty hard to really get things done on your own; but I believe that counts for any other game engine. It's very hard to make a game on your own... I tried to port the project to other game engines but bumped onto lots of issues with others as well. But that's for another thread I guess ;-)
Quote: I found a way to basically walk through it via mashing the keyboard
The collision mesh needs to be thick enough, if it fits perfect around your door mesh and you can run through it (or get stuck in it), it probably isn't.
#17
09/10/2014 (8:29 am)
A simpler approach would be to put a trigger over each door and use that to open it. If the trigger is large enough the player can't get close enough to the door before it opens to encounter these issues.
#18
09/10/2014 (9:43 pm)
My current door system has heaps of states, including being locked so I can't avoid the problem by just opening the door. I will try out thicker collision for the doors however, interesting to hear that can even be a problem.
#19
So to use a common problem: If you're moving real quick, and outside in one direction before the check, but inside more than halfway through the mesh the next time it checks, most aren't smart enough to dial you back to the last place, they instead spit you out the other side. (and if you're really going quick, it doesn't even have time to see that you were inside at any point).
wiki actually has a relatively decent writeup on the topic: en.wikipedia.org/wiki/Collision_detection#A_posteriori_.28discrete.29_versus_a_p... (torque baseline physics uses the a posteriori method with a bit of a priori for interpolation, for context)
09/10/2014 (9:59 pm)
Thing to remember about 99.9% of the collision systems out there (and particularly the ones with networking) is they're essntially based on comparing whether you've gone from being outside an object the last time the physics checked to inside it, and if so, acting on that info. So to use a common problem: If you're moving real quick, and outside in one direction before the check, but inside more than halfway through the mesh the next time it checks, most aren't smart enough to dial you back to the last place, they instead spit you out the other side. (and if you're really going quick, it doesn't even have time to see that you were inside at any point).
wiki actually has a relatively decent writeup on the topic: en.wikipedia.org/wiki/Collision_detection#A_posteriori_.28discrete.29_versus_a_p... (torque baseline physics uses the a posteriori method with a bit of a priori for interpolation, for context)
#20
09/10/2014 (11:36 pm)
You could do the Battlefield:Bad Company thing: To pass through door, destroy the door.
Torque Owner Daniel Buckmaster
T3D Steering Committee
I also agree this is a fairly embarrassing problem that nobody's ever really solved in the engine. Just goes to show how small and insular the community around the engine is.