zombie_mp/Assets/HQ FPS Weapons/Scripts/Camera/FirstPersonCamera.cs
Sewmina Dilshan 68183e5317 initial
2021-08-23 13:28:33 +05:30

481 lines
14 KiB
C#

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;
}
}