Game Development Community

An alternative to PathShape

by Michael Reino · in Torque 3D Professional · 05/28/2014 (8:28 pm) · 14 replies

I started out intending to look into the widely reported jittering issue with the PathShape resource. I never really got very far into it. It's really two resources rolled into one. It provides a shape class that can be moved along a predefined path and the ability for players to walk on the shape while it's moving. I decided to separate those two features so I could look at the jittering issue in isolation from the classes providing movement. I also wanted to see if I could recreate the functionality without modifying core engine files (...I couldn't, but they have been reduced). After a failed start, two re-writes and many hours analyzing debug spew, I finally have some code to share. You can get it here:
github.com/OTHGMars/Torque3D/tree/walkable_shapes

In Brief...

I'm calling this resource WalkableShapes (I'm open to suggestions for better class names). It provides three classes that can be used in games. TSPathShape is a simple path following shape. TSAttachable builds on TSPathShape to add the ability for players to walk on the shape while it's moving. The script interface for this class is almost identical to the traditional PathShape. The setup is slightly different. Since the DataBlock has been eliminated, the shape file is set in the editor. The WalkableShape class is a simple shape object that players can walk on while it's moving. It provides no movement of it's own, but can be mounted to...Anything! So if you want to walk on the back of a flatbed truck, model the bed as a separate shape and mount it to the truck in game as a WalkableShape. It can be mounted to any shape that provides movement. There is a demo level included that has a platform-jumping mini-game and a Cheetah with a platform mounted to the roof where the turret normally mounts. You'll need two connections to try that though.

It's still a work-in-progress. Anyone that wants to contribute changes or suggest improvements, please do so.

Testing in other builds

This resource should be compatible with all of the MIT T3D builds and possibly earlier. If you test in another build, please post your results here. To add to another build, you'll need the three engine changes, here, here and here. There are 8 new source code files that need to be included in your build. They do not need to be in the T3D directory. They can be compiled from your project/source directory for easy testing and removal. You'll also want to add the script files and demo level.

The Class Details

TSDynamic (tsDynamic.h, tsDynamic.cpp)
I wanted to base my path shape off the TSStatic class because it is so simple and lightweight, but unfortunately it wouldn't work well because it's networking was designed to be static and doesn't pack updates to clients efficiently. TSDynamic is just a renamed copy of TSStatic with a couple very minor modifications.

TSPathShape (tsPathShape.h, tsPathShape.cpp)
This class duplicates the movement features of the PathShape resource with none of the attachment code. All of the console methods are backward compatible with PathShape so it will be simple to modify existing scripts. It can handle looping paths without stopping on the last node and waiting to be restarted from script. I added a console method setLooping() so that can be turned on or off from script. I also added an onTargetReached() callback.
This can be a handy class for simple moving objects like a door that swings or slides. Motion can be started and stopped from script and it will fire callbacks when destinations are reached. It can also stop ticking when not in motion, making it almost as lightweight as a TSStatic when parked.

TSAttachable (tsAttachable.h, tsAttachable.cpp)
This class inherits TSPathShape and provides all of the attachment functionality of the PathShape resource. Three console methods have been added for managing the attachments, attachObject(obj), detatchObject(obj) and detachAll(). Any SceneObject derived class can be attached.
Two console variables have been added: UseAutoAttach (Bool) When this is true it will scan for objects directly above it and automatically attach any that are found. When false, objects must be explicitly attached from script. RayLength (F32) This is the length of raycast directly below attached objects when checking to see if they have fallen off. This is also the distance above the shape to scan when using auto-attach.
Two callback methods onObjectAttached(obj) and onObjectDetached(obj) have been added to provide a script notification anytime an object attaches to or detaches from the shape. These callbacks fire even if the object was manually attached from script.

WalkableShape (walkableShape.h, walkableShape.cpp)
This class provides the identical script interface as TSAttachable based on a TSDynamic object instead of TSPathShape. This class really renders TSAttachable obsolete since you could mount a WalkableShape onto a TSPathShape and get an identical result (from the users perspective). I have left TSAttachable in the resource since it's the replacement for the shape provided by the original PathShape resource.

The Jitters

There were a number of issues trying to synchronize a local client player object with a moving shape. A pathed shape that can tick it's position on the client was a great shape to test against. It knows precisely where it's supposed to be at every tick. The Player is interpreting a move locally and periodically (every readPacketData()) synchronising it's position with the server. That subtle adjustment becomes a huge jump when riding at high speed on a shape when the player is warped to the server location. This is the lone reason engine changes were required for this resource (the CameraSpline change is purely cosmetic). The Player class needs to know it's attached and bypass the warp in readPacketData() and unpackUpdate(). That warp is crucial though. The player needs to represent location and orientation correctly on the client or your bullets won't go where you aimed. So the walkable classes update the players position in local coordinates and rotation relative to the shape they're mounted on at the same frequency that they'd get adjusted in readPacketData(). If the shape they're on warps, they warp with it.

Areas that need improvement
The base class needs a collision callback to script. Other object types need tested and adjustments made. I imagine a vehicle as the control object (car on ferry deck?) would have the same jitter issue from warping and need a similar fix.

#1
05/29/2014 (6:24 am)
Excellent!
#2
05/29/2014 (10:57 am)
Loving the bifurcation of functionality, as well as the bit about keeping the attachment check enclosed in the class it's-self. Much, much cleaner.

Do still seem to be getting interpolation errors for a client attached to TSAttachable when not hosting if that client moves, but not when it's immobile, so likely something still a bit twitchy in either moveAttachments, moveRenderedAttachments, or write/readPacketData. (note: rotation counts as movement for purposes of the report.) Pretty much the opposite problem as the other one (There players specifically were jittery, with everything else being solid) unless we weren't testing at sufficient speeds.
#3
05/29/2014 (11:33 am)
I tried it out, works quite well. Only sort-of bug I found was when I was flying around on one of the saucers bouncing grenades off the other saucers there was one or two times I hit where the saucer used to be and the grenade still bounced off it. It could just be hitting a part of the saucers collision box I don't see or something.

Regardless of that, it's pretty awesome.
#4
05/29/2014 (12:27 pm)
Followup report:

Net-test, myself hosting, andrew joining.

Testing procedure 1 - Me on saucer, him on ground. I move, smooth motion for both.

Testing procedure 2 - Andrew on saucer, myself on ground. He moves, smooth motion from my POV, jitter his end when he was in motion.
#5
05/29/2014 (12:57 pm)
Thanks for the testing reports. There's probably a problem with how the rotations are being combined in moveRenderedAttachments(). I'll have to reexamine that. Having the code isolated like that makes it easier to throw out and try new things. Can you confirm that the jitter seen was rotational error only?
#6
05/29/2014 (1:14 pm)
Translation and rotation. Mentioned rotation explicitly because it didn't seem there was a case where that was handled when examining https://github.com/OTHGMars/Torque3D/commit/775f45a5df85244601ae0b3d12f4baec7a59eeec (that, and the values are packed and sent separately rather than ghosting the whole transform matrix.)

eidt: If you want, both of us spend quite a bit of time on widget00.mibbit.com/?settings=4c4bdb0c9496a9cc6a3575af8756f5e4&server=irc.ma... and today at least I've got a couple more hours of down-time.
#7
05/29/2014 (1:53 pm)
I'm also wondering if there isn't some jitter coming from the pathshape itself (output of CameraSpline::value()). An important observation is if there is any jitter relative to the shape you're on vs. an unattached shape. When riding on a Cheetah driving in circles, it seemed the rotational interpolation was smoother than on the pathshape, but that could be because the speed of rotation was not as high.
#8
05/29/2014 (2:09 pm)
Just a gut feeling there I'm afraid, and not a code-line yet, but I do find that somewhat doubtful due to the lack of jitters when standing stock still on a moving object. That and that the shape it's riding seems to jitter for a client connecting to a host when you alter that client's transform via movement when using the simpler testcase of spawning a second application and lan-connecting.
#9
06/01/2014 (2:03 pm)
This is great news indeed!

Well done Michael, I tried it out and looks nice and smooth. The mini game demo is great :)

Going to take out PathShape from my build tonight and replace it with this, much better...

Only thing I would suggest is a hook into the editor so you could add a new TSAttachable easily from there, as opposed to having to script it into the mission file. Unless this is already there and I missed it.

Also, I saw that you have different speed settings in the path markers - does this mean we can speed up and slow down the shape as it moves around? If so very cool.

Again, excellent job!
#10
06/01/2014 (7:03 pm)
So if I were to add this to a tank, players that jump on top of it could surf on it?
#11
06/01/2014 (7:08 pm)
There is still an issue with jittering on a remote client. Only now it's rotational instead of positional. There will be updates to that branch over the next couple days while resolving the remaining issues.
#12
06/01/2014 (7:10 pm)
@Chris Yes, but you would have to model the tank such that the surface you want to surf on was a mesh in a separate shape file. Then mount it to the tank as a walkable shape.
#13
06/02/2014 (3:47 pm)
There is an update in the branch that reduces back-stepping of rotation on remote clients.

@Paul - Yes you can modify the path speed at each node. I didn't change anything there. That was part of the original resource. I was going to hold off on editor modifications until we see what changes come out of the assimp branch for adding shapes. Here is a quick-n-dirty editor mod you can use in the meantime... github.com/OTHGMars/Torque3D/commit/6da122e18d32be3d766eaa42e81ad0f5ff526463
#14
06/02/2014 (4:15 pm)
Thanks for the link... I had actually gone ahead and figured out a simple hack myself lol but will check that out.

Really liking the new pathshapes... Having fun making banked roller coaster rides right now :)

Can't believe this is finally solved, those jitters were really annoying, and this new solution with the walkable shapes as well as attachable pathshapes adds a whole new range of possibilities.

Excellent excellent job, great work!

Cheers
P