Instantly share code, notes, and snippets.
Created
December 23, 2016 12:00
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save eintopf/b3c4b8780847e63d9733fd84509522fa to your computer and use it in GitHub Desktop.
This class is an addition to the Unity Standard Asset Scripts (need to be imported in your project to get this gist working). This component can be used like the standard asset "First Person Controller", however it moves on the NavMesh (instead of colliders). This can save a lot of setup pain and performance.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using UnityEngine; | |
using UnityEngine.AI; | |
using UnityStandardAssets.Characters.FirstPerson; | |
using UnityStandardAssets.CrossPlatformInput; | |
namespace ZKW.PlayerMovement | |
{ | |
public class NavMeshPlayerMovement : MonoBehaviour | |
{ | |
private const string noPlayerNavmeshCheckTag = "No Player NavMesh Check"; | |
public Camera cam; | |
private float yWhileInNoCheckArea; | |
private bool isInNoCheckArea; | |
public MouseLook mouseLook = new MouseLook(); | |
public MovementSettings movementSettings = new MovementSettings(); | |
private Transform myTranform; | |
public bool Running | |
{ | |
get | |
{ | |
#if !MOBILE_INPUT | |
return movementSettings.Running; | |
#else | |
return false; | |
#endif | |
} | |
} | |
private void Start() | |
{ | |
myTranform = transform; | |
mouseLook.Init(myTranform, cam.transform); | |
} | |
private void Update() | |
{ | |
RotateView(); | |
var input = GetInput(); | |
if (!(Mathf.Abs(input.x) > float.Epsilon) && !(Mathf.Abs(input.y) > float.Epsilon)) return; | |
// always move along the camera forward as it is the direction that it being aimed at | |
var desiredMove = cam.transform.forward*input.y + cam.transform.right*input.x; | |
desiredMove = Vector3.ProjectOnPlane(desiredMove, Vector3.zero).normalized; | |
desiredMove.x = desiredMove.x*movementSettings.CurrentTargetSpeed; | |
desiredMove.z = desiredMove.z*movementSettings.CurrentTargetSpeed; | |
desiredMove.y = desiredMove.y*movementSettings.CurrentTargetSpeed; | |
var movement = desiredMove*Time.deltaTime; | |
if (movement.magnitude == 0) return; | |
var currPos = myTranform.position; | |
var desiredPos = currPos + movement; | |
if (isInNoCheckArea) | |
desiredPos.y = yWhileInNoCheckArea; | |
myTranform.position = desiredPos; | |
if (isInNoCheckArea) return; | |
movePlayerToNearestNavMeshPosition(desiredPos); | |
} | |
private void movePlayerToNearestNavMeshPosition(Vector3 curr) | |
{ | |
var distance = 0.01f; | |
var hit = new NavMeshHit(); | |
do | |
{ | |
NavMesh.SamplePosition(curr, out hit, distance, NavMesh.AllAreas); | |
distance *= 2f; | |
} while (!hit.hit); | |
myTranform.position = hit.position; | |
} | |
private void OnTriggerEnter(Collider other) | |
{ | |
if (other.tag != noPlayerNavmeshCheckTag) return; | |
isInNoCheckArea = true; | |
yWhileInNoCheckArea = myTranform.position.y; | |
} | |
private void OnTriggerExit(Collider other) | |
{ | |
if (other.tag == noPlayerNavmeshCheckTag) | |
isInNoCheckArea = false; | |
} | |
private Vector2 GetInput() | |
{ | |
var input = new Vector2 | |
{ | |
x = CrossPlatformInputManager.GetAxis("Horizontal"), | |
y = CrossPlatformInputManager.GetAxis("Vertical") | |
}; | |
movementSettings.UpdateDesiredTargetSpeed(input); | |
return input; | |
} | |
private void RotateView() | |
{ | |
//avoids the mouse looking if the game is effectively paused | |
if (Mathf.Abs(Time.timeScale) < float.Epsilon) return; | |
// get the rotation before it's changed | |
mouseLook.LookRotation(transform, cam.transform); | |
} | |
[Serializable] | |
public class MovementSettings | |
{ | |
public float BackwardSpeed = 4.0f; // Speed when walking backwards | |
[HideInInspector] public float CurrentTargetSpeed = 8f; | |
public float ForwardSpeed = 8.0f; // Speed when walking forward | |
public float JumpForce = 30f; | |
#if !MOBILE_INPUT | |
#endif | |
public KeyCode RunKey = KeyCode.LeftShift; | |
public float RunMultiplier = 2.0f; // Speed when sprinting | |
public float StrafeSpeed = 4.0f; // Speed when walking sideways | |
#if !MOBILE_INPUT | |
public bool Running { get; private set; } | |
#endif | |
public void UpdateDesiredTargetSpeed(Vector2 input) | |
{ | |
if (input == Vector2.zero) return; | |
if ((input.x > 0) || (input.x < 0)) | |
CurrentTargetSpeed = StrafeSpeed; | |
if (input.y < 0) | |
CurrentTargetSpeed = BackwardSpeed; | |
if (input.y > 0) | |
CurrentTargetSpeed = ForwardSpeed; | |
#if !MOBILE_INPUT | |
if (Input.GetKey(RunKey)) | |
{ | |
CurrentTargetSpeed *= RunMultiplier; | |
Running = true; | |
} | |
else | |
{ | |
Running = false; | |
} | |
#endif | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment