123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481 |
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- using Random = UnityEngine.Random;
- namespace HQFPSWeapons
- {
- public class FirstPersonCamera : MonoBehaviour
- {
- #region Internal
- #pragma warning disable 0649
- [Serializable]
- private class SpringsModule
- {
- public float SpringLerpSpeed = 25f;
- [Space]
- [Group]
- public SpringSettings ForceSprings = SpringSettings.Default;
- [Group]
- public SpringSettings HeadbobSprings = SpringSettings.Default;
- }
- [Serializable]
- private struct HeadbobsModule
- {
- [Group]
- public CameraHeadBob WalkHeadbob;
- [Group]
- public CameraHeadBob CrouchHeadbob;
- [Group]
- public CameraHeadBob RunHeadbob;
- }
- [Serializable]
- private struct ShakesModule
- {
- public Spring.Data ShakeSpringSettings;
- public CameraShakeSettings ExplosionShake;
- public CameraShakeSettings DeathShake;
- }
- [Serializable]
- private struct FallImpactModule
- {
- [MinMax(0f, 50f)]
- public Vector2 FallImpactRange;
- public SpringForce PosForce;
- public SpringForce RotForce;
- }
- [Serializable]
- private struct JumpForceModule
- {
- public SpringForce PosForce;
- public SpringForce RotForce;
- }
- [Serializable]
- private struct GettingHitForceModule
- {
- [Range(0f, 10f)]
- public float PosForce;
- [Range(0f, 10f)]
- public float RotForce;
- }
- #pragma warning restore 0649
- #endregion
- public CameraHeadBob AimHeadBob { get; set; }
- public Camera UnityCamera { get { return m_Camera; } }
- [BHeader("General", true)]
- [SerializeField]
- private Camera m_Camera = null;
- [SerializeField]
- private Player m_Player = null;
- [Space]
- [SerializeField, Group()]
- private SpringsModule m_Springs = null;
- [SerializeField, Group()]
- private HeadbobsModule m_Headbobs = new HeadbobsModule();
- [SerializeField, Group()]
- private ShakesModule m_CamShakes = new ShakesModule();
- [SerializeField, Group()]
- private FallImpactModule m_FallImpact = new FallImpactModule();
- [SerializeField, Group()]
- private JumpForceModule m_JumpForce = new JumpForceModule();
- [SerializeField, Group()]
- private GettingHitForceModule m_GettingHitForce = new GettingHitForceModule();
- // Springs
- private Spring m_PositionSpring_Force;
- private Spring m_RotationSpring_Force;
- private Spring m_PositionSpring_Headbob;
- private Spring m_RotationSpring_Headbob;
- private Spring m_PositionShakeSpring;
- private Spring m_RotationShakeSpring;
- private Spring m_PositionRecoilSpring;
- private Spring m_RotationRecoilSpring;
- // Headbob
- private CameraHeadBob m_CurrentHeadbob;
- private float m_CurrentBobParam;
- private Vector3 m_FadeOutBob_Pos;
- private Vector3 m_FadeOutBob_Rot;
- private Vector3 m_FadeInBob_Pos;
- private Vector3 m_FadeInBob_Rot;
- private float m_FadeOutBobMult;
- private float m_FadeInBobMult;
- private float m_FadeInStartTime;
- private int m_LastFootDown;
- // Shakes
- private List<CameraShake> m_Shakes = new List<CameraShake>();
- public bool Raycast(float maxDistance, LayerMask mask, out RaycastHit hitInfo, QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.Ignore)
- {
- return Physics.Raycast(new Ray(m_Camera.transform.position, m_Camera.transform.forward), out hitInfo, maxDistance, mask, queryTriggerInteraction);
- }
- public void AdjustRecoilSettings(Spring.Data rotSpringData, Spring.Data posSpringData)
- {
- m_PositionRecoilSpring.Adjust(posSpringData);
- m_RotationRecoilSpring.Adjust(rotSpringData);
- }
- public void ApplyRecoil(RecoilForce force, float forceMultiplier = 1f)
- {
- force.PlayRecoilForce(forceMultiplier, m_RotationRecoilSpring, m_PositionRecoilSpring);
- }
- public void AddPositionForce(Vector3 positionForce, int distribution = 1)
- {
- m_FadeInBobMult = 0f;
- m_FadeInStartTime = Time.time + 1f;
- if (distribution <= 1)
- m_PositionSpring_Force.AddForce(positionForce);
- else
- m_PositionSpring_Force.AddDistributedForce(positionForce, distribution);
- }
- public void AddRotationForce(Vector3 rotationForce, int distribution = 1)
- {
- m_FadeInBobMult = 0f;
- m_FadeInStartTime = Time.time + 1f;
- if (distribution <= 1)
- m_RotationSpring_Force.AddForce(rotationForce);
- else
- m_RotationSpring_Force.AddDistributedForce(rotationForce, distribution);
- }
- public void DoShake(CameraShakeSettings shake, float scale)
- {
- m_Shakes.Add(new CameraShake(shake, m_PositionShakeSpring, m_RotationShakeSpring, scale));
- }
- public void AddExplosionShake(float scale)
- {
- m_Shakes.Add(new CameraShake(m_CamShakes.ExplosionShake, m_PositionShakeSpring, m_RotationShakeSpring, scale));
- }
- public void OnPlayerDeath()
- {
- m_Shakes.Add(new CameraShake(m_CamShakes.DeathShake, m_PositionShakeSpring, m_RotationShakeSpring, 1f));
- }
- private void Awake()
- {
- // Force Springs
- m_PositionSpring_Force = new Spring(Spring.Type.OverrideLocalPosition, m_Camera.transform);
- m_PositionSpring_Force.Adjust(m_Springs.ForceSprings.Position.Stiffness, m_Springs.ForceSprings.Position.Damping);
- m_RotationSpring_Force = new Spring(Spring.Type.OverrideLocalRotation, m_Camera.transform);
- m_RotationSpring_Force.Adjust(m_Springs.ForceSprings.Rotation.Stiffness, m_Springs.ForceSprings.Rotation.Damping);
- m_PositionSpring_Force.LerpSpeed = m_Springs.SpringLerpSpeed;
- m_RotationSpring_Force.LerpSpeed = m_Springs.SpringLerpSpeed;
- //Headbob Springs
- m_PositionSpring_Headbob = new Spring(Spring.Type.AddToLocalPosition, m_Camera.transform);
- m_PositionSpring_Headbob.Adjust(m_Springs.HeadbobSprings.Position.Stiffness, m_Springs.HeadbobSprings.Position.Damping);
- m_RotationSpring_Headbob = new Spring(Spring.Type.AddToLocalRotation, m_Camera.transform);
- m_RotationSpring_Headbob.Adjust(m_Springs.HeadbobSprings.Rotation.Stiffness, m_Springs.HeadbobSprings.Rotation.Damping);
- m_PositionSpring_Headbob.LerpSpeed = m_Springs.SpringLerpSpeed;
- m_RotationSpring_Headbob.LerpSpeed = m_Springs.SpringLerpSpeed;
- // Shake Springs
- m_PositionShakeSpring = new Spring(Spring.Type.AddToLocalPosition, m_Camera.transform);
- m_PositionShakeSpring.Adjust(m_CamShakes.ShakeSpringSettings);
- m_RotationShakeSpring = new Spring(Spring.Type.AddToLocalRotation, m_Camera.transform);
- m_RotationShakeSpring.Adjust(m_CamShakes.ShakeSpringSettings);
- m_PositionShakeSpring.LerpSpeed = m_Springs.SpringLerpSpeed;
- m_RotationShakeSpring.LerpSpeed = m_Springs.SpringLerpSpeed;
- //Recoil Springs
- m_PositionRecoilSpring = new Spring(Spring.Type.AddToLocalPosition, m_Camera.transform);
- m_PositionRecoilSpring.Adjust(new Vector3(0.02f, 0.02f, 0.02f), new Vector3(0.3f, 0.3f, 0.3f));
- m_RotationRecoilSpring = new Spring(Spring.Type.AddToLocalRotation, m_Camera.transform);
- m_RotationRecoilSpring.Adjust(new Vector3(0.02f, 0.02f, 0.02f), new Vector3(0.3f, 0.3f, 0.3f));
- m_PositionRecoilSpring.LerpSpeed = m_Springs.SpringLerpSpeed;
- m_RotationRecoilSpring.LerpSpeed = m_Springs.SpringLerpSpeed;
- m_Player.FallImpact.AddListener(OnFallImpact);
- m_Player.Jump.AddStartListener(OnStart_Jump);
- m_Player.Aim.AddStartListener(OnAimStart);
- m_Player.MoveCycleEnded.AddListener(OnStepTaken);
- m_Player.MoveCycle.AddChangeListener(OnMovCycleChanged);
- m_Player.ChangeHealth.AddListener(OnPlayerHealthChanged);
- m_Player.Death.AddListener(OnPlayerDeath);
- ShakeManager.ShakeEvent.AddListener(OnShakeEvent);
- }
- private void OnDestroy()
- {
- ShakeManager.ShakeEvent.RemoveListener(OnShakeEvent);
- }
- private void OnAimStart()
- {
- m_CurrentBobParam = 0f;
- }
- private void FixedUpdate()
- {
- m_PositionSpring_Force.FixedUpdate();
- m_RotationSpring_Force.FixedUpdate();
- m_PositionSpring_Headbob.FixedUpdate();
- m_RotationSpring_Headbob.FixedUpdate();
- m_PositionShakeSpring.FixedUpdate();
- m_RotationShakeSpring.FixedUpdate();
- m_PositionRecoilSpring.FixedUpdate();
- m_RotationRecoilSpring.FixedUpdate();
- UpdateHeadbobs(Time.fixedDeltaTime);
- UpdateShakes();
- }
- private void Update()
- {
- m_PositionSpring_Force.Update();
- m_RotationSpring_Force.Update();
- m_PositionSpring_Headbob.Update();
- m_RotationSpring_Headbob.Update();
- m_PositionShakeSpring.Update();
- m_RotationShakeSpring.Update();
- m_PositionRecoilSpring.Update();
- m_RotationRecoilSpring.Update();
- }
- private void UpdateHeadbobs(float deltaTime)
- {
- var previousHeadbob = m_CurrentHeadbob;
- if (m_Player.Run.Active && m_Player.Velocity.Val.sqrMagnitude > 0.2f)
- m_CurrentHeadbob = m_Headbobs.RunHeadbob;
- else if (m_Player.Aim.Active)
- m_CurrentHeadbob = AimHeadBob;
- else if (m_Player.Crouch.Active)
- m_CurrentHeadbob = m_Headbobs.CrouchHeadbob;
- else if (m_Player.Walk.Active)
- m_CurrentHeadbob = m_Headbobs.WalkHeadbob;
- else
- {
- m_CurrentHeadbob = null;
- Easings.Interpolate(ref m_FadeInBobMult, 1f, deltaTime, true);
- }
- if (previousHeadbob != m_CurrentHeadbob && previousHeadbob != null)
- {
- m_FadeOutBob_Pos = m_FadeInBob_Pos * m_FadeInBobMult + m_FadeOutBob_Pos * m_FadeOutBobMult;
- m_FadeOutBob_Rot = m_FadeInBob_Rot * m_FadeInBobMult + m_FadeOutBob_Rot * m_FadeOutBobMult;
- m_FadeInBobMult = 0f;
- m_FadeOutBobMult = 1f;
- }
- if (m_CurrentHeadbob != null && (m_Player.MoveInput.Val != Vector2.zero || m_Player.Aim.Active))
- Easings.Interpolate(ref m_FadeInBobMult, 1f, deltaTime);
- Easings.Interpolate(ref m_FadeOutBobMult, 1f, deltaTime, true);
- m_FadeOutBob_Pos = Vector3.Lerp(m_FadeOutBob_Pos, Vector3.zero, deltaTime * 0.02f);
- m_FadeOutBob_Rot = Vector3.Lerp(m_FadeOutBob_Rot, Vector3.zero, deltaTime * 0.02f);
- if (m_Player.Aim.Active && AimHeadBob != null)
- m_CurrentBobParam += deltaTime * AimHeadBob.HeadBobSpeed;
- else
- {
- m_CurrentBobParam = m_Player.MoveCycle.Val * Mathf.PI;
- if (m_LastFootDown != 0)
- m_CurrentBobParam += Mathf.PI;
- }
- if (Time.time < m_FadeInStartTime)
- m_FadeInBobMult = 0f;
- if (m_CurrentHeadbob != null)
- {
- Vector3 posBobAmplitude = Vector3.zero;
- Vector3 rotBobAmplitude = Vector3.zero;
- // Update position bob
- posBobAmplitude.x = m_CurrentHeadbob.PosAmplitude.x * -0.00001f;
- m_FadeInBob_Pos.x = Mathf.Cos(m_CurrentBobParam) * posBobAmplitude.x;
- posBobAmplitude.y = m_CurrentHeadbob.PosAmplitude.y * 0.00001f;
- m_FadeInBob_Pos.y = Mathf.Cos(m_CurrentBobParam * 2) * posBobAmplitude.y;
- posBobAmplitude.z = m_CurrentHeadbob.PosAmplitude.z * 0.00001f;
- m_FadeInBob_Pos.z = Mathf.Cos(m_CurrentBobParam) * posBobAmplitude.z;
- // Update rotation bob
- rotBobAmplitude.x = m_CurrentHeadbob.RotationAmplitude.x * 0.001f;
- m_FadeInBob_Rot.x = Mathf.Cos(m_CurrentBobParam * 2) * rotBobAmplitude.x;
- rotBobAmplitude.y = m_CurrentHeadbob.RotationAmplitude.y * 0.001f;
- m_FadeInBob_Rot.y = Mathf.Cos(m_CurrentBobParam) * rotBobAmplitude.y;
- rotBobAmplitude.z = m_CurrentHeadbob.RotationAmplitude.z * 0.001f;
- m_FadeInBob_Rot.z = Mathf.Cos(m_CurrentBobParam) * rotBobAmplitude.z;
- }
- else
- {
- m_FadeInBob_Pos = Vector3.Lerp(m_FadeInBob_Pos, Vector3.zero, deltaTime);
- m_FadeInBob_Rot = Vector3.Lerp(m_FadeInBob_Rot, Vector3.zero, deltaTime);
- }
- m_PositionSpring_Headbob.AddForce(m_FadeInBob_Pos * m_FadeInBobMult + m_FadeOutBob_Pos * m_FadeOutBobMult);
- m_RotationSpring_Headbob.AddForce(m_FadeInBob_Rot * m_FadeInBobMult + m_FadeOutBob_Rot * m_FadeOutBobMult);
- }
- private void OnShakeEvent(ShakeEventData shake)
- {
- if (shake.ShakeType == ShakeType.Explosion)
- {
- float distToExplosionSqr = (transform.position - shake.Position).sqrMagnitude;
- float explosionRadiusSqr = shake.Radius * shake.Radius;
- if (explosionRadiusSqr - distToExplosionSqr > 0f)
- {
- float distanceFactor = 1f - Mathf.Clamp01(distToExplosionSqr / explosionRadiusSqr);
- AddExplosionShake(distanceFactor * shake.Scale);
- }
- }
- }
- private void UpdateShakes()
- {
- if (m_Shakes.Count == 0)
- return;
- int i = 0;
- while (true)
- {
- if (m_Shakes[i].IsDone)
- m_Shakes.RemoveAt(i);
- else
- {
- m_Shakes[i].Update();
- i++;
- }
- if (i >= m_Shakes.Count)
- break;
- }
- }
- private void OnPlayerHealthChanged(HealthEventData healthEventData)
- {
- if (healthEventData.Delta < -8f)
- {
- Vector3 posForce = healthEventData.HitDirection == Vector3.zero ? Random.onUnitSphere : healthEventData.HitDirection.normalized;
- posForce *= Mathf.Abs(healthEventData.Delta / 80f);
- Vector3 rotForce = Random.onUnitSphere;
- AddPositionForce(m_Camera.transform.InverseTransformVector(posForce) * m_GettingHitForce.PosForce);
- AddRotationForce(rotForce * m_GettingHitForce.RotForce);
- }
- }
- private void OnFallImpact(float impactVelocity)
- {
- float impactVelocityAbs = Mathf.Abs(impactVelocity);
- if (impactVelocityAbs > m_FallImpact.FallImpactRange.x)
- {
- float multiplier = Mathf.Clamp01(impactVelocityAbs / m_FallImpact.FallImpactRange.y);
- AddPositionForce(m_Camera.transform.InverseTransformVector(m_FallImpact.PosForce.Force) * multiplier, m_FallImpact.PosForce.Distribution);
- AddRotationForce(m_FallImpact.RotForce.Force * multiplier, m_FallImpact.RotForce.Distribution);
- }
- }
- private void OnStart_Jump()
- {
- AddPositionForce(m_JumpForce.PosForce.Force, m_JumpForce.PosForce.Distribution);
- AddRotationForce(m_JumpForce.RotForce.Force, m_JumpForce.RotForce.Distribution);
- }
- private void OnMovCycleChanged(float cycle)
- {
- if (cycle == 0f)
- m_LastFootDown = 0;
- else if (m_Player.MoveCycle.PrevVal == 0f)
- {
- m_FadeOutBob_Pos = m_FadeInBob_Pos * m_FadeInBobMult + m_FadeOutBob_Pos * m_FadeOutBobMult;
- m_FadeOutBob_Rot = m_FadeInBob_Rot * m_FadeInBobMult + m_FadeOutBob_Rot * m_FadeOutBobMult;
- m_FadeInBobMult = 0f;
- m_FadeOutBobMult = 1f;
- }
- }
- private void OnStepTaken()
- {
- m_LastFootDown = m_LastFootDown == 0 ? 1 : 0;
- }
- private void OnValidate()
- {
- if (m_PositionSpring_Force != null && m_RotationSpring_Force != null)
- {
- m_PositionSpring_Force.Adjust(m_Springs.ForceSprings.Position.Stiffness, m_Springs.ForceSprings.Position.Damping);
- m_RotationSpring_Force.Adjust(m_Springs.ForceSprings.Rotation.Stiffness, m_Springs.ForceSprings.Rotation.Damping);
- }
- }
- }
- [Serializable]
- public struct SpringSettings
- {
- public static SpringSettings Default { get { return new SpringSettings() { Position = Spring.Data.Default, Rotation = Spring.Data.Default }; } }
- public Spring.Data Position, Rotation;
- }
- }
|