Player control of a 3D GameObject (and limiting the movement within a rectangle)

Many of the 3D recipes in this chapter are built on this basic project, which constructs a scene with a textured terrain, a Main Camera, and a red cube that can be moved around by the user with the four directional arrow keys. The bounds of movement of the cube are constrained using the same technique as in the previous 2D recipe.

Player control of a 3D GameObject (and limiting the movement within a rectangle)

How to do it...

To create a basic 3D cube controlled game, follow these steps:

  1. Create a new, empty 3D project.
  2. Once the project has been created, import the single Terrain Texture named SandAlbedo (it was named GoodDirt in Unity 4). Choose menu: Assets | Import Package | Environments, deselect everything, and then locate and tick the asset: Assets/Environment/TerrainAssets/SurfaceTextures/ SandAlbedo.psd.

    Tip

    You could have just added the Environment Asset Package when creating the project—but this would have imported 100s of files, and we only needed this one. Starting a project in Unity, then selectively importing just what we need is the best approach to take, if you want to keep the project's Asset folders to small sizes.

  3. Create a terrain positioned at (-15, 0, -10) and sized 30 by 20.

    Note

    The transform position for the terrains relates to their corner and not their center.

    Since the Transform position of the terrains relates to the corner of the object, we center such objects at (0,0,0) by setting the X-coordinate equal to ( -1*width/2), and the Z-coordinate equal to (-1*length/2). In other words, we slide the object by half its width and half its height to ensure that its center is just where we want it.

    In this case, the width is 30 and the length is 20, hence we get -15 for X (-1 * 30/2), and -10 for Z (-1 * 20/2).

  4. Texture paint this terrain with your texture called SandAlbedo.
  5. Create a directional light (it should face downwards to the terrain with the default settings—but if it doesn't for some reason, then rotate it so that the terrain is well lit).
  6. Make the following changes to the Main Camera:
    • position = (0, 20, -15)
    • rotation = (60, 0, 0)
  7. Change the Aspect Ratio of the Game Panel from Free Aspect to 4:3. You will now see the whole of the Terrain in the Game Panel.
  8. Create a new empty GameObject named corner_max, and position it at (14, 0, 9). With this GameObject selected in the Hierarchy, choose the large, yellow oblong icon, highlighted in the Inspector panel.
  9. Duplicate the corner_max GameObject, naming the clone as corner_min, and position this clone at (-14, 0, -9). The coordinates of these two GameObjects will determine the maximum and minimum bounds of the movement permitted for the player's character.
  10. Create a new Cube GameObject named Cube-player at a position called (0, 0.5, 0), and size it as (1,1,1).
  11. Add to the Cube-player GameObject, apply a component called Physics | RigidBody, and uncheck the RigidBody property Use Gravity.
  12. Create a red Material named m_red, and apply this Material to Cube-player.
  13. Add the following C# script class called PlayerControl to the Cube-player:
    using UnityEngine;
    using System.Collections;
    
    public class PlayerControl : MonoBehaviour {
      public Transform corner_max;
      public Transform corner_min;
    
      public float speed = 40;
      private Rigidbody rigidBody;
    
      private float x_min;
      private float x_max;
      private float z_min;
      private float z_max;
    
      void Awake (){
        rigidBody = GetComponent<Rigidbody>();
        x_max = corner_max.position.x;
        x_min = corner_min.position.x;
        z_max = corner_max.position.z;
        z_min = corner_min.position.z;
      }
    
      void FixedUpdate() {
        KeyboardMovement();
        KeepWithinMinMaxRectangle();
      }
    
      private void KeyboardMovement (){
        float xMove = Input.GetAxis("Horizontal") * speed * Time.deltaTime;
        float zMove = Input.GetAxis("Vertical") * speed * Time.deltaTime;
    
        float xSpeed = xMove * speed;
        float zSpeed = zMove * speed;
    
        Vector3 newVelocity = new Vector3(xSpeed, 0, zSpeed);
    
        rigidBody.velocity = newVelocity;	
    
        // restrict player movement
        KeepWithinMinMaxRectangle ();
      }
    
      private void KeepWithinMinMaxRectangle (){
        float x = transform.position.x;
        float y = transform.position.y;
        float z = transform.position.z;
        float clampedX = Mathf.Clamp(x, x_min, x_max);
        float clampedZ = Mathf.Clamp(z, z_min, z_max);
        transform.position = new Vector3(clampedX, y, clampedZ);
      }
    
      void OnDrawGizmos (){
        Vector3 top_right = Vector3.zero;
        Vector3 bottom_right = Vector3.zero;
        Vector3 bottom_left = Vector3.zero;
        Vector3 top_left = Vector3.zero;
    
        if(corner_max && corner_min){
          top_right = corner_max.position;
          bottom_left = corner_min.position;
    
          bottom_right = top_right;
          bottom_right.z = bottom_left.z;
    
          top_left = bottom_left;
          top_left.z = top_right.z;
        } 
    
        //Set the following gizmo colors to YELLOW
        Gizmos.color = Color.yellow;
    
        //Draw 4 lines making a rectangle
        Gizmos.DrawLine(top_right, bottom_right);
        Gizmos.DrawLine(bottom_right, bottom_left);
        Gizmos.DrawLine(bottom_left, top_left);
        Gizmos.DrawLine(top_left, top_right);
      }
    }
  14. With the Cube-player GameObject selected in the Hierarchy, drag the GameObjects called corner_max and corner_min over the public variables called corner_max and corner_min in the Inspector panel.
  15. When you run the scene, the positions of the corner_max and corner_min GameObjects will define the bounds of movement for the Player's Cube-player character.

How it works...

The scene contains a positioned terrain so that its center is (0,0,0). The red cube is controlled by the user's arrow keys through the PlayerControl script.

Just as with the previous 2D recipe, a reference to the (3D) RigidBody component is stored when the Awake() method executes, and the maximum and minimum X- and Z- values are retrieved from the two corner GameObjects, and is stored in the x_min, x_max, z_min, and z_max variables. Note that for this basic 3D game, we won't allow any Y-movement, although such movement (and bounding limits by adding a third 'max-height' corner GameObject) can be easily added by extending the code in this recipe.

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 velocity of the cube is updated. The amount it will move depends on the speed variable.

The KeepWithinMinMaxRectangle() method uses the Math.Clamp(…) function to move the character back inside the X and Z limits, so that the player's character is not permitted to move outside the area defined by the corner_max and corner_min GameObjects.

The OnDrawGizmos() method tests that the references to the corner_max and corner_min GameObjects are not null, and then sets the positions of the four Vector3 objects, representing the four corners defined by the rectangle with the corner_max and corner_min GameObjects at the opposite corners. It then sets the Gizmo color to yellow, and draws lines connecting the four corners in the Scene panel.

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

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