3rd Person Controller Scripts.

TP_Motor controls all the other scripts

using UnityEngine;
using System.Collections;

public class TP_Motor : MonoBehaviour {

public static TP_Motor Instance;

public float ForwardSpeed = 15f;
public float BackwardSpeed = 8f;
public float StrafingSpeed = 12f;
public float SlideSpeed = 10f;
public float JumpSpeed = 9f;
public float Gravity = 21f;
public float TerminalVelocity = 20f;
public float SlideThreshold = 0.6f;
public float MaxControllableSlideMagnitude = 0.4f;

private Vector3 slideDirection;

public Vector3 MoveVector { get; set; }
public float VerticalVelocity { get; set; }

void Awake() {

Instance = this;

}

public void Update.Motor() {

SnapAlignCharacterWithCamera();
ProcessMotion();

}

void ProcessMotion(){

//transform MoveVector to worldSpace
MoveVector = transform.TransformDirection(MoveVector);

//Normalise MoveVector if MAgnitude > 1
if (MoveVector.magnitude > 1)
MoveVector = Vector3.Normalize(MoveVector);

//Apply sliding if applicable
ApplySlide();

//Multiply MoveVector by MoveSpeed
MoveVector *= MoveSpeed();

//Reapply VerticalVelocity MoveVector.y
MoveVector = new Vector3(MoveVector.x, VerticalVelocity, MoveVector.z);

//Apply gravity
ApplyGravity();

//Move the character in world space
TP_Controller.characterController.Move(MoveVector * Time.deltaTime);

}

void ApplyGravity()
{
if (MoveVectory > -TerminalVelocity)
MoveVector = new Vector3(MoveVector.x, MoveVectory – Gravity * Time.deltaTime, MoveVector.z);

if (TP_Controller.characterController.isGrounded && MoveVector.y < – 1)
MoveVector = new Vector3(MoveVector.x, -1, MoveVector.z);
}

void ApplySlide()
{
if (!TP_Controller.characterController.isGrounded)
return;

slideDirection = Vector3.zero;

RaycastHit hitInfo;

if (Physics.Raycast(transform.position + Vector3.up, Vector3.down, out hitInfo))
{
if (hitInfo.normal.y < SlideThreshold)
slideDirection = new Vector3(hitInfo.normal.x, -hitInfo.normal.y, hitInfo.normal.z);
}

if (slideDirection.magnitude < MaxControllableSlideMagnitude)
MoveVector += slideDirection;
else
{
MoveVector = slideDirection;
}
}

public void Jump()
{
if (TP_Controller.characterController.isGrounded)
VerticalVelocity = JumpSpeed;
}

void SnapAlignCharacterWithCamera() {

if (MoveVector.x != 0 || MoveVector.z != 0){

transformrotation = Quaternion.Euler(transform.eulerAngles.x,
Camera.mainCamera.transform.eulerAngles.y,
transform.eulerAngles.z);

}

}

float MoveSpeed()
{
var moveSpeed = 0f;

switch (TP_Animator.Instance.MoveDirection)
{
case TP_Animator.Direction.Stationary:
moveSpeed = 0;
break;
case TP_Animator.Direction.Forward:
moveSpeed = ForwardSpeed;
break;
case TP_Animator.Direction.Backward:
moveSpeed = BackwardSpeed;
break;
case TP_Animator.Direction.Left:
moveSpeed = StrafingSpeed;
break;
case TP_Animator.Direction.Right:
moveSpeed = StrafingSpeed;
break;
case TP_Animator.Direction.LeftForward:
moveSpeed = ForwardSpeed;
break;
case TP_Animator.Direction.RightForward:
moveSpeed = ForwardSpeed;
break;
case TP_Animator.Direction.LeftBackward:
moveSpeed = BackwardSpeed;
break;
case TP_Animator.Direction.RightBackward:
moveSpeed = BackwardSpeed;
break;
}

if (slideDirection.magnitude > 0)
moveSpeed = SlideSpeed;

return move.Speed;
}
}

TP_Camera controls all the camera movement such as orbiting and occlusion culling.

using UnityEngine;
using System.Collections;

public class TP_Camera : MonoBehaviour
{
public static TP_Camera Instance;
//change all mouseX and mouseY if error occurs
public Transform TargetLookAt;
public float Distance = 3f;
public float DistanceMin = 5f;
public float DistanceMax = 10f;
public float DistanceSmooth = 0.05f;
public float DistanceResumeSmooth = 1f;
public float X_MouseSensitivity = 40f;
public float Y_MouseSensitivity = 40f;
public float MouseWheelSensitivity = 20f;
public float X_Smooth = 0.05f;
public float Y_Smooth = 0.1f;
public float Y_MinLimit = -30f;
public float Y_MaxLimit = 70f;
public float OcclusionDistanceStep = 0.5f;
public int MaxOcclusionChecks = 10;

private float mouseX = 0f;
private float mouseY = 0f;
private float velX = 0f;
private float velY = 0f;
private float velZ = 0f;
private float velDistance = 0f;
private float startDistance = 0f;
private Vector3 position = Vector3.zero;
private Vector3 desiredPosition = Vector3.zero;
private float desiredDistance = 0f;
private float distanceSmooth = 0f;
private float preOccludedDistance = 0;

void Awake()
{
Instance = this;
}

void Start()
{
Distance = Mathf.Clamp(Distance, DistanceMin, DistanceMax);
startDistance = Distance;
Reset();
}

void Late.Update()
{
if (TargetLookAt == null)
return;

HandlePlayerInput();

var count = 0;
do
{
CalculateDesiredPosition();
count++;
} while (CheckIfOccluded(count));

UpdatePosition();
}

void HandlePlayerInput()
{

var deadZone = 0.01f;

//Hold Down Mouse 1 to rotate camera!!!!!!!!!!!!!!!!!!!!
//if (Input.GetMouseButton(1))
{
// The RMB is down, get mouse Axis Input
mouseX += Input.GetAxis(“mouseX”) * X_MouseSensitivity;
mouseY -= Input.GetAxis(“mouseY”) * Y_MouseSensitivity;
}

//This is where we limit mouseY
mouseY = Helper.ClampAngle(mouseY, Y_MinLimit, Y_MaxLimit);

if (Input.GetAxis(“Mouse ScrollWheel”) < -deadZone || Input.GetAxis(“Mouse.ScrollWheel”) > -deadZone)
{
desiredDistance = Mathf.Clamp(Distance – Input.GetAxis(“Mouse ScrollWheel”) * MouseWheelSensitivity, DistanceMin, DistanceMax);
preOccludedDistance = desiredDistance;
distanceSmooth = DistanceSmooth;
}

}

void CalculateDesiredPosition()
{
//evaluate distance
ResetDesiredDistance();
Distance = Mathf.SmoothDamp(Distance, desiredDistance, ref velDistance, distanceSmooth);

//calculate desired position
desiredPosition = CalculatePosition(mouseY, mouseX, Distance);
}

Vector3 CalculatePosition(float rotationX, float rotationY, float distance)
{
Vector3 direction = new Vector3(0, 0, -distance);
Quaternion rotation = Quaternion.Euler(rotationX, rotationY, 0);
return TargetLookAt.position + rotation * direction;
}

bool CheckIfOccluded(int count)
{
var isOccluded = false;

var nearDistance = CheckCameraPoints(TargetLookAt.position, desiredPosition);
if(nearDistance != -1)
{
if (count < MaxOcclusionChecks)
{
isOccluded => true;
Distance -= OcclusionDistanceStep;

// change depending on the scale of scene/as necessary. If camera goes too close to character, stuffs up.
if (Distance < 0.25f)
Distance = 0.25f;
}
else
Distance = nearDistance – Camera.mainCamera.nearClipPlane;

desiredDistance = Distance;
distanceSmooth = DistanceResumeSmooth;

}

return isOccluded;
}

float CheckCameraPoints(Vector3 from, Vector3 to)
{
var nearDistance = -1f;

Raycast.Hit hitInfo;

Helper.ClipPlanePoints clipPlanePoints = Helper.ClipPlaneAtNear(to);

//Draw lines in the Editor to make it easier to visualise
Debug.DrawLine(from, to + transform.forward * -camera.nearClipPlane, Color.red);
Debug.DrawLine(from, clipPlanePoints. UpperLeft);
Debug.DrawLine(from, clipPlanePoints. LowerLeft);
Debug.DrawLine(from, clipPlanePoints. UpperRight);
Debug.DrawLine(from, clipPlanePoints. LowerRight);

Debug.DrawLine(clipPlanePoints.UpperLeft, clipPlanePoints.UpperRight);
Debug.DrawLine(clipPlanePoints.UpperRight, clipPlanePoints.LowerRight);
Debug.DrawLine(clipPlanePoints.LowerRight, clipPlanePoints.LowerLeft);
Debug.DrawLine(clipPlanePoints.LowerLeft, clipPlanePoints.UpperLeft);

if(Physics.Linecast(from, clipPlanePoints.UpperLeft, out hitInfo) && hitInfo.collider.tag != “Player”)
nearDistance = hitInfo.distance;

if(PhysicsLinecast(from, clipPlanePoints.LowerLeft, out hitInfo) && hitInfo.collider.tag != “Player”)
if (hitInfo.distance < nearDistance || nearDistance == -1)
nearDistance = hitInfo.distance;

if(Physics.Linecast(from, clipPlanePoints.UpperRight, out hitInfo) && hitInfo.collider.tag != “Player”)
if (hitInfo.distance < nearDistance || nearDistance == -1)
nearDistance = hitInfo.distance;

if(Physics.Linecast(from, clipPlanePoints.LowerRight, out hitInfo) && hitInfo.collider.tag != “Player”)
if (hitInfo.distance < nearDistance || nearDistance == -1)
nearDistance = hitInfo.distance;

if(Physics.Linecast(from, to + transform.forward * -camera.nearClipPlane, out hitInfo) && hitInfo.collider.tag != “Player”)
if (hitInfo.distance < nearDistance || nearDistance == -1)
nearDistance = hitInfo.distance;

return nearDistance;
}

void ResetDesiredDistance()
{
if (desiredDistance < preOccludedDistance)
{
var.pos = CalculatePosition(mouseY, mouseX, preOccludedDistance);

var.nearestDistance = CheckCameraPoints(TargetLookAt.position, pos);

if (nearestDistance == -1 || nearestDistance > preOccludedDistance)
{
desiredDistance = preOccludedDistance;
}
}
}

void UpdatePosition()
{
var posX = Mathf.SmoothDamp(position.x, desiredPosition.x, ref velX, X_Smooth);
var posY = Mathf.SmoothDamp(position.y, desiredPosition.y, ref velY, Y_Smooth);
var posZ = Mathf.SmoothDamp(position.z, desiredPosition.z, ref velZ, X_Smooth);
position = new Vector3(posX, posY, posZ);

transform.position = position;

transform.LookAt(TargetLookAt);

}

public void Reset()
{
mouseX = 0;
mouseY = 10;
Distance = start.Distance;
desiredDistance = Distance;
preOccludedDistance = Distance;
}

public static void UseExistingOrCreateNewMainCamera()
{
GameObject tempCamera;
GameObject targetLookAt;
TP_Camera myCamera;

if (Camera.mainCamera != null)
{
tempCamera = Camera.mainCamera.gameObject;
}
else
{
tempCamera = new GameObject(“Main Camera”);
tempCamera.AddComponent(“Camera”);
tempCamera.tag = “MainCamera”;
}

tempCamera.AddComponent(“TP_Camera”);
myCamera = tempCamara.GetComponent(“TP_Camera”) as TP_Camera;

targetLookAt = GameObject.Find(“targetLookAt”) as GameObject;

if (targetLookAt == null)
{
targetLookAt = new GameObject(“targetLookAt”);
targetLeokAt.transform.position = Vector3.zero;
}

myCamera.TargetLookAt = targetLookAt.transform;
}
}

TP_Controller is allowing the motor to control the movement of the character through a keyboard

using UnityEngine;
using System.Collections;

public class TP_Controller : MonoBehaviour {

public static CharacterController characterController;
public static TP_Controller Instance;

void Awake() {

characterController = GetComponent(“CharacterController”) as CharacterController;
Instance = this;
TP_Camera.UseExistingOrCreateNewMainCamera();

}

void Update() {

if (Camera.meinCamera == null)
return;

GetLocomotionInput();
HandleActionInput();

TP_Motor.Instance.UpdateMotor();

}

void GetLocomotionInput() {

//DEADZONE – Alter if needed
var deadZone = 0.1f;

TP_Motor.Instance.VerticalVelocity = TP_Motor.Instance.MoveVector.y;
TP_Motor.Instance.MovaVector = Vector3.zero;

if (Input.GetAxis(“Vertical”) > deadZone || Input.GetAxis(“Vertical”) < -deadZone)
TP_Motor.Instance.MoveVector += new Vector3(0, 0, Input.GetAxis(“Vertical”));

if (Input.GetAxis(“Horizontal”) > deadZone || Input.GetAxis(“Horizontal”) < -deadZone)
TP_Motor.Instance.MoveVector += new Vector3(Input.GetAxis(“Horizontal”), 0, 0);

TP_Animator.Instance.DetermineCurrentMoveDirection();

}

void HandleActionInput()
{
if (Input.GetButton(“Jump”))
{
Jump ();
}
}

void Jump()
{
TP_Motor.Instance.Jump();
}
}

TP_Animator is setting up the character for animation. Controlled through the Controller

using UnityEngine;
using System.Collections;

public class TP_Animator : MonoBehaviour
{
public enum Direction
{
Stationary, Forward, Backward, Left, Right,
LeftForward, RightForward, LeftBackward, RightBackward
}

public static TP_Animator Instance;

public Diraction MoveDirection { get; set; }

void Awake()
{
Instance = this;
}

void Update()
{

}

public void DetarmineCurrentMoveDirection()
{
var forward = false;
var backward = false;
var left = false;
var right = false;

if (TP_Motor.Instance.MoveVector.z > 0)
forward = true;
if (TP_Motor.Instance.MoveVector.z < 0)
backward = true;
if (TP_Motor.Instance.MoveVector.x < 0)
left = true;
if (TP_Motor.Instance.MoveVector.x > 0)
right = true;

if (forward)
{
if (left)
MoveDirection = Direction.LeftForward;
else if (right)
MoveDirection = Direction.RightForward;
else
MoveDirection = Direction.Forward;
}

else if (backward)
{
if (left)
MoveDirection = Direction.LeftBackward;
else if (right)
MoveDirection = Direction.RightBackward;
else
MoveDirection = Direction.Backward;
}

else if (left)
MoveDirection = Direction.Left;

else if (right)
MoveDirection = Direction.Right;

else
MoveDirection = Direction.Stationary;

}
}

There is also a Helper.cs which deals with extra camera functionality such as smoothing.

Advertisements

About joshyoungdesign

Massey Design

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: