Designing Pickup Animations for Murder 4 (Patreon)
Content
Pickups in VRChat are typically simple physics objects. They don't even use interesting first-person animation like FPS games. In desktop mode, there’s only one animation for “holding” a pickup, where your avatar’s right arm is outstretched and the hand is in a neutral position. If your avatar doesn’t have arms, the pickup just floats there. In VR, you have hand tracking, so it’s a little more interesting-- but the pickup is still locked in a fixed position in your hand. While making Murder 4 and some other side projects that include guns/melee weapons, I realized that I could add some animations to pickups to make them move around in your hand under certain conditions, making them look a little more interesting whether you’re in VR or on desktop.
At first this idea might seem impossible if have a basic understanding of the VRChat SDK. VRChat don’t let you actually adjust the configuration of the physics joint that holds pickups in your hand. It also doesn’t let you add extra animation to your avatar’s hand or arms… at least not today. So what I’ve done is just animate the geometry of the pickup while your actual hand stays in place. The end result is not visually perfect by any means- the pickup clearly deviates from your hand and it can look a little weird. But for desktop players, I would say anything is better than the default stiff-right-arm pose. For VR players, I think this effect should probably be limited to short recoil animations for firearms, since you don’t really need it for melee weapons.
Here’s a look at how the pickup is set up in order to achieve this effect. Essentially the core geometries of the pickup are split among several children, whereas an ordinary pickup without animations might be composed of just one object.
Every pickup needs a VRC_Pickup on the root object in the hierarchy. The root object must also have a collider which defines where your hand or mouse cursor needs to be hovering over in order to select the pickup. I usually use a large, round collider with isTrigger enabled so you can just aim in the general vicinity of the pickup and still be able to grab it. This large collider doesn’t actually affect how the object collides with the walls and floors of the world or anything, it’s just for selecting and grabbing.
The actual visuals for the revolver are a child of the root object. This way, I can animate the sub-object and play an animation for just the geometry in local space relative to the root. That is to say, no matter the position and rotation of the root pickup (or what it’s attached to), a “recoil” animation will always go “up and backward” based on wherever the pickup is located and rotated. If I just animated the root, it would always play back the animation in the same position relative to the world (in this case the revolver’s spawn point, or to coordinates 0, 0, 0 depending on how I set it up)… and we don’t want that. It wouldn’t even work if a player was holding the pickup, anyway, because VRChat would always force the root to snap to the player’s hand, and face directly forward.
The collision geometry for the actual gun is actually not attached to the recoil animation. Instead, they are children of the root with the “selection” collision, and therefore siblings of the animated geometry. This is because I don’t want them to have any influence on the hovering/selection of objects in VRChat and I don’t even need the recoil to affect them. These colliders affect how the pickup collides with the world collision like floors, walls, stairs, other pickups, etc. Yes, that means when an animation is playing, the geometry might clip through walls, but in this example that’s okay. I’ve tried animating the collision geometry for large melee weapon like axes and swords, but when the animated collision hits walls, it’s a little janky because the pickup really, really wants to keep its physics position fixed in place. If you’ve ever tried sticking a large pickup through a wall in VRChat, you know what I’m talking about, but imagine it’s even more jittery because an animation trying to force it through the wall instead. Oh, and if the colliders are children of the root, I can do stuff like rotate a box collider, as shows in the handle of the revolver above.
Anyway, on to the actual animation. Murder 2 had a “firing” animation that flashed a light source and a muzzle flash mesh when you shot the revolver. In Murder 4, I’m using a “Recoil” animation that does something similar. The revolver and muzzle flash have new meshes, textures, and shaders. There is no dynamic light anymore and the muzzle flash material is opaque-- for better quest optimization.
The firing/recoil animation just needs to do two simple things. One is to kick back the revolver (making it look really powerful) with a delayed, but snappy recoil that resets naturally and quickly enough to match the firing speed delay that we’re all used to from Murder 2. It also needs to make the recoil appear for just a flash, disappearing before the gun rotates too far (otherwise it would look weird, seeing rotated muzzle flash) with a bit of stretch-and-squish like it’s a growing ball of fire or something.
The first step was to roughly plan out the timing. Sort of like a storyboard. I made four keyframes for the recoil transform: the beginning, the end (which had to match to make it loop correctly), one frame about 10% of the way through for maximum recoil, and one frame about 40% of the way through for when the kick-back was finished and ready to transition back to normal. I already knew the animation would be 1 second long, but for other types of animations this is also a good time to make sure that the length of the whole timeline feels right. You can easily scale the playback rate during the game to adjust for game balance and stuff, but not when you’re authoring in the animation editor window unless you want to fiddle with scaling keyframes.
After that I’ll swap back and forth, messing around with position and rotation frames. I find that to illustrate more realistic weight and momentum, rotation keyframes are almost slightly delayed from the position keyframes. This gets kind of annoying when you’re making looping animations, since most animation editors make it really easy to adjust the start and end frames to make them match, but this recoil animation doesn’t need to preserve any momentum when the end of the animation loops back to the beginning, it just has to match so there isn’t any snapping.
As you can see, the rotation is delayed- the position is already halfway kicked back before the gun rotates upward. Then, for a decent chunk of time, the position stays kicked back and the gun stays pointed up-- wow, that’s some powerful recoil, it’s like the user’s hand is pushed back as far as it can go! Then as the position slides back to normal, the rotation is delayed just a little bit, but it’s really fast. Like the tip of the gun is playing catch-up to snap back down to a neutral position. But it overcompensates! Maybe the tip of the gun is pretty heavy, so it bounced way below the horizon line. Now it has to settle back upward. Basically, the story behind this animation is “I was surprised by how powerful this was-- my hand jolted back for just a moment, but the tip of this revolver went wild and it’s kinda hard to point it straight again!
The muzzle flash part of the animation is really short because it needs to be finished before the recoil rotates the gun upward. For just a one or two frames, the muzzle flash grows really huge. But instead of a simple scale up and down, it stretches forward almost like it’s squeezing out of the gun.
Another great thing about adding filler objects to the hierarchy means I can easily swap out the geometry of the gun and use the same animation for recoil and muzzle flash-- even if the gun is a different size or the muzzle flash appears in a different position.
The knives have a stabbing animation, which plays automatically when you run through someone in murder, but it could definitely be used on a click-trigger for desktop users for other types of melee combat games. I'm thinking of adding a "spinning" animation when you throw the knife and it's flying through the air.
I hope you liked this little preview of the new weapons and how the "first person animations" are coming along. You're welcome to ask questions in the comments or in the #backstage-pass channel on the discord server. Let me know what you want to see next!
-Jar