Smooth Looping Escalator

I created a model in Blender to replace a func_tracktrain based escalator in my map TTT_Nuclear_Power:

I animated it by having the steps move one step length and looping the animation, basically “teleporting” back into place to create a smooth loop. It uses two bones - one for the lower and top part that move straight forward, and one for the angled part that moves diagonally. It looks smooth in Blender but in Garry’s Mod there’s a fast “jump” in the animation when it loops that quickly moves the step backwards into place rather than “teleporting” back to the first frame at the end of the loop. I assume this is because the Source Engine interpolates the movement between the last and first frame of the loop.

I know most looping animations have the model return to it’s original position at the end of the loop, however that’s not really possible in my case. Is there any way to fix this jump? Can I get it to abruptly restart the loop at the first frame of the animation rather than have it jump back?

If there’s a seperate ‘stopped’ idle animation, replace it with the moving animation. If you need to, name the stopped animation something else.

I’m not sure I understand. It has an “idle” animation just as any Source model does but it’s a prop_dynamic that’s constantly playing a moving looping animation and “jumps” back when the loop repeats.

[editline]17th September 2017[/editline]

Alright I got it not to jump at the transition by defining “snap” in the model’s QC instead of “loop” (prop_dynamic will still loop the animation over and over) but now the model has a little pause every time the loop repeats. Maybe there is some way I can tweak this…

[editline]17th September 2017[/editline]

Okay this is strange, it has no pause at all in the model viewer or in Hammer with “snap” defined in the QC instead of “loop”, but in-game it does. I’m still stuck on this…

Disable fadein and fadeout in the qc.

I believe it has 0.2 as standard?

Would I disable it by adding ‘fadein 0 fadeout 0’ to the sequence’s line in the QC? It doesn’t seem to affect anything when I try that.

Here is the sequence in the QC with “fadein”/“fadeout”:

$sequence "up_once" "up.smd" fadein 0 fadeout 0 fps 24

Here is the sequence using “snap”:

$sequence "up_once" "up.smd" snap fps 24

Both perform the same exact way, with a little pause at the end of the loop before the animation restarts. This is really frustrating!

When I was doing something similar for another game engine I couldn’t completely get rid of the interpolation either. What I did was make the teleport happen right before the loop restarted, so basically I shifted the entire animation back one frame and then I made the curves completely vertical so there was no interpolation in Blender.

I believe if you have the 3D program do the stepping/teleporting from one frame to the next within the animation rather than the start and the end, you won’t have to mess with the interpolation, although with your current version you say there’s a little “pause” at the end. Are you sure that’s not because you accidentally made it last 2 frames by having a duplicate frame at the beginning and the end?

I’ll experiment with this, but with the “teleport” built into the animation, wouldn’t the engine still linearly interpolate motion between the two frames and still appear to quickly move back? After all, animation frames are not like video frames and the engine still interpolates everything in-between.

But no, I checked the animation SMD in a text editor and I do not have any duplicate frames. In-game it moves one whole step length, pauses for a split second, then restarts the animation with the steps in their original position. It looks smooth in Hammer and in the Model Viewer, but has this pause in-game. Very strange.

As far as I know most engines will use the interpolation style you define between frames in your 3d application and only mess with frame blending where you can’t define it, such as between loops and switching between animations.

I think if that weren’t the case then animations with things like ease in and ease out that don’t actually use extra keyframes wouldn’t be read in the engine, but they are, so I’d definitely give that a try.

In any case, let us know how it works out.

Ok, I will give that a shot later tonight!

But opening up the exported animation SMD in a text editor, it looks like it is simply a collection of position and rotation data for every bone each frame of the animation. I think even if you have only a few keyframes in your animation in Blender with any type of interpolation, when it exports to SMD it writes a keyframe for every single frame of your animation and the game engine linearly interpolates between them. So basically, your ease-in/out interpolation in Blender would look better or worse based on your frame rate since a high frame rate would add more “resolution” to your animation? Am I getting this right?

I appreciate all of your guys’ help. This is helping me learn a lot in a short amount of time!

Nah, you’re right, it just linearly interpolates between frames, and of course easing in and out works because there are keyframes to read at several points that make it look right.


[editline]17th September 2017[/editline]

Ah okay, I got it this time. Sorry, I didn’t realize you said the problem was only in-game. I experienced the same things you mentioned after spawning it in Garry’s Mod

Like Sreap said, you do in fact need either snap or fadein 0 fadeout 0, but in order to get rid of those stupid pauses you also have to add the realtime command apparently.

I was scrolling through the QC commands and it didn’t really sound like it’d work, but I guess that fixes it.

$modelname	"risenshine\escalator.mdl"
$body mybody	"escalator.smd"
$surfaceprop	combine_metal
$cdmaterials	"models\risenshine"

$sequence idle	"anims\escalator_idle.smd" fps 60 snap realtime

$collisionmodel	"escalator.smd" { $concave }

That fixed it! Thank you so much!

You’re right though, it doesn’t sound like it should fix it:

Any idea what this is actually doing? I’d just like to understand it a little better. It can’t be ignoring the sequence’s fps if it’s playing correctly. What is it referring to as far as the global clock?

I think what it means is that it doesn’t go by the internal cycle of the animation, but rather it calculates which frame to be on depending on either the player’s computer clock or how long the server’s been running, so since it does that then it never really transitions/blends into itself, it just calculates the next frame to go to based on the system time alone. So without the transition of reloading the animation and with interpolation turned off, it just goes straight to the next frame like it’s supposed to.

That’s my guess anyway, and I can’t imagine that’ll ever really be useful except in this strange situation to be honest hahaha

That seems logical enough to me. Just so long as it doesn’t act strange when the map is running on a server or add any network overhead. But I can’t imagine it would?