Playing satisfying audio clips

Below you can hear the audio sound that is played. Satisfying.

Your browser does not support the audio element.

Jiggling with animation layers

When you create a jiggle animation, you'll need to have an animation that can show the balloon jiggling without overriding any other animation states that are currently being used. For example we can used Unity's Mechanim to create animation layers to have the states blend. Say that you have an animation that stretches the balloon out one way or another and you also want to control when it jiggles separately. Well you can do that with layers. Since we're going to control jiggling independently of other animation states, we put it on it's own layer, and set it as an additive layer. We can then choose how much of that layer is blended.

If we only ever have one continuous jiggling animation, we can make the balloon infinitely jiggle on this layer and then change the layer weight to control how much jiggling gets blended in to the end result. This can be accessed and changed at runtime through code but above we can see the effect it will have by using the UI.

I'll show you our update loop for the balloon and you can see how we determine how much and how long we want to jiggle it.

Update() - Part 1 - Jiggle weight void Update() { if (!popped && !thrown) { //calculate velocity and acceleration current_pos = transform.position; current_vel = (current_pos - last_pos) / Time.deltaTime; accel = (Vector3.Distance(last_vel, current_vel) * accel_factor) / Time.deltaTime; //Jiggle if an accel threshold is surpassed if (accel > accel_threshold) { jiggle_layer_weight = 0.7f; } //decrement jiggling until it's back to 0 jiggle_layer_weight = Mathf.Clamp(jiggle_layer_weight - (.8f * Time.deltaTime), 0, 0.7f); anim.SetLayerWeight(1, jiggle_layer_weight); //prepare values for next frame last_pos = current_pos; last_vel = current_vel;

Since we move the balloon kinematically (by parenting it to the hand), we cannot get the velocity from the rigidbody, so we need to calculate it on our own with simple math and a few variables to keep track of displacement every frame. With this, we also calculate acceleration. If you recall, forces act on bodies in motion as a result of acceleration, so we'll only want to jiggle when there is a force jiggling the ballon (which is going to happen when the balloon moves or stops moving suddenly). When the acceleration surpasses a certain threshold we define, we can set the blend weight of our jiggling layer. We don't want this jiggling to turn off instantaneously, so we slowly decrease it until it is back to zero.

Haptic Jiggle Vibration

We already have a float variable jiggle_layer_weight that keeps track of how much our ballon is jiggling. If we use SteamVR's built in controller-vibration functions, it will be relatively easy to make it feel like the balloon is vibrating in your hands. Because we're using SteamVR's Throwable.cs script, we only have to access the correct hand and call a public function on it's Hand.cs Script. In the code below we've created a global variable, hand, that keeps track of which hand is holding the balloon. You'll want to set it when you grab the balloon and set it back to null when you let go as seen below. When you would update the animation weight, you'll also vibrate the controller by a propoertional amount. That's all there is to it. Such an easy step for what it accomplishes.

Haptic Vibration Code Additions //add these two lines to SpawnBalloon() if (Player.instance.leftHand.currentAttachedObject == this.gameObject) { hand = Player.instance.leftHand; } else if (Player.instance.rightHand.currentAttachedObject == this.gameObject) { hand = Player.instance.rightHand; } //put this in Throw() hand = null; //put this in Update() if(hand && jiggle_layer_weight > 0) {hand.controller.TriggerHapticPulse((ushort)(jiggle_layer_weight*1000f)); }

Deformation with Animation Layers The balloon now jiggles when you shake it and gives you some physical feedback. Great, we like this. The last bit will seal the deal, and make the balloon a satisfying bit of VR experience. In this part we'll make sure the balloon deforms somewhat realistically based on how you're holding it and the effects of gravity. Lets take another look at the Update() function that we used earlier. We'll add the following lines that reference the Animator's other layer. This is why we have layers, so that we can deform the balloon and ensure that the deformations are a base animation and that jiggling is an additive animation.