Many of the recipes in this chapter are built on this basic project, which constructs a scene with a textured terrain, a downward facing Main Camera, and a red cube (as shown in the following screenshot) that can be moved around by the user using the four directional arrow keys.
To create a player-controlled cube, perform the following steps:
Transform position for terrains relates to their corner not their center
Since the Transform
position of terrains relates to the corner of the object, we center such objects at (0, 0, 0) by setting the X-coordinate equal to (-1 x width/2) and the Z-coordinate to (-1 x length/2). In other words, we slide the object by half its width and half its height to ensure its center is just where we want it.
In this case, width is 30 and length is 20, hence we get -15 for X (-1 x 30/2), and -10 for Z (-1 x 20/2).
Cube-player
, at position (0, 0.5, 0) and sized (1, 1, 1).m_red
, and apply this material to Cube-player
.Cube-player
:// file: PlayerControl using UnityEngine; using System.Collections; public class PlayerControl : MonoBehaviour { public float y; public const float MIN_X = -15; public const float MAX_X = 15; public const float MIN_Z = -10; public const float MAX_Z = 10; private float speed = 20; private void Awake(){ y = transform.position.y; } private void Update () { KeyboardMovement(); CheckBounds(); } private void KeyboardMovement(){ float dx = Input.GetAxis("Horizontal") * speed * Time.deltaTime; float dz = Input.GetAxis("Vertical") * speed * Time.deltaTime; transform.Translate( new Vector3(dx,y,dz) ); } private void CheckBounds(){ float x = transform.position.x; float z = transform.position.z; x = Mathf.Clamp(x, MIN_X, MAX_X); z = Mathf.Clamp(z, MIN_Z, MAX_Z); transform.position = new Vector3(x, y, z); } }
// file: UsefulFunctions.cs using UnityEngine; public class UsefulFunctions { public static void DebugRay(Vector3 origin, Vector3 v, Color c) { Debug.DrawRay(origin, v * v.magnitude, c); } public static Vector3 ClampMagnitude(Vector3 v, float max) { if (v.magnitude > max) return v.normalized * max; else return v; } }
The scene contains a terrain, positioned so its center is (0, 0, 0). The red cube is controlled by the user's arrow keys through the PlayerControl
script. When the Awake()
method is called, the starting Y-coordinate is stored, so that any changes to the position of the cube will always keep the object to the same Y-position. For each frame, the Update()
method first calls KeyboardMovement()
and then CheckBounds()
.
The KeyboardMovement()
method reads the horizontal and vertical input values (which the Unity default settings read from the four directional arrow keys). Based on these left-right and up-down values, the position of the player's cube is moved (translated). The amount it is moved depends on the speed variable. Since our camera is looking down, the Y-coordinate is fixed, and it is the X and Z values that are used to determine how to move the red cube.
The CheckBounds()
method simply checks the X and Z positions against the four constants for the maximum and minimum values. If values are outside the range, they are set to the maximum or minimum as appropriate.
Mathf.Clamp() is a very handy function
This function is very useful as it allows us to restrict a value between a minimum and maximum value. The first parameter is the value, the second is the minimum, and the third is the maximum. If the value is smaller than the minimum, then the minimum is returned. If the value is larger than the maximum, the maximum is returned. Otherwise the value (which must then be somewhere within these limits) is returned.
Although not used in this project, the class UsefulFunctions
is used by several of the recipes in this chapter. It offers two useful functions to our project:
DebugRay()
: This takes two Vector3
objects and a color as input, and draws a line of the given color from the start point (first argument) in the direction (and length) of the vector, which is the second argumentClampVector()
: This takes a Vector3
object and a maximum size as input, and returns a vector with a maximum length (magnitude) of the input maximum size, that is, if the length of the given vector is greater than the maximum, then a vector of maximum length in the same direction is returned3.16.137.117