Simple keyboard-based first person controller for Unity3D

Today I’m going to present a simple first person controller for Unity3D. The script allows you to control your character with the arrow keys (or WASD if you want). A general understanding of Unity3D is required. The reason for me doing this is that the default first person controller provided by Unity is based on mouse AND keyboard interaction. This one is just based on the keyboard and might be more suitable for some applications.

Besides moving your character, a simple collision detection based on Unitys Physics.Linecast() is provided by the script. With it, walls (or colliders) are detected. If the player walks against a wall, movement in the direction where the wall is located will be prohibited. Turning left or right and moving in the opposite direction is allowed. Note: To detect a collision, objects like walls or furniture need to have a collider.

The collision detection is based on targets. The target parameters of the script are empty GameObjects which have to be positioned slightly in front and in the back of the camera. On each call of Update(), the script tests the area between the center of the camera and the targets for collisions with colliders. If there is a collision, moving the character will be restricted.

The script also handles stairs meaning the player is able to walk up and down stairs. However, walking downwards is implemented only prototypical at the moment.

So, here is what you have to do in order to get the script and the first person controller working:
1. Create an empty GameObject of the type Caspule and name it FW_PlayerWrapper
2. Add CameraMovementScript to FW_PlayerWrapper
3. Add a camera as child to FW_PlayerWrapper (called FW_FPCamera)
4. Add another four GameObjects as children to the camera (FW_stairTargetFront, FW_targetBack, FW_targetFront, FW_targetFront2)
5. In the GameObject from step 1, look for the CameraMovementScript and set the targets to your GameObjects from step 4
The final configuration of your hierarchy should look like this. Also the FW_PlayerWrapper needs to have the cameraMovementScript as a component.

Hierarchy for an easy FP-Controller
Now, after you have placed your first person controller into a nice environment where the floor is a terrain or has a collider, you should see something like this:

Camera Object with lines indicating the targets
The red, blue, green and cyan line indicate the position of your targets. Note that they need to be positioned in a similiar manner. Otherwise, the first person controller won’t work. The green one represents the FW_stairTarget, the blue one the FW_targetBack. The cyan and red lines represent the targets in front of the player.

Here’s the code for the cameraMovementScript:

using UnityEngine;
using System.Collections;
using AssemblyCSharp;

public class cameraMovementScript : MonoBehaviour {

 public float rotationSpeed = 123.0f;
 public float translationSpeed = 240.0f;
 public float stair_height;

 public Transform target_front;
 public Transform target_front_2;
 public Transform target_back;
 public Transform stair_target_front;

 public float mutliplicator = 0.2f;

 Vector3 horizontalRotation;
 Vector3 translation;

 private bool collision_line_front = false;
 private bool collision_line_back = false;
 private bool collision_line_front_2 = false;
 private bool stop_movement = true;
 private bool stair_front = false;

 private bool last_was_up = false;

 float horizont, vertical;

 public void Start(){
 }

 //movement w/ arrow keys and wasd
 public void Update() {

  horizont = Input.GetAxis ("Horizontal");
  vertical = Input.GetAxis ("Vertical");

  horizontalRotation = new Vector3 (0, horizont, 0);
  translation = new Vector3 (0, 0, vertical);

  Debug.DrawLine (transform.position, target_front.position, Color.red);
  Debug.DrawLine (transform.position, target_back.position, Color.blue);
  Debug.DrawLine (transform.position, target_front_2.position, Color.cyan);

  //check for back and front collision
  collision_line_front = Physics.Linecast (transform.position, target_front.position);
  collision_line_front_2 = Physics.Linecast (transform.position, target_front_2.position);
  collision_line_back = Physics.Linecast (transform.position, target_back.position);

  stop_movement = handleCollisionWithMovement(collision_line_back, collision_line_front,collision_line_front_2, translation.z);

  //if no collision move and rotate
  if (!stop_movement) {
   rotateMe(horizontalRotation);
   translateMe(translation);
   //just rotate
  } else {
   rotateMe(horizontalRotation);
  }

  Debug.DrawLine (transform.position, stair_target_front.position, Color.green);

  stair_front = Physics.Linecast (transform.position, stair_target_front.position);
  if (!collision_line_front && stair_front && !last_was_up) {
  Vector3 t = new Vector3(0.0f,stair_height,0.0f);
  transform.Translate(t*Time.deltaTime*translationSpeed);
  last_was_up = true;
  }
 }

 private bool handleCollisionWithMovement(bool _collision_line_back, bool _collision_line_front, bool _collision_line_front_2, float z){
  bool result;

  //if there's no collision, allow movement
  if (!collision_line_back && !collision_line_front && !collision_line_front_2 ) {
   result = false;
  } else {
   //if collision with object behind character, but desired direction of movement is forward, allow movement
   if (collision_line_back && (translation.z) > 0) {
    result = false;
   }
   //if collision with object in front of character but desired direction of movemtn is backward, allow movement
   else if ((collision_line_front|| collision_line_front_2) && (translation.z) < 0 ) {
    result = false;
   }
  else
   result = true;
  }
  return result;
 }

 private void rotateMe(Vector3 horizontalRotation){
  transform.Rotate (horizontalRotation * rotationSpeed * Time.deltaTime);
  last_was_up = false;;
 }

 private void translateMe(Vector3 translationVector){
  transform.Translate (translation * Time.deltaTime * translationSpeed);
  last_was_up = false;
 }
}

I hope everything works as expected. If not, please let me know 🙂
Have fun!

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s