HOW TO ADD SLOW MOTION EFFECT TO ALL OBJECTS EXCEPT CHARACTER IN UNITY3D

If you have not gone through the post on HOW TO ADD SLOW MOTION(BULLET TIME) EFFECT IN UNITY3D, I would encourage you to do so before going through this post.

In the post whose link is mentioned above, we learned how to add the slow motion effect a.k.a. bullet time effect to all the gameObjects. That is a very useful trick, but, most of the times you do not want to add this slow motion effect to the character. Apart from the character, everything else should move in a lesser speed than their usual. This is exactly what we will be learning in this post.

Just for the sake of completeness, I would like to create a new scene, it's all fine even if you continue this in the same scene. Apparently, I will be adding all the same objects which were present in the previous post, but with a character which can be controlled by the keyboard inputs.

- Create a new Scene and you can name it anything you like.
- Add a Directional Light so that we can see what's going on in the scene. Of course, the objects will be visible even without the light, but, I just like to add a light in the scene.
- Add a cube and name it Enemy, by default it will be positioned at (0, 0, 0), we will keep it there.
- Skip this step if you already have a script named EffectsScript with code that is mentioned below. Create a C# script named EffectsScript, if you haven't already. Add the below code to the enemy script, this script is exactly same as the one in the previous post.

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; 
    }
}

- Create another cube, by duplicating the one created above or creating a new one, name it as Player. Position it at (-5, 0, 0)
- Create a new C# script called PlayerScript. Attach it to the Player gameObject. Add the code below to it.

using UnityEngine;
using System.Collections;

public class PlayerScript : MonoBehaviour {
    //factor for cube movement speed
    float speed = 10f;
    void Update()
    {   
        //get input from keyboard i.e. the arrow keys
        float h = Input.GetAxisRaw("Horizontal");
        float v = Input.GetAxisRaw("Vertical");
        //add the input values to the Player so as to move it
        transform.position += new Vector3(h, 0, v)*Time.deltaTime*speed*1/Time.timeScale;
    }
}

- In line 6, we have defined a variable named Speed, this essentially defines the speed at which the cube moves on receiving the input from the keyboard.
- We have used GetAxisRaw instead of GetAxis. The reason being GetAxis uses gravity and sensitivity from the Input settings, which are affected by timescale. And this is what we don't want to happen.
- In line 13, we add movement to the Player gameobject based on keyboard input. There are two cases you would want to test.
i) If the line 13 was like
transform.position += new Vector3(h, 0, v)*Time.deltaTime*speed
It would work all fine but then, it would add the slow motion effect to our Player gameobject as well.
ii) The second case is the one I have posted the code above. What we basically do by dividing it by the Time.timeScale is we make it impotent to the changes in Time.timeScale.

Test the scene now, and you will notice that the Player gameObject moves at a normal speed while the other object is affected by the Time.timeScale.

The unity package for the Bullet Time Effect can be downloaded from the below link
BulletTimeEffectUnity
  
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