using System; using DarkTonic.MasterAudio; using Rewired; using UFS2.Gameplay; using UnityEngine; using UnityEngine.Events; using UnityStandardAssets.Utility; namespace UnityStandardAssets.Characters.FirstPerson { [RequireComponent(typeof(CharacterController))] [RequireComponent(typeof(AudioSource))] public class FirstPersonController : MonoBehaviour { [Serializable] public class PlayTransformEvent : UnityEvent { } [Serializable] public class PlayTranformMultiplier : UnityEvent { } [SerializeField] private bool m_IsWalking; [SerializeField] public float m_WalkSpeed; [SerializeField] public float m_RunSpeed; [SerializeField] [Range(0f, 1f)] private float m_RunstepLenghten; [SerializeField] private float m_JumpSpeed; [SerializeField] private float m_StickToGroundForce; [SerializeField] private float m_GravityMultiplier; [SerializeField] public MouseLook m_MouseLook; [SerializeField] private bool m_UseFovKick; [SerializeField] private FOVKick m_FovKick = new FOVKick(); [SerializeField] private bool m_UseHeadBob; [SerializeField] private CurveControlledBob m_HeadBob = new CurveControlledBob(); [SerializeField] private LerpControlledBob m_JumpBob = new LerpControlledBob(); [SerializeField] private float m_StepInterval; [SerializeField] private AudioClip[] m_FootstepSounds; [SerializeField] private AudioClip[] m_FootstepSoundsBridge; [SerializeField] private AudioClip[] m_FootstepSoundsStone; [SerializeField] private AudioClip m_JumpSound; [SerializeField] private AudioClip m_LandSound; [SerializeField] private Camera m_Camera; public Transform cameraTransform; private bool m_Jump; public bool frezzeRotation; public bool frezzePosition; public bool rotateMouseInFixedUpdate = true; public Vector2 m_Input; public Vector3 m_MoveDir = Vector3.zero; public CharacterController m_CharacterController; private CollisionFlags m_CollisionFlags; private bool m_PreviouslyGrounded; private Vector3 m_OriginalCameraPosition; private float m_StepCycle; private float m_NextStep; private bool m_Jumping; private AudioSource m_AudioSource; private string groundTypeTag = ""; public float horizontal; public float vertical; public bool isJumping; public bool isRuning; public PlayTransformEvent OnJump; public PlayTransformEvent OnLanding; public PlayTransformEvent OnBridgeStep; public PlayTransformEvent OnTerrainStep; public PlayTransformEvent OnStoneStep; public PlayTransformEvent OnResidenceWoodStep; public PlayTransformEvent OnResidenceTileStep; public PlayTransformEvent OnWaterMovementStep; public PlayTransformEvent OnWaterRunMovementStep; public bool notMove; [HideInInspector] public Vector3 lastValidPosition = Vector3.zero; public bool isWater; public static event Action OnJumpGlobal; public static event Action OnLandingGlobal; public static event Action OnBridgeStepGlobal; public static event Action OnTerrainStepGlobal; public static event Action OnStoneStepGlobal; public static event Action OnResidenceWoodStepGlobal; public static event Action OnResidenceTilesStepGlobal; public static event Action OnWaterMovementStepGlobal; public static event Action OnWaterRunMovementStepGlobal; private void Start() { m_CharacterController = GetComponent(); if (UnityEngine.Object.FindObjectOfType() == null) { m_Camera = UnityEngine.Object.FindObjectOfType().GetComponent(); } else { m_Camera = GetComponentInChildren(); } m_OriginalCameraPosition = m_Camera.transform.localPosition; m_FovKick.Setup(m_Camera); m_HeadBob.Setup(m_Camera, m_StepInterval); m_StepCycle = 0f; m_NextStep = m_StepCycle / 2f; m_Jumping = false; m_AudioSource = GetComponent(); m_MouseLook.Init(base.transform, cameraTransform); } private void Update() { if (!frezzeRotation && !rotateMouseInFixedUpdate) { RotateView(); } if (!m_Jump) { m_Jump = isJumping; } if (!m_PreviouslyGrounded && m_CharacterController.isGrounded) { StartCoroutine(m_JumpBob.DoBobCycle()); OnLanding?.Invoke(base.transform); FirstPersonController.OnLandingGlobal?.Invoke(base.transform); m_NextStep = m_StepCycle + 0.5f; 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 PlayLandingSound() { m_AudioSource.clip = m_LandSound; m_AudioSource.Play(); } private void FixedUpdate() { if (!frezzeRotation && rotateMouseInFixedUpdate) { RotateView(); } if (frezzePosition) { return; } GetInput(out var speed); Vector3 vector = base.transform.forward * m_Input.y + base.transform.right * m_Input.x; Physics.SphereCast(base.transform.position, m_CharacterController.radius, Vector3.down, out var hitInfo, m_CharacterController.height / 2f, -1, QueryTriggerInteraction.Ignore); vector = Vector3.ProjectOnPlane(vector, hitInfo.normal).normalized; m_MoveDir.x = vector.x * speed; m_MoveDir.z = vector.z * speed; if (m_CharacterController.isGrounded) { m_MoveDir.y = 0f - m_StickToGroundForce; if (m_Jump && !isWater) { if ((bool)base.transform.parent && base.transform.parent.gameObject.layer == LayerMask.NameToLayer("Boat")) { return; } m_MoveDir.y = m_JumpSpeed; OnJump?.Invoke(base.transform); FirstPersonController.OnJumpGlobal?.Invoke(base.transform); m_Jump = false; m_Jumping = true; } } else { m_MoveDir += Physics.gravity * m_GravityMultiplier * Time.fixedDeltaTime; } if (!notMove) { m_CollisionFlags = m_CharacterController.Move(m_MoveDir * Time.fixedDeltaTime); } ProgressStepCycle(speed); UpdateCameraPosition(speed); UpdateIsWater(); m_MouseLook.UpdateCursorLock(); } private void PlayJumpSound() { m_AudioSource.clip = m_JumpSound; m_AudioSource.Play(); } private void ProgressStepCycle(float speed) { if (m_CharacterController.velocity.sqrMagnitude > 0f && (m_Input.x != 0f || m_Input.y != 0f)) { m_StepCycle += (m_CharacterController.velocity.magnitude + speed * (m_IsWalking ? 1f : m_RunstepLenghten)) * Time.fixedDeltaTime; } if (m_StepCycle > m_NextStep) { m_NextStep = m_StepCycle + m_StepInterval; PlayFootStepAudio(); } } private void PlayFootStepAudio() { if (!m_CharacterController.isGrounded) { return; } if (groundTypeTag == "Bridge" || groundTypeTag == "Boat") { OnBridgeStep?.Invoke(base.transform); FirstPersonController.OnBridgeStepGlobal?.Invoke(base.transform); } else if (groundTypeTag == "Stone") { OnStoneStep?.Invoke(base.transform); FirstPersonController.OnStoneStepGlobal?.Invoke(base.transform); } else if (groundTypeTag == "Residence_Wood") { OnResidenceWoodStep?.Invoke(base.transform); FirstPersonController.OnResidenceWoodStepGlobal?.Invoke(base.transform); } else if (groundTypeTag == "Residence_Tiles") { OnResidenceTileStep?.Invoke(base.transform); FirstPersonController.OnResidenceTilesStepGlobal?.Invoke(base.transform); } else if (groundTypeTag == "WaterMovementCollider") { if (ReInput.players.GetPlayer(0).GetButton("runKey")) { MasterAudio.PlaySound3DAtTransform("Fantasy_Game_Footsteps_Water_1", base.transform).ActingVariation.VarAudio.pitch = 1.2f; } else { MasterAudio.PlaySound3DAtTransform("Fantasy_Game_Footsteps_Water_1", base.transform); } } else { OnTerrainStep?.Invoke(base.transform); FirstPersonController.OnTerrainStepGlobal?.Invoke(base.transform); } } private void UpdateCameraPosition(float speed) { if (m_UseHeadBob) { Vector3 localPosition; if (m_CharacterController.velocity.magnitude > 0f && m_CharacterController.isGrounded) { cameraTransform.transform.localPosition = m_HeadBob.DoHeadBob(m_CharacterController.velocity.magnitude + speed * (m_IsWalking ? 1f : m_RunstepLenghten)); localPosition = cameraTransform.transform.localPosition; localPosition.y = cameraTransform.transform.localPosition.y - m_JumpBob.Offset(); } else { localPosition = cameraTransform.transform.localPosition; localPosition.y = m_OriginalCameraPosition.y - m_JumpBob.Offset(); } cameraTransform.transform.localPosition = localPosition; } } private void UpdateIsWater() { isWater = GameWaterSystem.IsPositionUnderWater(base.transform.position + Vector3.down * m_CharacterController.height * 0.5f); } private void GetInput(out float speed) { bool isWalking = m_IsWalking; m_IsWalking = !isRuning; speed = (m_IsWalking ? m_WalkSpeed : m_RunSpeed); m_Input = new Vector2(horizontal, vertical); if (m_Input.sqrMagnitude > 1f) { m_Input.Normalize(); } if (m_IsWalking != isWalking && m_UseFovKick && m_CharacterController.velocity.sqrMagnitude > 0f) { StopAllCoroutines(); StartCoroutine((!m_IsWalking) ? m_FovKick.FOVKickUp() : m_FovKick.FOVKickDown()); } } public void RotateView() { m_MouseLook.LookRotation(base.transform, cameraTransform); } public void UnFrezzeLook() { frezzePosition = false; frezzeRotation = false; m_MouseLook.Init(base.transform, cameraTransform); } private void OnControllerColliderHit(ControllerColliderHit hit) { Rigidbody attachedRigidbody = hit.collider.attachedRigidbody; groundTypeTag = hit.collider.tag; if (!isWater && (groundTypeTag == "Terrain" || groundTypeTag == "Boat")) { lastValidPosition = base.transform.position; } if (m_CollisionFlags != CollisionFlags.Below && !(attachedRigidbody == null)) { _ = attachedRigidbody.isKinematic; } } private void OnTriggerStay(Collider other) { if (other.tag == "Water") { isWater = true; } } private void OnTriggerExit(Collider other) { if (other.tag == "Water") { isWater = false; } } } }