HOW TO ADD SLOW MOTION(BULLET TIME) EFFECT IN UNITY3D

Max Payne. Yes, Max Payne, is where this effect became popular. We had this kind of effect is Prince of Persia: SOD as well, I believe.

We will be learning how to achieve this Bullet Time Effect i.e., Slow Motion Effect in Unity3d. We will be also learning how to achieve the, what shall we call? Ah, Fast Motion Effect (Cheap. Isn't it? Well, that's alright. It's good to be cheap sometimes.)

The concept behind this is as simple as manipulating the Time.timeScale. For normal execution of the game, the value of Time.timeScale is 1. If we needed to pause the game, we simply set the Time.timeScale = 0. 
Yet, it is not as simple as setting the Time.timeScale to 0, 1 or any other value. There is a whole lot of dependencies that are to be taken into consideration. We will look at some of those dependencies in this post.

Create a New Scene. Add a Cube GameObject to the scene. Create a new C# Script named EffectsScript. Add the below line in the Update function.
using UnityEngine;
using System.Collections;

public class EffectsScript : MonoBehaviour {
 
 // Update is called once per frame
 void Update () {
  //rotate the cube at a constant rate
  transform.Rotate(new Vector3(5,5,5));
 }
}

If you bother to add this script to the cube and test the scene by hitting on the Play button.
You will notice that the cube is rotating at a constant rate.

Now we will add a Slow Motion effect to this scene. To do this we need to change the value of Time.timeScale.

Add the below script to 
using UnityEngine;
using UnityEngine;
using System.Collections;

public class EffectsScript : MonoBehaviour {

 private float slowMoTimeScale; //new time scale
 private float factor = 4f;  //factor to increase or decrease the timescale by
 // Use this for initialization
 void Start () {
  slowMoTimeScale = Time.timeScale/factor; //calculate the new timescale
 }

 // Update is called once per frame
 void Update () {
  //rotate the cube at a constant rate
  transform.Rotate(new Vector3(5,5,5));  
  slowMo();
 }

 //add slow motion effect
 void slowMo (){
  //assign new time scale value
  Time.timeScale = slowMoTimeScale;
  //reduce this to the same proportion as timescale to ensure smooth simulation
  Time.fixedDeltaTime = Time.fixedDeltaTime*Time.timeScale;  
 }
}

All we have done here is to reduce the timeScale by a factor of 4. We have also reduced the Time.fixedDetaTime to make sure the RigidBody simulation does not become inconsistent. Yeah, this is a dependency.

Now if you test the scene after updating the script you will not notice any difference. Why is that so?
Well, the rotation of the cube is frame rate dependent. There you go, another dependency. For the Time.timeScale to make any changes, we need to make the rotation frame rate independent. The next question you might ask, well, I hope you won't, is how to make the rotation frame rate independent.
The answer is by multiplying the vector by Time.deltaTime. This, perhaps is the most basic thing one should be aware of.
Replace, the line 16 with the below code

transform.Rotate(new Vector3(200,200,200)*Time.deltaTime);  

We have our slow motion effect all set.

If we wanted to do the opposite of the slow motion effect, we would simply do the opposite of what we did to achieve the slow motion effect. Refer the script below:

using UnityEngine;
using System.Collections;

public class EffectsScript : MonoBehaviour {

 private float slowMoTimeScale; //slow motion time scale
 private float fastMoTimeScale;  //fast motion time scale
 private float factor = 4f;  //factor to increase or decrease the timescale by
 // Use this for initialization
 void Start () {
  slowMoTimeScale = Time.timeScale/factor; //calculate the new timescale
  fastMoTimeScale = Time.timeScale*factor; 
 }

 // Update is called once per frame
 void Update () {
  //rotate the cube at a constant rate
  transform.Rotate(new Vector3(200,200,200)*Time.deltaTime);  
  fastMo();
 }

 //add slow motion effect
 void slowMo (){
  //assign new time scale value
  Time.timeScale = slowMoTimeScale;
  //reduce this to the same proportion as timescale to ensure smooth simulation
  Time.fixedDeltaTime = Time.fixedDeltaTime*Time.timeScale;  
 }

 //add fast motion effect
 void  fastMo (){
  Time.timeScale = fastMoTimeScale;
  Time.fixedDeltaTime = Time.fixedDeltaTime*Time.timeScale;  
 }
}

If you test this, you will notice that the cube is rotating insanely fast. Yeah, that's the fast motion effect.

If you want to pause the game you would simply set the Time.timeScale to 0. Set it to 1 when you want to unpause it.

The below script is a nice compilation of all the effects for your reference.

using UnityEngine;
using System.Collections;

public class EffectsScript : MonoBehaviour {

 private float slowMoTimeScale; //slow motion time scale
 private float fastMoTimeScale;  //fast motion time scale
 private float factor = 4f;  //factor to increase or decrease the timescale by
 // Use this for initialization
 void Start () {
  slowMoTimeScale = Time.timeScale/factor; //calculate the new timescale
  fastMoTimeScale = Time.timeScale*factor; 
 }

 // Update is called once per frame
 void Update () {
  //rotate the cube at a constant rate
  transform.Rotate(new Vector3(200,200,200)*Time.deltaTime);  
 }

 void  OnGUI (){
  //Pause/Unpause on click
  if(GUI.Button( new Rect(0,0,120,30),"PAUSE/RESUME")){
   CheckPaused();
  }
  //add slow motion effect
  if(GUI.Button( new Rect(0,30,80,30),"SLOWMO")){
   slowMo();
  }
  //add fast motion effect
  if(GUI.Button( new Rect(0,60,120,30),"FASTMO")){
   fastMo();
  }
 }

 //check if paused
 void  CheckPaused(){
  if(Time.timeScale>0){
   pauseGame();
  } else {
   unPauseGame();
  }
 }
 //pause the game
 void  pauseGame (){
  Time.timeScale=0;
 }
 //unpause the game
 void  unPauseGame (){
  Time.timeScale=1;
 }

 //add slow motion effect
 void slowMo (){
  //assign new time scale value
  Time.timeScale = slowMoTimeScale;
  //reduce this to the same proportion as timescale to ensure smooth simulation
  Time.fixedDeltaTime = Time.fixedDeltaTime*Time.timeScale;  
 }

 //add fast motion effect
 void  fastMo (){
  Time.timeScale = fastMoTimeScale;
  Time.fixedDeltaTime = Time.fixedDeltaTime*Time.timeScale;  
 }
}
Also check out:
HOW TO ADD SLOW MOTION(BULLET TIME) EFFECT IN UNITY3D-PART2
Share on Google+

About Sujit Horakeri

Sujit Horakeri is a game freak just like any other next door guy you would come across. He is a Web Developer by Profession, Game Developer by Choice.
Connect with him on:
    Blogger
    Facebook

0 comments:

Post a Comment