Codementor Events

Getting started with Unity: Transition between 2 scenes via an input action Part 2

Published Dec 12, 2019
Getting started with Unity: Transition between 2 scenes via an input action Part 2

In part 1 we did the level design, building, added some cool animations and audio effects. If you missed part 1, Getting started with Unity: Transition between 2 scenes via an input action Part 2, catch up via this link.

Lets get down and dirty now with the scripting part, which is a whole new world of fun and learning!

Scripts

On the created GameController game object from part 1

  • click on Add Component
  • Type in Script
  • Select New Script
  • Name it ZoomSelectedobj.cs

I want to start off with, if I click on my Zombie then the camera should zoom towards the entry of the pyramid, stop at a specified distance away from the entry, wait for a split second and then transition into the next scene called “InsideTombScene”.

  • In order to access the SceneManagement Library, add the following line to the top of the cs script,

    • using UnityEngine.SceneManagement;

    sceneManagement.png

Variables

I would like the following variables in my script to assist me with tweaking the zoom settings as I test:

Remember, i use SerializeField in order to keep my variable as private, but make them accessible from the editor to edit in play mode in Unity

  • A float to edit the speed at which the camera zooms towards the target
  • A float to depict how far the camera must zoom up until I want it to stop
  • A game object to specify towards what is the camera zooming to, IE, the target
  • A bool to state whether the camera is currently zooming or not, IE, True or false if camera is zooming
  • A game object to specify the main camera, as its transform position is the one that will be physically moving in the game

Here is a snippet of these variables:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement; //This needs to be added to navigate between scenes in the Unity Project.

public class zoomSelectedObj : MonoBehaviour
{

//This is the speed at which the camera moves towards the target. The value can be edited for convenience while testing in the editor due to me making the field Serializeable (not sure if that word exists in the English Dictionary 😉)
[SerializeField]
private float m_movespeed = 10.0f;

//This will be the stopping distance from the target, IE, how far away from the target the camera will stop. The target in our case is the Temple Entry
[SerializeField]
private float m_stopminDistanceFromTarget = 5f;

//This is what the camera is zooming to, so the target in our case is the temple entry door
[SerializeField]
private GameObject m_targetobject;

//A bool used to confirm if the camera is in zooming state or still state
[SerializeField]
private bool m_zoomtowardstarget = false;

//Used to specify what camera object will be zooming, I only have one camera, the main camera, so this variable will be populated with my main camera
[SerializeField]
private GameObject m_Camera;

Update ()

// Update is called once per frame
//The update function is used to run continuously in the project. IE, anything that is scripted in the Update function will run once per frame,
void Update()
{
if (Input.GetMouseButtonDown(0)) //the GetMouseButtonDown function is a Unity default function, and the parameter of 0 is equal to the left click button on the mouse.
{ Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//The Ray is an imaginary “laser” from point A to point B, in this case from the camera’s current position to what it collides with. This information is sent back and used further in the project. A ray travels until it collides with anything that has a collider component attached to it. A new Ray variable is being created called ray and it will be populated with the ray information from the camera’s transform position(origin) to where the mouse will be clicked, I.E.input.mousePosition.

    RaycastHit hit;

//In this code we are creating a new RaycastHit variable called hit, to get information back from the raycast module. Raycast is used for rendering purposes, IE from the camera’s point sending out a ray in the scene, and find the surface or object it will collide with.

if (Physics.Raycast(ray, out hit, 100.0f))//if the Raycast module with parameters (ray (mousePosition transform position, reference to the hit variable, maximum distance the laser should travel, in this case 100.0f))
{
//If the variable hit collides with a gameobject that is tagged as clickable, then start coroutine.
if (hit.collider.gameObject.tag == "Clickable")
{
StartCoroutine( ZoomInAndLoadScene());
}
}
}
}

If i had to put this in a step by step explanation, this is how it would go:

  • If the Left mouse button is down, create a ray variable and populate with the data of the camera’s transform position to where the mouse button click position took place in the scene
  • Create a new raycasthit variable
    • IF the ray and hit data, and the maximum distance the ray should travel is 100
      • IF the hit data has a gameobject tag of clickable
        • THEN StartCoroutine( ZoomInAndLoadScene());;

CameraZoom ()

This function is to move the camera forward in a zoom effect, giving the illusion that the player is now going into the tomb. We will pass in the target that the camera needs to zoom towards which is the Gameobject target, I.E. the tomb entrance in my case

private void CameraZoom(GameObject target)
{
if (Vector3.Distance(m_Camera.transform.position, target.transform.position) > minimumDistanceFromTarget)//The distance module needs to 2 values, the FROM and TO, A and B, Origin and Finish.
IF the main camera's distance (m_Camera.transform position) is greater than the minimumDistanceFromTarget ,IE currently 5, then we move closer to the target(tomb entrance). Only move the main camera object if the we are further away than minimumDistanceFromTarget

{
m_Camera.transform.position = Vector3.MoveTowards(m_Camera.transform.position, target.transform.position, movespeed * Time.deltaTime);//take the camera objects transform position, set it to a new vector3 moving towards this new position to the targets transform position at the speed of our variable. Move it at the speed we have set in our variable movespeed * time clock speed time
}

//ELSE stop moving or don't move, and set movingtowardstarget bool to false and change scenes
else
{
m_zoomtowardstarget = false;
}
}

ZoomInAndLoadScene ()

I used an IEnumerator due to the fact that I wanted a pause between the camera zoom and loading the next scene.
An IEnumerator allows the process to stop at a specific moment, wait for a defined amount of time, and then go onto the next action. So in the case of the ZoomInAndLoadScene () function, when it is called in the update() function, the following is happening:

  • Set bool variable m_zoomtowardstarget to true

  • While(this will be looped while the statement is true, I.E. while m_zoomtowardstarget is true) the bool variable is set to true, call the function CameraZoom(targetobject), passing in the parameter of targetobject(Tomb entrance GO). The yield return null line of code is needed in order for the loop to rerun while the statement is true every frame instead of the whole function running through in a single frame. So it will loop and loop and loop while the statement is true

  • When the camera gets to m_minimumDistanceFromTarget (5.0f), it will jump out of the loop because the m_zoomtowardstarget will be set to false

  • It will wait half a second

  • It will load a new scene via LoadScene from Scenemanager library

    • All scenes need to be part of build settings in order to load.
    • If you get an error at the the code line “SceneManager.LoadScene("InsideTombScene");” , then your InsideTombScene is not part of build settings.

    IEnumerator ZoomInAndLoadScene()

    {
    m_zoomtowardstarget = true; \set m_zoomtowardstarget to true
    while (m_zoomtowardstarget) \while m_zoomtowardstarget is true, run CameraZoom()
    {
    CameraZoom(targetobject);
    yield return null;
    }
    yield return new WaitForSeconds(0.5f); \When min distance it reached, pause for 0.5 seconds
    SceneManager.LoadScene("InsideTombScene"); \Load next scene
    }
    }

Final Result

FinishedProject.gif

Conclusion

There you have it! 2 scenes joined with inputs and scripts transitioning in a neat smooth way. There is so much that this small demo still needs, and dont stop working on it just because the blog is done. Work on it, build it, make it yours!

zoomSelectedObj.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;


public class zoomSelectedObj : MonoBehaviour
{

   //this is the speed at which the camera moves towards the target, it's a public variable so the float number can be changed to how fast or slow you want the camera to move
   [SerializeField]
   private float m_movespeed = 10.0f;

   //this will be the stopping distance from the target, IE how far away from the target it will stop.  The target in our case the the Temple Entry
   [SerializeField]
   private float m_stopminDistanceFromTarget = 5f;

   //this is what the camera is zooming to, so the target, in our case that would the the temple entry door
   [SerializeField]
   private GameObject m_targetobject;

   //bool used to confirm if camera is in zooming state or still state
   [SerializeField]
   private bool m_zoomtowardstarget = false;

   //This variable will host the main camera object in the scene.  We need this to control the camera’s zooming etc
   [SerializeField]
   private GameObject m_Camera;


   private void Awake()
   {
       //In order for the loading scene to run we need the Game Controller game object in the outside tomb scene not to be destroyed.
       //By default when scenes are changed, the object in that scene get “destroyed” with the scene.  We need this line of code in order
       //not to destroy the Game Object that this script is attached too, IE GameController

       DontDestroyOnLoad(gameObject);
   }

   // Update is called once per frame
   void Update()
   {
       //If Left Mouse button down, 0 stands for Left     

       if (Input.GetMouseButtonDown(0))
       {
           Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
           RaycastHit hit;

           if (Physics.Raycast(ray, out hit, 100.0f))
           {
               //Replace this with whatever logic you want to use to validate the objects you want to click on
               if (hit.collider.gameObject.tag == "Clickable")
               {
                  StartCoroutine( ZoomInAndLoadScene());
               }
           }
       }
   }

   private void CameraZoom(GameObject target)
   {
       //if the camera's distance (transform position) is greater than the minimumDistanceFromTarget ,IE current 5, then we move closer to the target.  Only move if the we are further away than minimumDistanceFromTarget
       if (Vector3.Distance(m_Camera.transform.position, target.transform.position) > m_stopminDistanceFromTarget)
       {
           //setting the camera's position to a new vector3 position which is the targets transform position, move it at the speed we have set time clockspeed time
           m_Camera.transform.position = Vector3.MoveTowards(m_Camera.transform.position, target.transform.position, m_movespeed * Time.deltaTime);
       }
       else //otherwise stop moving or dont move and set movingtowardstarget bool to false
       {
           m_zoomtowardstarget = false;
       }
   }

   IEnumerator ZoomInAndLoadScene()
   {
       m_zoomtowardstarget = true;
       
       while (m_zoomtowardstarget)
       {
           CameraZoom(m_targetobject);
           yield return null;
       }
       yield return new WaitForSeconds(0.5f);
       SceneManager.LoadScene("InsideTombScene");
   }
}
Discover and read more posts from Melanie Leemans
get started
post commentsBe the first to share your opinion
Show more replies