254 lines
8.3 KiB
C#
254 lines
8.3 KiB
C#
using UnityEngine;
|
|
|
|
namespace GPUInstancer
|
|
{
|
|
// Note: This is a stripped down version of the FirstPersonController script from the Unity Standard Assets package.
|
|
// It's dependencies have been removed/modified and it has been taken into the GPUInstancer namespace to avoid conflicts.
|
|
// This class is only used in the demo scenes that showcase the GPU Instancer capabilities.
|
|
|
|
[RequireComponent(typeof (CharacterController))]
|
|
public class FPController : MonoBehaviour
|
|
{
|
|
[SerializeField] public float m_WalkSpeed;
|
|
[SerializeField] public float m_RunSpeed;
|
|
[SerializeField] public float m_JumpSpeed;
|
|
|
|
private bool m_IsWalking;
|
|
private MouseLook m_MouseLook;
|
|
private Camera m_Camera;
|
|
private bool m_Jump;
|
|
private float m_YRotation;
|
|
private Vector2 m_Input;
|
|
private Vector3 m_MoveDir = Vector3.zero;
|
|
private CharacterController m_CharacterController;
|
|
private CollisionFlags m_CollisionFlags;
|
|
private bool m_PreviouslyGrounded;
|
|
private bool m_Jumping;
|
|
private float m_StickToGroundForce = 10f;
|
|
private float m_GravityMultiplier = 2f;
|
|
|
|
private void Start()
|
|
{
|
|
m_CharacterController = GetComponent<CharacterController>();
|
|
m_Camera = Camera.main;
|
|
m_Jumping = false;
|
|
m_MouseLook = new MouseLook();
|
|
m_MouseLook.Init(transform , m_Camera.transform);
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
RotateView();
|
|
// the jump state needs to read here to make sure it is not missed
|
|
if (!m_Jump && Cursor.lockState == CursorLockMode.Locked)
|
|
{
|
|
m_Jump = Input.GetButtonDown("Jump");
|
|
}
|
|
|
|
if (!m_PreviouslyGrounded && m_CharacterController.isGrounded)
|
|
{
|
|
m_MoveDir.y = 0f;
|
|
m_Jumping = false;
|
|
}
|
|
if (!m_CharacterController.isGrounded && !m_Jumping && m_PreviouslyGrounded)
|
|
{
|
|
m_MoveDir.y = 0f;
|
|
}
|
|
|
|
m_PreviouslyGrounded = m_CharacterController.isGrounded;
|
|
}
|
|
|
|
|
|
private void FixedUpdate()
|
|
{
|
|
float speed;
|
|
GetInput(out speed);
|
|
// always move along the camera forward as it is the direction that it being aimed at
|
|
Vector3 desiredMove = transform.forward*m_Input.y + transform.right*m_Input.x;
|
|
|
|
// get a normal for the surface that is being touched to move along it
|
|
RaycastHit hitInfo;
|
|
Physics.SphereCast(transform.position, m_CharacterController.radius, Vector3.down, out hitInfo,
|
|
m_CharacterController.height/2f, Physics.AllLayers, QueryTriggerInteraction.Ignore);
|
|
desiredMove = Vector3.ProjectOnPlane(desiredMove, hitInfo.normal).normalized;
|
|
|
|
m_MoveDir.x = desiredMove.x*speed;
|
|
m_MoveDir.z = desiredMove.z*speed;
|
|
|
|
|
|
if (m_CharacterController.isGrounded)
|
|
{
|
|
m_MoveDir.y = -m_StickToGroundForce;
|
|
|
|
if (m_Jump)
|
|
{
|
|
m_MoveDir.y = m_JumpSpeed;
|
|
m_Jump = false;
|
|
m_Jumping = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_MoveDir += Physics.gravity*m_GravityMultiplier*Time.fixedDeltaTime;
|
|
}
|
|
m_CollisionFlags = m_CharacterController.Move(m_MoveDir*Time.fixedDeltaTime);
|
|
|
|
m_MouseLook.UpdateCursorLock();
|
|
}
|
|
|
|
private void GetInput(out float speed)
|
|
{
|
|
// Read input
|
|
float horizontal = Input.GetAxis("Horizontal");
|
|
float vertical = Input.GetAxis("Vertical");
|
|
|
|
// On standalone builds, walk/run speed is modified by a key press.
|
|
// keep track of whether or not the character is walking or running
|
|
m_IsWalking = !Input.GetKey(KeyCode.LeftShift);
|
|
|
|
// set the desired speed to be walking or running
|
|
speed = m_IsWalking ? m_WalkSpeed : m_RunSpeed;
|
|
m_Input = new Vector2(horizontal, vertical);
|
|
|
|
// normalize input if it exceeds 1 in combined length:
|
|
if (m_Input.sqrMagnitude > 1)
|
|
{
|
|
m_Input.Normalize();
|
|
}
|
|
}
|
|
|
|
|
|
private void RotateView()
|
|
{
|
|
m_MouseLook.LookRotation (transform, m_Camera.transform);
|
|
}
|
|
|
|
|
|
private void OnControllerColliderHit(ControllerColliderHit hit)
|
|
{
|
|
Rigidbody body = hit.collider.attachedRigidbody;
|
|
//dont move the rigidbody if the character is on top of it
|
|
if (m_CollisionFlags == CollisionFlags.Below)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (body == null || body.isKinematic)
|
|
{
|
|
return;
|
|
}
|
|
body.AddForceAtPosition(m_CharacterController.velocity*0.1f, hit.point, ForceMode.Impulse);
|
|
}
|
|
}
|
|
|
|
public class MouseLook
|
|
{
|
|
public float XSensitivity = 2f;
|
|
public float YSensitivity = 2f;
|
|
public bool clampVerticalRotation = true;
|
|
public float MinimumX = -90F;
|
|
public float MaximumX = 90F;
|
|
public bool smooth;
|
|
public float smoothTime = 5f;
|
|
public bool lockCursor = true;
|
|
|
|
|
|
private Quaternion m_CharacterTargetRot;
|
|
private Quaternion m_CameraTargetRot;
|
|
private bool m_cursorIsLocked = true;
|
|
|
|
public void Init(Transform character, Transform camera)
|
|
{
|
|
m_CharacterTargetRot = character.localRotation;
|
|
m_CameraTargetRot = camera.localRotation;
|
|
}
|
|
|
|
|
|
public void LookRotation(Transform character, Transform camera)
|
|
{
|
|
if (m_cursorIsLocked)
|
|
{
|
|
float yRot = Input.GetAxis("Mouse X") * XSensitivity;
|
|
float xRot = Input.GetAxis("Mouse Y") * YSensitivity;
|
|
|
|
m_CharacterTargetRot *= Quaternion.Euler(0f, yRot, 0f);
|
|
m_CameraTargetRot *= Quaternion.Euler(-xRot, 0f, 0f);
|
|
|
|
if (clampVerticalRotation)
|
|
m_CameraTargetRot = ClampRotationAroundXAxis(m_CameraTargetRot);
|
|
|
|
if (smooth)
|
|
{
|
|
character.localRotation = Quaternion.Slerp(character.localRotation, m_CharacterTargetRot,
|
|
smoothTime * Time.deltaTime);
|
|
camera.localRotation = Quaternion.Slerp(camera.localRotation, m_CameraTargetRot,
|
|
smoothTime * Time.deltaTime);
|
|
}
|
|
else
|
|
{
|
|
character.localRotation = m_CharacterTargetRot;
|
|
camera.localRotation = m_CameraTargetRot;
|
|
}
|
|
}
|
|
UpdateCursorLock();
|
|
}
|
|
|
|
public void SetCursorLock(bool value)
|
|
{
|
|
lockCursor = value;
|
|
if (!lockCursor)
|
|
{//we force unlock the cursor if the user disable the cursor locking helper
|
|
Cursor.lockState = CursorLockMode.None;
|
|
Cursor.visible = true;
|
|
}
|
|
}
|
|
|
|
public void UpdateCursorLock()
|
|
{
|
|
//if the user set "lockCursor" we check & properly lock the cursos
|
|
if (lockCursor)
|
|
InternalLockUpdate();
|
|
}
|
|
|
|
private void InternalLockUpdate()
|
|
{
|
|
if (Input.GetKeyUp(KeyCode.Escape))
|
|
{
|
|
m_cursorIsLocked = false;
|
|
}
|
|
else if (Input.GetMouseButtonUp(0))
|
|
{
|
|
m_cursorIsLocked = true;
|
|
}
|
|
|
|
if (m_cursorIsLocked)
|
|
{
|
|
Cursor.lockState = CursorLockMode.Locked;
|
|
Cursor.visible = false;
|
|
}
|
|
else if (!m_cursorIsLocked)
|
|
{
|
|
Cursor.lockState = CursorLockMode.None;
|
|
Cursor.visible = true;
|
|
}
|
|
}
|
|
|
|
Quaternion ClampRotationAroundXAxis(Quaternion q)
|
|
{
|
|
q.x /= q.w;
|
|
q.y /= q.w;
|
|
q.z /= q.w;
|
|
q.w = 1.0f;
|
|
|
|
float angleX = 2.0f * Mathf.Rad2Deg * Mathf.Atan(q.x);
|
|
|
|
angleX = Mathf.Clamp(angleX, MinimumX, MaximumX);
|
|
|
|
q.x = Mathf.Tan(0.5f * Mathf.Deg2Rad * angleX);
|
|
|
|
return q;
|
|
}
|
|
|
|
}
|
|
}
|