223 lines
8.5 KiB
C#
223 lines
8.5 KiB
C#
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;
|
|
|
|
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;
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
JumpAndGravity();
|
|
GroundedCheck();
|
|
Move();
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
//https://docs.unity3d.com/6000.4/Documentation/ScriptReference/CharacterController.Move.html
|
|
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);
|
|
}
|
|
}
|
|
|
|
//https://docs.unity3d.com/6000.4/Documentation/ScriptReference/Mathf.Sqrt.html
|
|
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 OnFootstep(AnimationEvent animationEvent)
|
|
{
|
|
}
|
|
|
|
// Die beiden teile sind einfach da damit das spiel nicht einfriert, immernoch keinen plan warum, aber es ist so
|
|
private void OnLand(AnimationEvent animationEvent)
|
|
{
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
} |