Since Remedy Entertainment's Max Payne, slow motion, or bullet-time, has become a popular feature in games. For example, Criterion's Burnout series has successfully explored the slow-motion effect in the racing genre. In this recipe, we will implement slow motion while the player presses down the right mouse button or the Alt key.
For this recipe, we will use the same prepared package as the previous recipe: BallShooterGame
from the 0423_10_01
folder. We will also need a texture for a time progress bar, which is named barTexture.png
and can be found in the 0423_10_02
folder.
To implement slow-motion, perform the following steps:
barTexture.png
.BallShooterGame
into your project and open the level named RoomLevel
(from the Scenes
folder).ShooterScript
with new code to implement slow motion time effects. Open ShooterScript
and replace everything with the following code:// file: ShooterScript.cs using UnityEngine; using System.Collections; public class ShooterScript : MonoBehaviour { public Rigidbody projectile; public float projectileForce = 5000.0f; public bool compensateBulletSpeed = true; public float slowMotionSpeed = 10.0f; public Texture2D slowMotionBar; public float slowMotionTotalTime = 10.0f; public float recoverTimeRate = 0.5f; private bool isSlowMotionMode = false; private float remainingSloMoTime; private float startSloMoTimestamp; private float elapsedTime = 0.0f; private float actualForce; private void Start() { Screen.showCursor = false; remainingSloMoTime = slowMotionTotalTime; actualForce = projectileForce; } private void Update() { CheckUserInput(); if( isSlowMotionMode ) SlowMotionModeActions(); else NormalTimeActions(); } private void CheckUserInput() { if (Input.GetButtonDown("Fire1")){ Rigidbody clone = (Rigidbody) Instantiate(projectile, Camera.main.transform.position, Camera.main.transform.rotation); clone.AddForce(clone.transform.forward * actualForce); } if (Input.GetButtonDown("Fire2") && remainingSloMoTime > 0) ActivateSloMo(); if (Input.GetButtonUp("Fire2")) DeactivateSloMo(); } private void SlowMotionModeActions() { elapsedTime = (Time.time - startSloMoTimestamp) * slowMotionSpeed; remainingSloMoTime = slowMotionTotalTime - elapsedTime; if (elapsedTime >= slowMotionTotalTime) DeactivateSloMo(); } private void NormalTimeActions() { if( remainingSloMoTime < slowMotionTotalTime ) remainingSloMoTime += Time.deltaTime * recoverTimeRate; else remainingSloMoTime = slowMotionTotalTime; } private void ActivateSloMo() { Time.timeScale = 1.0f / slowMotionSpeed; Time.fixedDeltaTime = 0.02f / slowMotionSpeed; actualForce = projectileForce * slowMotionSpeed; isSlowMotionMode = true; float timeLeftToRefill = (slowMotionTotalTime - remainingSloMoTime) / slowMotionSpeed; startSloMoTimestamp = (Time.time - timeLeftToRefill); } private void DeactivateSloMo() { Time.timeScale = 1.0f; Time.fixedDeltaTime = 0.02f; actualForce = projectileForce; isSlowMotionMode = false; } private void OnGUI() { float proportionRemaining = remainingSloMoTime / slowMotionTotalTime; float barDisplayWidth = slowMotionBar.width * proportionRemaining; int proportionRemaininInt = (int)(proportionRemaining * 100); string percentageString = proportionRemaininInt + "%"; GUI.Label(new Rect(10, 15, 40, 20), percentageString); Rect newRect = new Rect(50, 10, barDisplayWidth, slowMotionBar.height); GUI.DrawTexture( newRect, slowMotionBar, ScaleMode.ScaleAndCrop, true, 10.0f); } }
Basically, all we need to do to have the slow motion effect is decrease the value of the Time.timeScale
variable. In our script, we do that by dividing it by the slowMotionSpeed
variable. We do the same to the Time.fixedDeltaTime
variable, which updates the physics simulation of our game. The ActivateSloMo()
method sets values for slow motion effects, and the DeactivateSloMo()
method returns values for normal speed time.
In order to make the experience more challenging, we have also implemented a sort of "energy bar" to indicate how much bullet time the player has left (the initial value is given by the slowMotionDuration
variable). Whenever the player is not using bullet time, he has his quota filled according to the recoverTimeRate
variable.
The GUI is implemented based on finding the proportion of slow motion time remaining, and sizing the width of the bar texture accordingly.
The following are some suggestions for you to improve your slow motion effect even further:
Motion Blur is an image effect frequently identified with slow motion. Once attached to the camera, it could be enabled and disabled through the ActivateSloMo()
and DeactivateSloMo()
methods respectively. More information on the Motion Blur image effect can be found at docs.unity3d.com/Documentation/Components/script-MotionBlur.html.
18.227.72.212