Adding a global timescale

Presently, you might have already noticed that both our scripts, Spin and Orbit, have a gametimePerDay variable that does the same thing--defines the number of game seconds that correspond to an earth hour.

No one writes code without expecting to change it. Programming is a dynamic art as you rethink how to do things, as requirements grow, and problems get fixed. Sometimes, these changes are not necessarily to add a new feature or fix a bug but to make the code cleaner, easier to use, and easier to maintain. This is called refactoring, when you change or rewrite parts of a program but do not necessarily change what it does, that is, its behavior.

Let's refactor our code to remove this duplication and put this variable in a master GameController object instead:

  1. In Hierarchy, create an empty game object and name it GameController.
  2. Add Component, New Script (C-Sharp) and name it MasterControls, then press Create and Add.

Open it for editing, as follows:

File: MasterControls.cs 
using System.Collections; 
using System.Collections.Generic; 
using UnityEngine; 
 
public class MasterControls : MonoBehaviour { 
    public float gametimePerDay = 0.05f;  
} 

The script sets the default time to 0.05f, which will run pretty fast, but it will show the earth orbiting the sun once every 18 seconds (365 * 0.05).

Now, we will modify both Orbit.cs and Spin.cs to reference gametimePerDay of MasterControls rather than their own.

While we're at it, in preparation for adding other planets, we will also modify the Spin script so it also takes rotationRate. This is its local day in earth days. For earth, it'll be 1.0. For other planets, it can be different:

File: Spin.cs 
public class Spin : MonoBehaviour { 
    public float rotationRate = 1f; // in earth days 
    private MasterControls controls; 
 
    void Start() { 
        GameObject controller = GameObject.Find("GameController"); 
        controls = controller.GetComponent<MasterControls>(); 
    } 
 
    void Update () { 
        float deltaAngle = (360.0f / (rotationRate * controls.gametimePerDay)) * Time.deltaTime; 
        transform.Rotate( 0f, deltaAngle, 0f); 
    } 
} 

In Spin.cs, we added two variables: rotationRate (which for the earth is 1.0) and a private controls reference to the MasterControls component. Then, we added a Start() method that will initialize controls when the app starts by finding GameController in Hierarchy and getting its MasterControls component so we can reference it in Update(). Then, in Update(), we used controls.gametimePerDay instead of a local one.

Experienced programmers may disapprove of using GameObject. Find, as it carries a performance overhead and is error-prone, requiring an object specifically named GameController. A better practice would be to use the singleton pattern (see https://unity3d.com/learn/tutorials/projects/2d-roguelike-tutorial/writing-game-manager) or Unity-scriptable objects (see https://unity3d.com/learn/tutorials/modules/beginner/live-training-archive/scriptable-objects).

Next, we will make a similar change to Orbit.cs to use MasterControlsgametimePerDay, as follows:

File: Orbit.cs 
using System.Collections; 
using System.Collections.Generic; 
using UnityEngine; 
 
public class Orbit : MonoBehaviour { 
    public Transform aroundBody; 
    public float orbitalPeriod = 27.3f; // earth days for one complete orbit 
    private MasterControls controls; 
 
    void Start() { 
        GameObject controller = GameObject.Find("GameController"); 
        controls = controller.GetComponent<MasterControls>(); 
    } 
 
    void Update() { 
        float deltaAngle = (360.0f / (orbitalPeriod * controls.gametimePerDay)) * Time.deltaTime; 
        transform.RotateAround(aroundBody.position, Vector3.up, deltaAngle); 
    } 
} 

Save the scripts. Press Play. You can change the value of Gametime Per Day while it's running to see it change dynamically.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.234.83