Creating a door trigger
by Justin Knight · in Torque 3D Professional · 02/10/2010 (1:03 pm) · 18 replies
Someone was asking how to create a trigger to open an animated door.
Only thing I'm not sure about is how to get collision working with the door. As I understand it staticshape doesn't support polysoup and TSStatic doesn't support animation. Someone once told me you can define a collision volume that is associated with the mesh in 3dsmax - is that the best solution and can anyone explain how to do that?
Mini-tutorial
The door needs to be added to the scene as a StaticShape since TSStatic objects don't support animation. Create a StaticShape datablock like this and add it to the bottom of art/datablocks/managedDatablocks.cs:
If you restart the world editor you should now find your door under Library->Scripted->StaticShape->doorDB, double click it and it will add your animated door mesh into the scene as a staticShape. Give it a name such as 'testDoor'.
In the shape editor create two animation sequences called 'open' and 'close' showing the relevant parts of the animation. There's an animated door here to play with (doesn't include any collision volume unfortunately):
torque.abigholeintheweb.com/public_system/useruploads/max9_animated_door_example...
In art/datablocks/triggers.cs add a door trigger.
Add a scripts/server/door.cs file like this:
In scripts/server/scriptExec.cs add a line to include your new script:
In the scene tree in the T3D world editor select Level->Level->Trigger to add a new trigger. Call it what you want and select 'DoorTrigger' to be the datablock.
Move and scale your trigger volume to the desired size, you want it to cover the area infront and behind your door. In the world editor set 'doorRef' to be 'testDoor' - this is what wires the trigger up to the door.
The door should now open when the player enters the trigger area and close after they leave it.

Only thing I'm not sure about is how to get collision working with the door. As I understand it staticshape doesn't support polysoup and TSStatic doesn't support animation. Someone once told me you can define a collision volume that is associated with the mesh in 3dsmax - is that the best solution and can anyone explain how to do that?
Mini-tutorial
The door needs to be added to the scene as a StaticShape since TSStatic objects don't support animation. Create a StaticShape datablock like this and add it to the bottom of art/datablocks/managedDatablocks.cs:
datablock StaticShapeData(doorDB)
{
shapeFile = "art/shapes/door/mesh.dts";
category = "StaticShape";
};Change the shapeFile line to point to the path to your DTS.If you restart the world editor you should now find your door under Library->Scripted->StaticShape->doorDB, double click it and it will add your animated door mesh into the scene as a staticShape. Give it a name such as 'testDoor'.
In the shape editor create two animation sequences called 'open' and 'close' showing the relevant parts of the animation. There's an animated door here to play with (doesn't include any collision volume unfortunately):
torque.abigholeintheweb.com/public_system/useruploads/max9_animated_door_example...
In art/datablocks/triggers.cs add a door trigger.
datablock TriggerData( DoorTrigger) {
tickPeriodMS = 1000;
};This will test once a second if the player is in the trigger area. You can adjust the tick period if you've got a particularly fast or slow player.Add a scripts/server/door.cs file like this:
function DoorTrigger::onEnterTrigger( %this, %trigger, %obj) {
echo("Entered DoorTrigger");
%trigger.doorRef.playThread( 0, "open");
}
function DoorTrigger::onLeaveTrigger( %this, %trigger, %obj) {
echo("Left DoorTrigger");
%trigger.doorRef.playThread( 0, "close");
}You can remove the echo statements for production code. This code opens the door when the player enters the trigger area and closes it when they leave.In scripts/server/scriptExec.cs add a line to include your new script:
exec("./door.cs");In the scene tree in the T3D world editor select Level->Level->Trigger to add a new trigger. Call it what you want and select 'DoorTrigger' to be the datablock.
Move and scale your trigger volume to the desired size, you want it to cover the area infront and behind your door. In the world editor set 'doorRef' to be 'testDoor' - this is what wires the trigger up to the door.The door should now open when the player enters the trigger area and close after they leave it.

About the author
#2
Hey im probably resurrecting a old thread now but there i just one little thing i don't get and thats when you say:
"In the world editor set 'doorRef' to be 'testDoor' - this is what wires the trigger up to the door."
I have no clue what so ever what i need to name or link to what doorref appear twice in the code yes however it does not appear anywhere in the editor so where am i supposed to change it to testdoor?
Just need a little clarification.
Best regards
/Jonas
07/16/2010 (1:36 am)
Im getting desperate in finding a "door" i have been looking over the forums for 3 days constant and this is the only viable option for me some please give me a response.Hey im probably resurrecting a old thread now but there i just one little thing i don't get and thats when you say:
"In the world editor set 'doorRef' to be 'testDoor' - this is what wires the trigger up to the door."
I have no clue what so ever what i need to name or link to what doorref appear twice in the code yes however it does not appear anywhere in the editor so where am i supposed to change it to testdoor?
Just need a little clarification.
Best regards
/Jonas
#3
@Jonas - testDoor is what I called my door in my mission. i.e. in the inspector in the world editor set name to be testDoor. Then once you've added your trigger select it in the inspector, scroll down to the section that says 'Dynamic Fields' and click the '+' to add a new field. Set the left hand key to be 'doorRef' and the right hand value to be 'testDoor'.
07/16/2010 (7:30 am)
@PGames - I haven't used PhysX before but I vaguely recall seeing forum posts about triggers not working with PhysX objects.@Jonas - testDoor is what I called my door in my mission. i.e. in the inspector in the world editor set name to be testDoor. Then once you've added your trigger select it in the inspector, scroll down to the section that says 'Dynamic Fields' and click the '+' to add a new field. Set the left hand key to be 'doorRef' and the right hand value to be 'testDoor'.
#4
Thanks for the clarification and overall its a great quick tutorial!
Best regards
/Jonas
07/16/2010 (7:43 am)
Ah i see, ye i got it working now!Thanks for the clarification and overall its a great quick tutorial!
Best regards
/Jonas
#5
You use a StaticShape for your door, just like you do here. Create the collision mesh(es) as big as your trigger would be.
When you collide with the StaticShape you get a callback in StaticShapeData::onCollision . Here, play the opening animation and simply hide the collision mesh(es) much like you'd hide any submesh of a shape.
Schedule a check for any players nearby in t secs. If there are none nearby, play the closing aniation and unhide the collision mesh.
Hiding/showing the collision mesh has the advantage of not having to update the collision geometry for the shape, yet it will behave as if you did.
07/19/2010 (11:00 am)
Just wanted to add another method that doesn't use triggers.You use a StaticShape for your door, just like you do here. Create the collision mesh(es) as big as your trigger would be.
When you collide with the StaticShape you get a callback in StaticShapeData::onCollision . Here, play the opening animation and simply hide the collision mesh(es) much like you'd hide any submesh of a shape.
Schedule a check for any players nearby in t secs. If there are none nearby, play the closing aniation and unhide the collision mesh.
Hiding/showing the collision mesh has the advantage of not having to update the collision geometry for the shape, yet it will behave as if you did.
#6
07/20/2010 (11:15 am)
That is a nice solution Konrad.
#7
How do you hide the collision mesh from script?
is it via setmeshhidden?
I clearly prefer this solution as once your model is setup, you setup have to put doors on your mission map and the script will work for all doors.
07/21/2010 (5:41 pm)
@Konrad,How do you hide the collision mesh from script?
is it via setmeshhidden?
I clearly prefer this solution as once your model is setup, you setup have to put doors on your mission map and the script will work for all doors.
#8
Exactly, you can just throw all the doors down and they all work instantly.
Edit: Another bonus is that you can scale the door and the collision will scale to it. If you want to make use of this, make sure you take scale into account when scanning for nearby players before closing it.
07/21/2010 (5:45 pm)
Yes, setMeshHidden. Hide the mesh called "Collision". (The different numbers after are treated as (negative) LODs). So with this method, you will hide every collision mesh on the shape.Exactly, you can just throw all the doors down and they all work instantly.
Edit: Another bonus is that you can scale the door and the collision will scale to it. If you want to make use of this, make sure you take scale into account when scanning for nearby players before closing it.
#9
07/21/2010 (6:15 pm)
I use a raycast interact method so as to not deal with extra triggers, but Konrad's suggestion to hide/unhide the Collision mesh is something that didn't occur me -- excellent idea!
#10
My goal was to have a very simple door system that lets players go as soon as the door opens - much like when you're waiting in a Battleground in WoW behind the closed gates. You keep pushing onto the gate, and the second it lets you go, you start moving right away. This was the simplest method that let me do this.
07/21/2010 (6:20 pm)
Thanks Michael! :)My goal was to have a very simple door system that lets players go as soon as the door opens - much like when you're waiting in a Battleground in WoW behind the closed gates. You keep pushing onto the gate, and the second it lets you go, you start moving right away. This was the simplest method that let me do this.
#11
What's faster in term of CPU charge: Ray cast or collision?
Sometime, depending of your game design, you need to find "time" for other function. This might help to make a choice.
07/21/2010 (6:47 pm)
May be outside of the initial subject:What's faster in term of CPU charge: Ray cast or collision?
Sometime, depending of your game design, you need to find "time" for other function. This might help to make a choice.
#12
I've not taken the time to test which was quicker, ray cast or collision -- although both are negligible if managed properly. For me it was simply a question of how I wanted to interact with a door object. Using a collision callback would simply cause something to happen if you ran into it -- get close enough and the door opens just like the automatic doors at the supermarket. I chose a ray cast to see what the player is looking at, and if he is looking at a door then open it (with appropriate animations if applicable).
07/21/2010 (8:00 pm)
@elvince:I've not taken the time to test which was quicker, ray cast or collision -- although both are negligible if managed properly. For me it was simply a question of how I wanted to interact with a door object. Using a collision callback would simply cause something to happen if you ran into it -- get close enough and the door opens just like the automatic doors at the supermarket. I chose a ray cast to see what the player is looking at, and if he is looking at a door then open it (with appropriate animations if applicable).
#13
That being said, like Michael stated - if used intelligently the different isn't important enough to matter.
07/21/2010 (10:41 pm)
A ray-cast will be, in most cases quicker, and any kind of complex object (convex hulls and up) generally use multiple ray-casts in their collision determination. And indeed even simple shapes (say, a sphere->sphere) when moving use effectively the same code as a simple ray-cast.That being said, like Michael stated - if used intelligently the different isn't important enough to matter.
#15
You have helped me figure out how to in general, I must now get it to work. so for the door object i will now have to code a unique control to be clicked on correct.
11/27/2011 (2:10 am)
Wonderful code, I was wanting to have the player click on the door to open it, yet after player has gone through the door way close the door.You have helped me figure out how to in general, I must now get it to work. so for the door object i will now have to code a unique control to be clicked on correct.
#16
http://www.garagegames.com/community/forums/viewthread/128726
11/27/2011 (6:03 pm)
This may be of interest to some of you:http://www.garagegames.com/community/forums/viewthread/128726
#17
02/13/2012 (10:47 pm)
brilliant - thanks guys.
#18
02/14/2012 (5:19 am)
You can use the trigger's onLeaveTrigger() callback to close the door behind you, or simply schedule the door to close again after it has been opened.
Torque 3D Owner PGames
In 1.0.1 I traced it back to this code in player.cpp:
if ( mPhysicsPlayer ) mPhysicsPlayer->findContact( &contactObject, contactNormal ); else _findContact( &contactObject, contactNormal );The trigger code is in _findContact(), but the player is a PhysX object so findContact() (without the underscore) is called instead. So I figured that maybe this had been fixed in 1.1, and it turns out that it has to some extent, but the error is now in a different place. The call to the trigger code was refactored out of _findContact() and into a universal findContact() function from which the other two findContact() functions are called. Here is the call to the PhysX player:
It gives us a list of objects that are overlapped by the player object, which it looks in to see if the player is physically overlapping a trigger object. This is all well and good, except that overlapObjects is never filled in when it's passed into the PhysX player's findContact() function.
Anyone know how to fix this? Am I misunderstanding the code?