FirstPersonCamera.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using Random = UnityEngine.Random;
  5. namespace HQFPSWeapons
  6. {
  7. public class FirstPersonCamera : MonoBehaviour
  8. {
  9. #region Internal
  10. #pragma warning disable 0649
  11. [Serializable]
  12. private class SpringsModule
  13. {
  14. public float SpringLerpSpeed = 25f;
  15. [Space]
  16. [Group]
  17. public SpringSettings ForceSprings = SpringSettings.Default;
  18. [Group]
  19. public SpringSettings HeadbobSprings = SpringSettings.Default;
  20. }
  21. [Serializable]
  22. private struct HeadbobsModule
  23. {
  24. [Group]
  25. public CameraHeadBob WalkHeadbob;
  26. [Group]
  27. public CameraHeadBob CrouchHeadbob;
  28. [Group]
  29. public CameraHeadBob RunHeadbob;
  30. }
  31. [Serializable]
  32. private struct ShakesModule
  33. {
  34. public Spring.Data ShakeSpringSettings;
  35. public CameraShakeSettings ExplosionShake;
  36. public CameraShakeSettings DeathShake;
  37. }
  38. [Serializable]
  39. private struct FallImpactModule
  40. {
  41. [MinMax(0f, 50f)]
  42. public Vector2 FallImpactRange;
  43. public SpringForce PosForce;
  44. public SpringForce RotForce;
  45. }
  46. [Serializable]
  47. private struct JumpForceModule
  48. {
  49. public SpringForce PosForce;
  50. public SpringForce RotForce;
  51. }
  52. [Serializable]
  53. private struct GettingHitForceModule
  54. {
  55. [Range(0f, 10f)]
  56. public float PosForce;
  57. [Range(0f, 10f)]
  58. public float RotForce;
  59. }
  60. #pragma warning restore 0649
  61. #endregion
  62. public CameraHeadBob AimHeadBob { get; set; }
  63. public Camera UnityCamera { get { return m_Camera; } }
  64. [BHeader("General", true)]
  65. [SerializeField]
  66. private Camera m_Camera = null;
  67. [SerializeField]
  68. private Player m_Player = null;
  69. [Space]
  70. [SerializeField, Group()]
  71. private SpringsModule m_Springs = null;
  72. [SerializeField, Group()]
  73. private HeadbobsModule m_Headbobs = new HeadbobsModule();
  74. [SerializeField, Group()]
  75. private ShakesModule m_CamShakes = new ShakesModule();
  76. [SerializeField, Group()]
  77. private FallImpactModule m_FallImpact = new FallImpactModule();
  78. [SerializeField, Group()]
  79. private JumpForceModule m_JumpForce = new JumpForceModule();
  80. [SerializeField, Group()]
  81. private GettingHitForceModule m_GettingHitForce = new GettingHitForceModule();
  82. // Springs
  83. private Spring m_PositionSpring_Force;
  84. private Spring m_RotationSpring_Force;
  85. private Spring m_PositionSpring_Headbob;
  86. private Spring m_RotationSpring_Headbob;
  87. private Spring m_PositionShakeSpring;
  88. private Spring m_RotationShakeSpring;
  89. private Spring m_PositionRecoilSpring;
  90. private Spring m_RotationRecoilSpring;
  91. // Headbob
  92. private CameraHeadBob m_CurrentHeadbob;
  93. private float m_CurrentBobParam;
  94. private Vector3 m_FadeOutBob_Pos;
  95. private Vector3 m_FadeOutBob_Rot;
  96. private Vector3 m_FadeInBob_Pos;
  97. private Vector3 m_FadeInBob_Rot;
  98. private float m_FadeOutBobMult;
  99. private float m_FadeInBobMult;
  100. private float m_FadeInStartTime;
  101. private int m_LastFootDown;
  102. // Shakes
  103. private List<CameraShake> m_Shakes = new List<CameraShake>();
  104. public bool Raycast(float maxDistance, LayerMask mask, out RaycastHit hitInfo, QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.Ignore)
  105. {
  106. return Physics.Raycast(new Ray(m_Camera.transform.position, m_Camera.transform.forward), out hitInfo, maxDistance, mask, queryTriggerInteraction);
  107. }
  108. public void AdjustRecoilSettings(Spring.Data rotSpringData, Spring.Data posSpringData)
  109. {
  110. m_PositionRecoilSpring.Adjust(posSpringData);
  111. m_RotationRecoilSpring.Adjust(rotSpringData);
  112. }
  113. public void ApplyRecoil(RecoilForce force, float forceMultiplier = 1f)
  114. {
  115. force.PlayRecoilForce(forceMultiplier, m_RotationRecoilSpring, m_PositionRecoilSpring);
  116. }
  117. public void AddPositionForce(Vector3 positionForce, int distribution = 1)
  118. {
  119. m_FadeInBobMult = 0f;
  120. m_FadeInStartTime = Time.time + 1f;
  121. if (distribution <= 1)
  122. m_PositionSpring_Force.AddForce(positionForce);
  123. else
  124. m_PositionSpring_Force.AddDistributedForce(positionForce, distribution);
  125. }
  126. public void AddRotationForce(Vector3 rotationForce, int distribution = 1)
  127. {
  128. m_FadeInBobMult = 0f;
  129. m_FadeInStartTime = Time.time + 1f;
  130. if (distribution <= 1)
  131. m_RotationSpring_Force.AddForce(rotationForce);
  132. else
  133. m_RotationSpring_Force.AddDistributedForce(rotationForce, distribution);
  134. }
  135. public void DoShake(CameraShakeSettings shake, float scale)
  136. {
  137. m_Shakes.Add(new CameraShake(shake, m_PositionShakeSpring, m_RotationShakeSpring, scale));
  138. }
  139. public void AddExplosionShake(float scale)
  140. {
  141. m_Shakes.Add(new CameraShake(m_CamShakes.ExplosionShake, m_PositionShakeSpring, m_RotationShakeSpring, scale));
  142. }
  143. public void OnPlayerDeath()
  144. {
  145. m_Shakes.Add(new CameraShake(m_CamShakes.DeathShake, m_PositionShakeSpring, m_RotationShakeSpring, 1f));
  146. }
  147. private void Awake()
  148. {
  149. // Force Springs
  150. m_PositionSpring_Force = new Spring(Spring.Type.OverrideLocalPosition, m_Camera.transform);
  151. m_PositionSpring_Force.Adjust(m_Springs.ForceSprings.Position.Stiffness, m_Springs.ForceSprings.Position.Damping);
  152. m_RotationSpring_Force = new Spring(Spring.Type.OverrideLocalRotation, m_Camera.transform);
  153. m_RotationSpring_Force.Adjust(m_Springs.ForceSprings.Rotation.Stiffness, m_Springs.ForceSprings.Rotation.Damping);
  154. m_PositionSpring_Force.LerpSpeed = m_Springs.SpringLerpSpeed;
  155. m_RotationSpring_Force.LerpSpeed = m_Springs.SpringLerpSpeed;
  156. //Headbob Springs
  157. m_PositionSpring_Headbob = new Spring(Spring.Type.AddToLocalPosition, m_Camera.transform);
  158. m_PositionSpring_Headbob.Adjust(m_Springs.HeadbobSprings.Position.Stiffness, m_Springs.HeadbobSprings.Position.Damping);
  159. m_RotationSpring_Headbob = new Spring(Spring.Type.AddToLocalRotation, m_Camera.transform);
  160. m_RotationSpring_Headbob.Adjust(m_Springs.HeadbobSprings.Rotation.Stiffness, m_Springs.HeadbobSprings.Rotation.Damping);
  161. m_PositionSpring_Headbob.LerpSpeed = m_Springs.SpringLerpSpeed;
  162. m_RotationSpring_Headbob.LerpSpeed = m_Springs.SpringLerpSpeed;
  163. // Shake Springs
  164. m_PositionShakeSpring = new Spring(Spring.Type.AddToLocalPosition, m_Camera.transform);
  165. m_PositionShakeSpring.Adjust(m_CamShakes.ShakeSpringSettings);
  166. m_RotationShakeSpring = new Spring(Spring.Type.AddToLocalRotation, m_Camera.transform);
  167. m_RotationShakeSpring.Adjust(m_CamShakes.ShakeSpringSettings);
  168. m_PositionShakeSpring.LerpSpeed = m_Springs.SpringLerpSpeed;
  169. m_RotationShakeSpring.LerpSpeed = m_Springs.SpringLerpSpeed;
  170. //Recoil Springs
  171. m_PositionRecoilSpring = new Spring(Spring.Type.AddToLocalPosition, m_Camera.transform);
  172. m_PositionRecoilSpring.Adjust(new Vector3(0.02f, 0.02f, 0.02f), new Vector3(0.3f, 0.3f, 0.3f));
  173. m_RotationRecoilSpring = new Spring(Spring.Type.AddToLocalRotation, m_Camera.transform);
  174. m_RotationRecoilSpring.Adjust(new Vector3(0.02f, 0.02f, 0.02f), new Vector3(0.3f, 0.3f, 0.3f));
  175. m_PositionRecoilSpring.LerpSpeed = m_Springs.SpringLerpSpeed;
  176. m_RotationRecoilSpring.LerpSpeed = m_Springs.SpringLerpSpeed;
  177. m_Player.FallImpact.AddListener(OnFallImpact);
  178. m_Player.Jump.AddStartListener(OnStart_Jump);
  179. m_Player.Aim.AddStartListener(OnAimStart);
  180. m_Player.MoveCycleEnded.AddListener(OnStepTaken);
  181. m_Player.MoveCycle.AddChangeListener(OnMovCycleChanged);
  182. m_Player.ChangeHealth.AddListener(OnPlayerHealthChanged);
  183. m_Player.Death.AddListener(OnPlayerDeath);
  184. ShakeManager.ShakeEvent.AddListener(OnShakeEvent);
  185. }
  186. private void OnDestroy()
  187. {
  188. ShakeManager.ShakeEvent.RemoveListener(OnShakeEvent);
  189. }
  190. private void OnAimStart()
  191. {
  192. m_CurrentBobParam = 0f;
  193. }
  194. private void FixedUpdate()
  195. {
  196. m_PositionSpring_Force.FixedUpdate();
  197. m_RotationSpring_Force.FixedUpdate();
  198. m_PositionSpring_Headbob.FixedUpdate();
  199. m_RotationSpring_Headbob.FixedUpdate();
  200. m_PositionShakeSpring.FixedUpdate();
  201. m_RotationShakeSpring.FixedUpdate();
  202. m_PositionRecoilSpring.FixedUpdate();
  203. m_RotationRecoilSpring.FixedUpdate();
  204. UpdateHeadbobs(Time.fixedDeltaTime);
  205. UpdateShakes();
  206. }
  207. private void Update()
  208. {
  209. m_PositionSpring_Force.Update();
  210. m_RotationSpring_Force.Update();
  211. m_PositionSpring_Headbob.Update();
  212. m_RotationSpring_Headbob.Update();
  213. m_PositionShakeSpring.Update();
  214. m_RotationShakeSpring.Update();
  215. m_PositionRecoilSpring.Update();
  216. m_RotationRecoilSpring.Update();
  217. }
  218. private void UpdateHeadbobs(float deltaTime)
  219. {
  220. var previousHeadbob = m_CurrentHeadbob;
  221. if (m_Player.Run.Active && m_Player.Velocity.Val.sqrMagnitude > 0.2f)
  222. m_CurrentHeadbob = m_Headbobs.RunHeadbob;
  223. else if (m_Player.Aim.Active)
  224. m_CurrentHeadbob = AimHeadBob;
  225. else if (m_Player.Crouch.Active)
  226. m_CurrentHeadbob = m_Headbobs.CrouchHeadbob;
  227. else if (m_Player.Walk.Active)
  228. m_CurrentHeadbob = m_Headbobs.WalkHeadbob;
  229. else
  230. {
  231. m_CurrentHeadbob = null;
  232. Easings.Interpolate(ref m_FadeInBobMult, 1f, deltaTime, true);
  233. }
  234. if (previousHeadbob != m_CurrentHeadbob && previousHeadbob != null)
  235. {
  236. m_FadeOutBob_Pos = m_FadeInBob_Pos * m_FadeInBobMult + m_FadeOutBob_Pos * m_FadeOutBobMult;
  237. m_FadeOutBob_Rot = m_FadeInBob_Rot * m_FadeInBobMult + m_FadeOutBob_Rot * m_FadeOutBobMult;
  238. m_FadeInBobMult = 0f;
  239. m_FadeOutBobMult = 1f;
  240. }
  241. if (m_CurrentHeadbob != null && (m_Player.MoveInput.Val != Vector2.zero || m_Player.Aim.Active))
  242. Easings.Interpolate(ref m_FadeInBobMult, 1f, deltaTime);
  243. Easings.Interpolate(ref m_FadeOutBobMult, 1f, deltaTime, true);
  244. m_FadeOutBob_Pos = Vector3.Lerp(m_FadeOutBob_Pos, Vector3.zero, deltaTime * 0.02f);
  245. m_FadeOutBob_Rot = Vector3.Lerp(m_FadeOutBob_Rot, Vector3.zero, deltaTime * 0.02f);
  246. if (m_Player.Aim.Active && AimHeadBob != null)
  247. m_CurrentBobParam += deltaTime * AimHeadBob.HeadBobSpeed;
  248. else
  249. {
  250. m_CurrentBobParam = m_Player.MoveCycle.Val * Mathf.PI;
  251. if (m_LastFootDown != 0)
  252. m_CurrentBobParam += Mathf.PI;
  253. }
  254. if (Time.time < m_FadeInStartTime)
  255. m_FadeInBobMult = 0f;
  256. if (m_CurrentHeadbob != null)
  257. {
  258. Vector3 posBobAmplitude = Vector3.zero;
  259. Vector3 rotBobAmplitude = Vector3.zero;
  260. // Update position bob
  261. posBobAmplitude.x = m_CurrentHeadbob.PosAmplitude.x * -0.00001f;
  262. m_FadeInBob_Pos.x = Mathf.Cos(m_CurrentBobParam) * posBobAmplitude.x;
  263. posBobAmplitude.y = m_CurrentHeadbob.PosAmplitude.y * 0.00001f;
  264. m_FadeInBob_Pos.y = Mathf.Cos(m_CurrentBobParam * 2) * posBobAmplitude.y;
  265. posBobAmplitude.z = m_CurrentHeadbob.PosAmplitude.z * 0.00001f;
  266. m_FadeInBob_Pos.z = Mathf.Cos(m_CurrentBobParam) * posBobAmplitude.z;
  267. // Update rotation bob
  268. rotBobAmplitude.x = m_CurrentHeadbob.RotationAmplitude.x * 0.001f;
  269. m_FadeInBob_Rot.x = Mathf.Cos(m_CurrentBobParam * 2) * rotBobAmplitude.x;
  270. rotBobAmplitude.y = m_CurrentHeadbob.RotationAmplitude.y * 0.001f;
  271. m_FadeInBob_Rot.y = Mathf.Cos(m_CurrentBobParam) * rotBobAmplitude.y;
  272. rotBobAmplitude.z = m_CurrentHeadbob.RotationAmplitude.z * 0.001f;
  273. m_FadeInBob_Rot.z = Mathf.Cos(m_CurrentBobParam) * rotBobAmplitude.z;
  274. }
  275. else
  276. {
  277. m_FadeInBob_Pos = Vector3.Lerp(m_FadeInBob_Pos, Vector3.zero, deltaTime);
  278. m_FadeInBob_Rot = Vector3.Lerp(m_FadeInBob_Rot, Vector3.zero, deltaTime);
  279. }
  280. m_PositionSpring_Headbob.AddForce(m_FadeInBob_Pos * m_FadeInBobMult + m_FadeOutBob_Pos * m_FadeOutBobMult);
  281. m_RotationSpring_Headbob.AddForce(m_FadeInBob_Rot * m_FadeInBobMult + m_FadeOutBob_Rot * m_FadeOutBobMult);
  282. }
  283. private void OnShakeEvent(ShakeEventData shake)
  284. {
  285. if (shake.ShakeType == ShakeType.Explosion)
  286. {
  287. float distToExplosionSqr = (transform.position - shake.Position).sqrMagnitude;
  288. float explosionRadiusSqr = shake.Radius * shake.Radius;
  289. if (explosionRadiusSqr - distToExplosionSqr > 0f)
  290. {
  291. float distanceFactor = 1f - Mathf.Clamp01(distToExplosionSqr / explosionRadiusSqr);
  292. AddExplosionShake(distanceFactor * shake.Scale);
  293. }
  294. }
  295. }
  296. private void UpdateShakes()
  297. {
  298. if (m_Shakes.Count == 0)
  299. return;
  300. int i = 0;
  301. while (true)
  302. {
  303. if (m_Shakes[i].IsDone)
  304. m_Shakes.RemoveAt(i);
  305. else
  306. {
  307. m_Shakes[i].Update();
  308. i++;
  309. }
  310. if (i >= m_Shakes.Count)
  311. break;
  312. }
  313. }
  314. private void OnPlayerHealthChanged(HealthEventData healthEventData)
  315. {
  316. if (healthEventData.Delta < -8f)
  317. {
  318. Vector3 posForce = healthEventData.HitDirection == Vector3.zero ? Random.onUnitSphere : healthEventData.HitDirection.normalized;
  319. posForce *= Mathf.Abs(healthEventData.Delta / 80f);
  320. Vector3 rotForce = Random.onUnitSphere;
  321. AddPositionForce(m_Camera.transform.InverseTransformVector(posForce) * m_GettingHitForce.PosForce);
  322. AddRotationForce(rotForce * m_GettingHitForce.RotForce);
  323. }
  324. }
  325. private void OnFallImpact(float impactVelocity)
  326. {
  327. float impactVelocityAbs = Mathf.Abs(impactVelocity);
  328. if (impactVelocityAbs > m_FallImpact.FallImpactRange.x)
  329. {
  330. float multiplier = Mathf.Clamp01(impactVelocityAbs / m_FallImpact.FallImpactRange.y);
  331. AddPositionForce(m_Camera.transform.InverseTransformVector(m_FallImpact.PosForce.Force) * multiplier, m_FallImpact.PosForce.Distribution);
  332. AddRotationForce(m_FallImpact.RotForce.Force * multiplier, m_FallImpact.RotForce.Distribution);
  333. }
  334. }
  335. private void OnStart_Jump()
  336. {
  337. AddPositionForce(m_JumpForce.PosForce.Force, m_JumpForce.PosForce.Distribution);
  338. AddRotationForce(m_JumpForce.RotForce.Force, m_JumpForce.RotForce.Distribution);
  339. }
  340. private void OnMovCycleChanged(float cycle)
  341. {
  342. if (cycle == 0f)
  343. m_LastFootDown = 0;
  344. else if (m_Player.MoveCycle.PrevVal == 0f)
  345. {
  346. m_FadeOutBob_Pos = m_FadeInBob_Pos * m_FadeInBobMult + m_FadeOutBob_Pos * m_FadeOutBobMult;
  347. m_FadeOutBob_Rot = m_FadeInBob_Rot * m_FadeInBobMult + m_FadeOutBob_Rot * m_FadeOutBobMult;
  348. m_FadeInBobMult = 0f;
  349. m_FadeOutBobMult = 1f;
  350. }
  351. }
  352. private void OnStepTaken()
  353. {
  354. m_LastFootDown = m_LastFootDown == 0 ? 1 : 0;
  355. }
  356. private void OnValidate()
  357. {
  358. if (m_PositionSpring_Force != null && m_RotationSpring_Force != null)
  359. {
  360. m_PositionSpring_Force.Adjust(m_Springs.ForceSprings.Position.Stiffness, m_Springs.ForceSprings.Position.Damping);
  361. m_RotationSpring_Force.Adjust(m_Springs.ForceSprings.Rotation.Stiffness, m_Springs.ForceSprings.Rotation.Damping);
  362. }
  363. }
  364. }
  365. [Serializable]
  366. public struct SpringSettings
  367. {
  368. public static SpringSettings Default { get { return new SpringSettings() { Position = Spring.Data.Default, Rotation = Spring.Data.Default }; } }
  369. public Spring.Data Position, Rotation;
  370. }
  371. }