Files
ClearTheZone/.vs/CopilotSnapshots/80B56B6AD3425A4CB6C42A1F66934898/5D9C76A54131F94EB32AD7F604D1770E/5B5FCA03A0103645D2970C452CF1E542
T

321 lines
11 KiB
Plaintext

namespace StarterAssets
{
using UnityEngine;
using UnityEngine.InputSystem;
[RequireComponent(typeof(CharacterController))]
[RequireComponent(typeof(PlayerInput))]
public class ThirdPersonController : MonoBehaviour
{
public float MoveSpeed = 2.0f;
public float SprintSpeed = 5.335f;
public float SpeedChangeRate = 10.0f;
public float JumpHeight = 1.2f;
public float Gravity = -15.0f;
public float JumpTimeout = 0.50f;
public float FallTimeout = 0.15f;
public bool Grounded = true;
public float GroundedOffset = -0.14f;
public float GroundedRadius = 0.28f;
public LayerMask GroundLayers;
public Camera PlayerCamera;
public float TopClamp = 70.0f;
public float BottomClamp = -30.0f;
public float CameraAngleOverride = 0.0f;
public bool LockCameraPosition = false;
public GameObject[] Items;
private int currentItemIndex = 0;
private float _cinemachineTargetYaw;
private float _cinemachineTargetPitch;
private float _speed;
private float _verticalVelocity;
private float _terminalVelocity = 53.0f;
private float _jumpTimeoutDelta;
private float _fallTimeoutDelta;
private PlayerInput _playerInput;
private CharacterController _controller;
private StarterAssetsInputs _input;
private Animator _animator;
private int _animIDSpeed;
private int _animIDGrounded;
private int _animIDJump;
private int _animIDFreeFall;
private int _animIDMotionSpeed;
private const float _threshold = 0.01f;
private bool _hasAnimator;
private bool IsCurrentDeviceMouse
{
get
{
return _playerInput != null && _playerInput.currentControlScheme == "KeyboardMouse";
}
}
private void Awake()
{
if (PlayerCamera == null)
{
PlayerCamera = Camera.main;
}
}
private void Start()
{
_cinemachineTargetYaw = PlayerCamera.transform.rotation.eulerAngles.y;
_controller = GetComponent<CharacterController>();
_input = GetComponent<StarterAssetsInputs>();
_hasAnimator = TryGetComponent(out _animator);
_playerInput = GetComponent<PlayerInput>();
AssignAnimationIDs();
_jumpTimeoutDelta = JumpTimeout;
_fallTimeoutDelta = FallTimeout;
ActivateItem(currentItemIndex);
}
private void Update()
{
_hasAnimator = TryGetComponent(out _animator);
JumpAndGravity();
GroundedCheck();
Move();
HandleItemSwitch();
}
private void LateUpdate()
{
CameraRotation();
}
private void AssignAnimationIDs()
{
_animIDSpeed = Animator.StringToHash("Speed");
_animIDGrounded = Animator.StringToHash("Grounded");
_animIDJump = Animator.StringToHash("Jump");
_animIDFreeFall = Animator.StringToHash("FreeFall");
_animIDMotionSpeed = Animator.StringToHash("MotionSpeed");
}
private void GroundedCheck()
{
Vector3 spherePosition = new Vector3(transform.position.x, transform.position.y - GroundedOffset,
transform.position.z);
//https://docs.unity3d.com/6000.4/Documentation/ScriptReference/Physics.CheckSphere.html
Grounded = Physics.CheckSphere(spherePosition, GroundedRadius, GroundLayers,
QueryTriggerInteraction.Ignore);
if (_hasAnimator)
{
_animator.SetBool(_animIDGrounded, Grounded);
}
}
private void CameraRotation()
{
if (_input.look.sqrMagnitude >= _threshold && !LockCameraPosition)
{
float deltaTimeMultiplier = IsCurrentDeviceMouse ? 1.0f : Time.deltaTime;
_cinemachineTargetYaw += _input.look.x * deltaTimeMultiplier;
_cinemachineTargetPitch += _input.look.y * deltaTimeMultiplier;
}
_cinemachineTargetYaw = ClampAngle(_cinemachineTargetYaw, float.MinValue, float.MaxValue);
_cinemachineTargetPitch = ClampAngle(_cinemachineTargetPitch, BottomClamp, TopClamp);
PlayerCamera.transform.rotation = Quaternion.Euler(_cinemachineTargetPitch + CameraAngleOverride,
_cinemachineTargetYaw, 0.0f);
transform.rotation = Quaternion.Euler(0.0f, _cinemachineTargetYaw, 0.0f);
}
private void Move()
{
float targetSpeed = _input.sprint ? SprintSpeed : MoveSpeed;
if (_input.move == Vector2.zero) targetSpeed = 0.0f;
float currentHorizontalSpeed = new Vector3(_controller.velocity.x, 0.0f, _controller.velocity.z).magnitude;
float speedOffset = 0.1f;
float inputMagnitude = _input.analogMovement ? _input.move.magnitude : 1f;
if (currentHorizontalSpeed < targetSpeed - speedOffset ||
currentHorizontalSpeed > targetSpeed + speedOffset)
{
_speed = Mathf.Lerp(currentHorizontalSpeed, targetSpeed * inputMagnitude,
Time.deltaTime * SpeedChangeRate);
_speed = Mathf.Round(_speed * 1000f) / 1000f;
}
else
{
_speed = targetSpeed;
}
Vector3 inputDirection = new Vector3(_input.move.x, 0.0f, _input.move.y).normalized;
Vector3 moveDirection = PlayerCamera.transform.right * inputDirection.x + PlayerCamera.transform.forward * inputDirection.z;
moveDirection.y = 0f;
_controller.Move(moveDirection.normalized * (_speed * Time.deltaTime) +
new Vector3(0.0f, _verticalVelocity, 0.0f) * Time.deltaTime);
if (_hasAnimator)
{
_animator.SetFloat(_animIDSpeed, _speed);
_animator.SetFloat(_animIDMotionSpeed, inputMagnitude);
}
}
private void JumpAndGravity()
{
if (Grounded)
{
_fallTimeoutDelta = FallTimeout;
if (_hasAnimator)
{
_animator.SetBool(_animIDJump, false);
_animator.SetBool(_animIDFreeFall, false);
}
if (_verticalVelocity < 0.0f)
{
_verticalVelocity = -2f;
}
if (_input.jump && _jumpTimeoutDelta <= 0.0f)
{
_verticalVelocity = Mathf.Sqrt(JumpHeight * -2f * Gravity);
if (_hasAnimator)
{
_animator.SetBool(_animIDJump, true);
}
}
if (_jumpTimeoutDelta >= 0.0f)
{
_jumpTimeoutDelta -= Time.deltaTime;
}
}
else
{
_jumpTimeoutDelta = JumpTimeout;
if (_fallTimeoutDelta >= 0.0f)
{
_fallTimeoutDelta -= Time.deltaTime;
}
else
{
if (_hasAnimator)
{
_animator.SetBool(_animIDFreeFall, true);
}
}
_input.jump = false;
}
if (_verticalVelocity < _terminalVelocity)
{
_verticalVelocity += Gravity * Time.deltaTime;
}
}
private static float ClampAngle(float lfAngle, float lfMin, float lfMax)
{
if (lfAngle < -360f) lfAngle += 360f;
if (lfAngle > 360f) lfAngle -= 360f;
return Mathf.Clamp(lfAngle, lfMin, lfMax);
}
private void HandleItemSwitch()
{
float scroll = Input.GetAxis("Mouse ScrollWheel");
if (scroll > 0f)
{
currentItemIndex = (currentItemIndex + 1) % Items.Length;
ActivateItem(currentItemIndex);
}
else if (scroll < 0f)
{
currentItemIndex = (currentItemIndex - 1 + Items.Length) % Items.Length;
ActivateItem(currentItemIndex);
}
}
private void ActivateItem(int index)
{
for (int i = 0; i < Items.Length; i++)
{
if (Items[i] != null)
{
Items[i].SetActive(i == index);
if (i == index)
{
// https://docs.unity3d.com/ScriptReference/Transform.SetParent.html
Items[i].transform.SetParent(PlayerCamera.transform);
// https://docs.unity3d.com/ScriptReference/Transform-localPosition.html
Items[i].transform.localPosition = new Vector3(0.4f, -0.3f, 0.7f);
// https://docs.unity3d.com/ScriptReference/Transform-localRotation.html
Items[i].transform.localRotation = Quaternion.identity;
}
}
}
}
private Vector2 lastLook;
private Vector2 wiggleOffset;
private void LateUpdate()
{
CameraRotation();
UpdateItemWiggle();
}
private void UpdateItemWiggle()
{
if (Items != null && Items.Length > 0 && Items[currentItemIndex] != null && Items[currentItemIndex].activeSelf)
{
// https://docs.unity3d.com/ScriptReference/Vector2.Lerp.html
Vector2 lookDelta = _input.look - lastLook;
lastLook = _input.look;
wiggleOffset = Vector2.Lerp(wiggleOffset, lookDelta * 0.05f, 0.2f);
Items[currentItemIndex].transform.localPosition = new Vector3(0.4f + wiggleOffset.x, -0.3f + wiggleOffset.y, 0.7f);
}
}
private void OnFootstep()
{
}
private void OnDrawGizmosSelected()
{
Color transparentGreen = new Color(0.0f, 1.0f, 0.0f, 0.35f);
Color transparentRed = new Color(1.0f, 0.0f, 0.0f, 0.35f);
if (Grounded) Gizmos.color = transparentGreen;
else Gizmos.color = transparentRed;
Gizmos.DrawSphere(
new Vector3(transform.position.x, transform.position.y - GroundedOffset, transform.position.z),
GroundedRadius);
}
}
}