Advertisement
Guest User

Untitled

a guest
Aug 2nd, 2021
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 60.94 KB | None | 0 0
  1. /// ---------------------------------------------
  2. /// Ultimate Character Controller
  3. /// Copyright (c) Opsive. All Rights Reserved.
  4. /// https://www.opsive.com
  5. /// ---------------------------------------------
  6.  
  7. namespace Opsive.UltimateCharacterController.FirstPersonController.Camera.ViewTypes
  8. {
  9.     using Opsive.Shared.Events;
  10.     using Opsive.Shared.Game;
  11.     using Opsive.Shared.StateSystem;
  12.     using Opsive.Shared.Utility;
  13.     using Opsive.UltimateCharacterController.Camera;
  14.     using Opsive.UltimateCharacterController.Camera.ViewTypes;
  15.     using Opsive.UltimateCharacterController.Game;
  16.     using Opsive.UltimateCharacterController.Motion;
  17.     using Opsive.UltimateCharacterController.Utility;
  18.     using UnityEngine;
  19.  
  20.     /// <summary>
  21.     /// The FirstPerson ViewType allows the camera to be placed in a first person perspective.
  22.     /// </summary>
  23.     public abstract class FirstPerson : ViewType
  24.  
  25.     {
  26. #if ULTIMATE_CHARACTER_CONTROLLER_UNIVERSALRP|| ULTIMATE_CHARACTER_CONTROLLER_HDRP
  27.         /// <summary>
  28.         /// Specifies how the overlay objects are rendered.
  29.         /// </summary>
  30.         public enum ObjectOverlayRenderType
  31.         {
  32.             SecondCamera,   // Use a second stacked camera to ensure the overlay objects do no clip with any other objects.
  33.             RenderPipeline, // Use the URP/HDRP render pipeline to ensure the overlay objects do no clip with any other objects.
  34.             None            // No special rendering for the overlay objects.
  35.         }
  36. #endif
  37.  
  38.         [Tooltip("The distance that the character should look ahead.")]
  39.         [SerializeField] protected float m_LookDirectionDistance = 100;
  40.         [Tooltip("The offset between the anchor and the camera.")]
  41.         [SerializeField] protected Vector3 m_LookOffset = new Vector3(0, .1f, 0.27f);
  42.         [Tooltip("Amount to adjust the camera position by when the character is looking down.")]
  43.         [SerializeField] protected Vector3 m_LookDownOffset = new Vector3(0, 0, 0.28f);
  44.         [Tooltip("The culling mask of the camera.")]
  45.         [SerializeField] protected LayerMask m_CullingMask = ~(1 << LayerManager.Overlay);
  46.         [Tooltip("Specifies the position offset from the camera that the first person objects should render.")]
  47.         [SerializeField] protected Vector3 m_FirstPersonPositionOffset;
  48.         [Tooltip("Specifies the rotation offset from the camera that the first person objects should render.")]
  49.         [SerializeField] protected Vector3 m_FirstPersonRotationOffset;
  50. #if ULTIMATE_CHARACTER_CONTROLLER_UNIVERSALRP|| ULTIMATE_CHARACTER_CONTROLLER_HDRP
  51.         [Tooltip("Specifies how the overlay objects are rendered.")]
  52.         [SerializeField] protected ObjectOverlayRenderType m_OverlayRenderType = ObjectOverlayRenderType.SecondCamera;
  53. #else
  54.         [Tooltip("Should the first person camera be used?")]
  55.         [SerializeField] protected bool m_UseFirstPersonCamera = true;
  56. #endif
  57.         [Tooltip("A reference to the first person camera.")]
  58.         [SerializeField] protected UnityEngine.Camera m_FirstPersonCamera;
  59.         [Tooltip("The culling mask of the first person objects.")]
  60.         [SerializeField] protected LayerMask m_FirstPersonCullingMask = 1 << LayerManager.Overlay;
  61.         [Tooltip("Should the first person camera's field of view be synchronized with the main camera?")]
  62.         [SerializeField] protected bool m_SynchronizeFieldOfView = true;
  63.         [Tooltip("Specifies the field of view for the first person camera.")]
  64.         [SerializeField] protected float m_FirstPersonFieldOfView = 30f;
  65.         [Tooltip("The damping time of the field of view angle when changed.")]
  66.         [SerializeField] protected float m_FirstPersonFieldOfViewDamping = 0.2f;
  67.  
  68.         [Tooltip("A vertical limit intended to prevent the camera from intersecting with the character.")]
  69.         [SerializeField] protected float m_PositionLowerVerticalLimit = 0.25f;
  70.         [Tooltip("Determines how much the camera will be pushed down when the player falls onto a surface.")]
  71.         [SerializeField] protected float m_PositionFallImpact = 2f;
  72.         [Tooltip("The number of frames that the fall impact force should be applied.")]
  73.         [SerializeField] protected int m_PositionFallImpactSoftness = 4;
  74.         [Tooltip("Rotates the camera depending on the sideways local velocity of the character, resulting in the camera leaning into or away from its sideways movement direction.")]
  75.         [SerializeField] protected float m_RotationStrafeRoll = 0.01f;
  76.         [Tooltip("Determines how much the camera will roll when the player falls onto a surface.")]
  77.         [SerializeField] protected float m_RotationFallImpact = 0.1f;
  78.         [Tooltip("The number of frames that the fall impact force should be applied.")]
  79.         [SerializeField] protected int m_RotationFallImpactSoftness = 1;
  80.  
  81.         [Tooltip("The positional spring used for regular movement.")]
  82.         [SerializeField] protected Spring m_PositionSpring = new Spring();
  83.         [Tooltip("The rotational spring used for regular movement.")]
  84.         [SerializeField] protected Spring m_RotationSpring = new Spring();
  85.         [Tooltip("The positional spring which returns to equilibrium after a small amount of time (for recoil).")]
  86.         [SerializeField] protected Spring m_SecondaryPositionSpring = new Spring();
  87.         [Tooltip("The rotational spring which returns to equilibrium after a small amount of time (for recoil).")]
  88.         [SerializeField] protected Spring m_SecondaryRotationSpring = new Spring();
  89.  
  90.         [Tooltip("The minimum pitch angle (in degrees).")]
  91.         [SerializeField] protected float m_MinPitchLimit = -72;
  92.         [Tooltip("The maximum pitch angle (in degrees).")]
  93.         [SerializeField] protected float m_MaxPitchLimit = 72;
  94.  
  95.         [Tooltip("The rate that the camera changes its position while the character is moving.")]
  96.         [SerializeField] protected Vector3 m_BobPositionalRate = new Vector3(0.0f, 1.4f, 0.0f);
  97.         [Tooltip("The strength of the positional camera bob. Determines how far the camera swings in each respective direction.")]
  98.         [SerializeField] protected Vector3 m_BobPositionalAmplitude = new Vector3(0.0f, 0.35f, 0.0f);
  99.         [Tooltip("The rate that the camera changes its roll rotation value while the character is moving.")]
  100.         [SerializeField] protected float m_BobRollRate = 0.9f;
  101.         [Tooltip("The strength of the roll within the camera bob. Determines how far the camera tilts from left to right.")]
  102.         [SerializeField] protected float m_BobRollAmplitude = 1.7f;
  103.         [Tooltip("This tweaking feature is useful if the bob motion gets out of hand after changing character velocity.")]
  104.         [SerializeField] protected float m_BobInputVelocityScale = 1;
  105.         [Tooltip("A cap on the velocity value from the bob function, preventing the camera from flipping out when the character travels at excessive speeds.")]
  106.         [SerializeField] protected float m_BobMaxInputVelocity = 1000;
  107.         [Tooltip("A trough should only occur when the bob vertical offset is less then the specified value.")]
  108.         [SerializeField] protected float m_BobMinTroughVerticalOffset = -0.01f;
  109.         [Tooltip("The amount of force to add when the bob has reached its lowest point. This can be used to add a shaking effect to the camera to mimick a giant walking.")]
  110.         [SerializeField] protected Vector3 m_BobTroughForce = new Vector3(0.0f, 0.0f, 0.0f);
  111.         [Tooltip("Determines whether the bob should stay in effect only when the character is on the ground.")]
  112.         [SerializeField] protected bool m_BobRequireGroundContact = true;
  113.  
  114.         [Tooltip("The speed that the camera should shake.")]
  115.         [SerializeField] protected float m_ShakeSpeed = 0.1f;
  116.         [Tooltip("The strength of the shake. Determines how much the camera will tilt.")]
  117.         [SerializeField] protected Vector3 m_ShakeAmplitude = new Vector3(10, 10);
  118.  
  119.         [Tooltip("Number of head offset values to average together. The head offset value specifies how reactive the camera is to head movements.")]
  120.         [SerializeField] protected int m_SmoothHeadOffsetSteps = 2;
  121.         [Tooltip("The radius of the camera's collision sphere to prevent it from clipping with other objects.")]
  122.         [SerializeField] protected float m_CollisionRadius = 0.05f;
  123.         [Tooltip("Should the camera rotate as the character's head rotates?")]
  124.         [SerializeField] protected bool m_RotateWithHead;
  125.         public CameraController cameraController; // assign in inspector, or get during runtime in Awake/Start
  126.  
  127.        
  128.         public Vector3 LookOffset { get { return m_LookOffset; }
  129.             set
  130.             {
  131.                 m_LookOffset = value;
  132.                 if (m_PositionSpring != null && m_CameraController != null) {
  133.                     InitializePositionSpringValue();
  134.                 }
  135.             }
  136.         }
  137.         public Vector3 LookDownOffset { get { return m_LookDownOffset; } set { m_LookDownOffset = value; } }
  138.         public LayerMask CullingMask { get { return m_CullingMask; } set {
  139.                 if (m_CullingMask != value) {
  140.                     m_CullingMask = value;
  141.                     if (m_CharacterLocomotion.FirstPersonPerspective) {
  142.                         m_Camera.cullingMask &= m_CullingMask;
  143.                     }
  144.                 }
  145.             } }
  146.         public float FieldOfView { get { return m_FieldOfView; } set { m_FieldOfView = value; } }
  147.         public float FieldOfViewDamping { get { return m_FieldOfViewDamping; } set { m_FieldOfViewDamping = value; } }
  148.         public Vector3 FirstPersonPositionOffset { get { return m_FirstPersonPositionOffset; }
  149.             set
  150.             {
  151.                 m_FirstPersonPositionOffset = value;
  152.                 if (m_FirstPersonCameraTransform != null) {
  153.                     m_FirstPersonCameraTransform.localPosition = m_FirstPersonPositionOffset;
  154.                 }
  155.             }
  156.         }
  157.         public Vector3 FirstPersonRotationOffset { get { return m_FirstPersonRotationOffset; }
  158.             set
  159.             {
  160.                 m_FirstPersonRotationOffset = value;
  161.                 if (m_FirstPersonCameraTransform != null) {
  162.                     m_FirstPersonCameraTransform.localRotation = Quaternion.Euler(m_FirstPersonRotationOffset);
  163.                 }
  164.             }
  165.         }
  166.         public override float LookDirectionDistance { get { return m_LookDirectionDistance; } }
  167. #if ULTIMATE_CHARACTER_CONTROLLER_UNIVERSALRP|| ULTIMATE_CHARACTER_CONTROLLER_HDRP
  168.         [NonSerialized] public ObjectOverlayRenderType OverlayRenderType { get { return m_OverlayRenderType; } set { m_OverlayRenderType = value; } }
  169. #else
  170.         public bool UseFirstPersonCamera { get { return m_UseFirstPersonCamera; }
  171.             set
  172.             {
  173.                 m_UseFirstPersonCamera = value;
  174.                 if (m_FirstPersonCamera == null || m_CharacterLocomotion == null) {
  175.                     return;
  176.                 }
  177.                 UpdateFirstPersonCamera(m_CharacterLocomotion.FirstPersonPerspective);
  178.             }
  179.         }
  180. #endif
  181.         [NonSerialized] public UnityEngine.Camera FirstPersonCamera { get { return m_FirstPersonCamera; } set { m_FirstPersonCamera = value; } }
  182.         public LayerMask FirstPersonCullingMask { get { return m_FirstPersonCullingMask; }
  183.             set {
  184. #if ULTIMATE_CHARACTER_CONTROLLER_UNIVERSALRP|| ULTIMATE_CHARACTER_CONTROLLER_HDRP
  185.                 if (m_OverlayRenderType == ObjectOverlayRenderType.RenderPipeline && m_FirstPersonCullingMask != value) {
  186.                     m_FirstPersonCullingMask = value;
  187.                     UpdateFirstPersonCamera(m_CharacterLocomotion.FirstPersonPerspective);
  188. #else
  189.                 if (m_FirstPersonCamera != null &&  m_FirstPersonCullingMask != value) {
  190.                     m_FirstPersonCullingMask = value;
  191.                     m_FirstPersonCamera.cullingMask = m_FirstPersonCullingMask;
  192. #endif
  193.                 }
  194.             }
  195.         }
  196.         public bool SynchronizeFieldOfView { get { return m_SynchronizeFieldOfView; } set { m_SynchronizeFieldOfView = value; } }
  197.         public float FirstPersonFieldOfView { get { return m_FirstPersonFieldOfView; } set { m_FirstPersonFieldOfView = value; } }
  198.         public float FirstPersonFieldOfViewDamping { get { return m_FirstPersonFieldOfViewDamping; } set { m_FirstPersonFieldOfViewDamping = value; } }
  199.         public float PositionLowerVerticalLimit { get { return m_PositionLowerVerticalLimit; }
  200.             set {
  201.                 m_PositionLowerVerticalLimit = value;
  202.                 if (m_PositionSpring != null && m_CameraController != null) {
  203.                     InitializePositionSpringValue();
  204.                 }
  205.             } }
  206.         public float PositionFallImpact { get { return m_PositionFallImpact; } set { m_PositionFallImpact = value; } }
  207.         public int PositionFallImpactSoftness { get { return m_PositionFallImpactSoftness; } set { m_PositionFallImpactSoftness = value; } }
  208.         public float RotationStrafeRoll { get { return m_RotationStrafeRoll; } set { m_RotationStrafeRoll = value; } }
  209.         public float RotationFallImpact { get { return m_RotationFallImpact; } set { m_RotationFallImpact = value; } }
  210.         public int RotationFallImpactSoftness { get { return m_RotationFallImpactSoftness; } set { m_RotationFallImpactSoftness = value; } }
  211.         public Spring PositionSpring { get { return m_PositionSpring; }
  212.             set {
  213.                 m_PositionSpring = value;
  214.                 if (m_CameraController != null) { m_PositionSpring.Initialize(false, true); InitializePositionSpringValue(); }
  215.             } }
  216.         public Spring RotationSpring { get { return m_RotationSpring; }
  217.             set {
  218.                 m_RotationSpring = value;
  219.                 if (m_RotationSpring != null) { m_RotationSpring.Initialize(true, true); }
  220.             } }
  221.         public Spring SecondaryPositionSpring { get { return m_SecondaryPositionSpring; }
  222.             set {
  223.                 m_SecondaryPositionSpring = value;
  224.                 if (m_SecondaryPositionSpring != null) { m_SecondaryPositionSpring.Initialize(false, true); }
  225.             } }
  226.         public Spring SecondaryRotationSpring { get { return m_SecondaryRotationSpring; }
  227.             set {
  228.                 m_SecondaryRotationSpring = value;
  229.                 if (m_SecondaryRotationSpring != null) { m_SecondaryRotationSpring.Initialize(true, true); }
  230.             } }
  231.         public float MinPitchLimit { get { return m_MinPitchLimit; } set { m_MinPitchLimit = value; } }
  232.         public float MaxPitchLimit { get { return m_MaxPitchLimit; } set { m_MaxPitchLimit = value; } }
  233.         public Vector3 BobPositionalRate { get { return m_BobPositionalRate; } set { m_BobPositionalRate = value; } }
  234.         public Vector3 BobPositionalAmplitude { get { return m_BobPositionalAmplitude; } set { m_BobPositionalAmplitude = value; } }
  235.         public float BobRollRate { get { return m_BobRollRate; } set { m_BobRollRate = value; } }
  236.         public float BobRollAmplitude { get { return m_BobRollAmplitude; } set { m_BobRollAmplitude = value; } }
  237.         public float BobInputVelocityScale { get { return m_BobInputVelocityScale; } set { m_BobInputVelocityScale = value; } }
  238.         public float BobMaxInputVelocity { get { return m_BobMaxInputVelocity; } set { m_BobMaxInputVelocity = value; } }
  239.         public float BobMinTroughVerticalOffset { get { return m_BobMinTroughVerticalOffset; } set { m_BobMinTroughVerticalOffset = value; } }
  240.         public Vector3 BobTroughForce { get { return m_BobTroughForce; } set { m_BobTroughForce = value; } }
  241.         public bool BobRequireGroundContact { get { return m_BobRequireGroundContact; } set { m_BobRequireGroundContact = value; } }
  242.         public float ShakeSpeed { get { return m_ShakeSpeed; } set { m_ShakeSpeed = value; } }
  243.         public Vector3 ShakeAmplitude { get { return m_ShakeAmplitude; } set { m_ShakeAmplitude = value; } }
  244.         public int SmoothHeadOffsetSteps { get { return m_SmoothHeadOffsetSteps; } set {
  245.                 m_SmoothHeadOffsetSteps = value;
  246.                 if (value == 0) {
  247.                     m_SmoothHeadBufferCount = 0;
  248.                 }
  249.             } }
  250.         public bool RotateWithHead { get { return m_RotateWithHead; } set { m_RotateWithHead = value; } }
  251.  
  252.         private Transform m_CrosshairsTransform;
  253.         private Canvas m_CrosshairsCanvas;
  254.         private UI.CrosshairsMonitor m_CrosshairsMonitor;
  255.         private AimAssist m_AimAssist;
  256.         private Transform m_FirstPersonCameraTransform;
  257.  
  258.         protected float m_Pitch;
  259.         protected float m_Yaw;
  260.         private float m_PrevBobSpeed;
  261.         protected Vector3 m_Shake;
  262.         protected Quaternion m_CharacterRotation;
  263.         private Quaternion m_CharacterPlatformRotationOffset = Quaternion.identity;
  264.         private Quaternion m_PlatformRotation = Quaternion.identity;
  265.         private bool m_AppendingZoomState;
  266.         private Vector3 m_CrosshairsPosition;
  267.         private Quaternion m_CrosshairsDeltaRotation;
  268.  
  269.         private Transform m_CharacterAnchor;
  270.         private Vector3 m_CharacterAnchorOffset;
  271.         private Quaternion m_CharacterAnchorRotation;
  272.         private Vector3[] m_SmoothHeadOffsetBuffer;
  273.         private int m_SmoothHeadBufferIndex;
  274.         private int m_SmoothHeadBufferCount;
  275.         private ScheduledEventBase m_SmoothHeadBufferEvent;
  276.         private RaycastHit m_RaycastHit;
  277.         private float m_FirstPersonFieldOfViewChangeTime;
  278.         private float m_BobVerticalOffset = float.MaxValue;
  279.         private bool m_BobVerticalOffsetDecreasing = false;
  280.         private float m_VerticalOffsetAdjustment;
  281.  
  282.         private Vector3 m_PrevPositionSpringValue;
  283.         private Vector3 m_PrevPositionSpringVelocity;
  284.         private Vector3 m_PrevRotationSpringValue;
  285.         private Vector3 m_PrevRotationSpringVelocity;
  286.         private Vector3 m_PrevSecondaryPositionSpringValue;
  287.         private Vector3 m_PrevSecondaryPositionSpringVelocity;
  288.         private Vector3 m_PrevSecondaryRotationSpringValue;
  289.         private Vector3 m_PrevSecondaryRotationSpringVelocity;
  290.         private float m_PrevFieldOfViewDamping;
  291.         private float m_PrevFirstPersonFieldOfViewDamping;
  292.         private int m_StateChangeFrame = -1;
  293.  
  294.         public override float Pitch { get { return m_Pitch; } }
  295.         public override float Yaw { get { return m_Yaw; } }
  296.         public override Quaternion CharacterRotation { get { return m_CharacterRotation; } }
  297.         public override bool FirstPersonPerspective { get { return true; } }
  298.         public Vector3 Shake { get { return m_Shake; } }
  299.  
  300.         /// <summary>
  301.         /// Initializes the view type to the specified camera controller.
  302.         /// </summary>
  303.         /// <param name="cameraController">The camera controller to initialize the view type to.</param>
  304.         public override void Initialize(CameraController cameraController)
  305.         {
  306.             base.Initialize(cameraController);
  307.  
  308.             m_Camera = cameraController.gameObject.GetCachedComponent<UnityEngine.Camera>();
  309.             m_AimAssist = m_GameObject.GetCachedComponent<AimAssist>();
  310.  
  311.             m_Camera.depth = 0;
  312. #if ULTIMATE_CHARACTER_CONTROLLER_UNIVERSALRP|| ULTIMATE_CHARACTER_CONTROLLER_HDRP
  313.             if (m_OverlayRenderType != ObjectOverlayRenderType.None) {
  314. #else
  315.             if (m_UseFirstPersonCamera) {
  316. #endif
  317.                 m_Camera.cullingMask &= m_CullingMask;
  318.             }
  319.  
  320.             // Setup the overlay camera.
  321.             if (m_FirstPersonCamera != null) {
  322. #if ULTIMATE_CHARACTER_CONTROLLER_VR
  323.                 if (!UnityEngine.XR.XRSettings.enabled) {
  324. #endif
  325.                     m_Camera.fieldOfView = m_FieldOfView;
  326.                     m_FirstPersonCamera.fieldOfView = m_SynchronizeFieldOfView ? m_FieldOfView : m_FirstPersonFieldOfView;
  327. #if ULTIMATE_CHARACTER_CONTROLLER_VR
  328.                 }
  329. #endif
  330.                 m_FirstPersonCamera.clearFlags = CameraClearFlags.Depth;
  331.                 m_FirstPersonCamera.cullingMask = m_FirstPersonCullingMask;
  332.                 m_FirstPersonCamera.depth = m_Camera.depth + 1;
  333.                 m_FirstPersonCamera.rect = m_Camera.rect;
  334.                 m_FirstPersonCameraTransform = m_FirstPersonCamera.transform;
  335.                 m_FirstPersonCameraTransform.parent = m_Transform;
  336.                 m_FirstPersonCameraTransform.localPosition = m_FirstPersonPositionOffset;
  337.                 m_FirstPersonCameraTransform.localRotation = Quaternion.Euler(m_FirstPersonRotationOffset);
  338.             }
  339.  
  340.             // Using the buffer is optional.
  341.             if (m_SmoothHeadOffsetSteps > 0) {
  342.                 m_SmoothHeadOffsetBuffer = new Vector3[m_SmoothHeadOffsetSteps];
  343.             }
  344.  
  345.             // Initialize the springs.
  346.             m_PositionSpring.Initialize(false, false);
  347.             m_RotationSpring.Initialize(true, true);
  348.             m_SecondaryPositionSpring.Initialize(false, false);
  349.             m_SecondaryRotationSpring.Initialize(true, true);
  350.             InitializePositionSpringValue();
  351.             m_PositionSpring.Reset();
  352.  
  353.             // Register for any interested events.
  354.             EventHandler.RegisterEvent(m_GameObject, "OnAnchorOffsetUpdated", InitializePositionSpringValue);
  355.             EventHandler.RegisterEvent<ViewType, bool>(m_GameObject, "OnCameraChangeViewTypes", OnChangeViewType);
  356.         }
  357.  
  358.         /// <summary>
  359.         /// Initializes the position spring value.
  360.         /// </summary>
  361.         private void InitializePositionSpringValue()
  362.         {
  363.             m_PositionSpring.RestValue = m_CameraController.AnchorOffset + m_LookOffset;
  364.             var value = m_PositionSpring.MinValue;
  365.             value.y = m_PositionSpring.RestValue.y - m_PositionLowerVerticalLimit;
  366.             m_PositionSpring.MinValue = value;
  367.         }
  368.  
  369.         /// <summary>
  370.         /// Attaches the camera to the specified character.
  371.         /// </summary>
  372.         /// <param name="character">The character to attach the camera to.</param>
  373.         public override void AttachCharacter(GameObject character)
  374.         {
  375.             // Unregister from any events on the previous character.
  376.             if (m_Character != null) {
  377.                 EventHandler.UnregisterEvent<Transform>(m_Character, "OnCharacterChangeMovingPlatforms", OnCharacterChangeMovingPlatforms);
  378.                 EventHandler.UnregisterEvent<bool>(m_Character, "OnCameraChangePerspectives", UpdateFirstPersonCamera);
  379.                 EventHandler.UnregisterEvent<float>(m_Character, "OnCharacterLand", OnCharacterLand);
  380.                 EventHandler.UnregisterEvent<float, float, float>(m_Character, "OnCharacterLean", OnCharacterLean);
  381.                 EventHandler.UnregisterEvent<float>(m_Character, "OnHeightChangeAdjustHeight", AdjustVerticalOffset);
  382.                 if (m_SmoothHeadBufferEvent != null) {
  383.                     Scheduler.Cancel(m_SmoothHeadBufferEvent);
  384.                     m_SmoothHeadBufferEvent = null;
  385.                 }
  386.                 m_CharacterAnchor = null;
  387.             }
  388.  
  389.             base.AttachCharacter(character);
  390.  
  391.             // Initialize the camera with the new character.
  392.             if (m_Character != null) {
  393.                 var characterAnimator = m_Character.GetCachedComponent<Animator>();
  394.                 if (characterAnimator != null && m_SmoothHeadOffsetBuffer != null) {
  395.                     m_CharacterAnchor = characterAnimator.GetBoneTransform(HumanBodyBones.Neck);
  396.                     // If the neck doesn't exist then try to get the head.
  397.                     if (m_CharacterAnchor == null) {
  398.                         m_CharacterAnchor = characterAnimator.GetBoneTransform(HumanBodyBones.Head);
  399.                     }
  400.                     if (m_CharacterAnchor != null) {
  401.                         if (m_SmoothHeadBufferEvent != null) {
  402.                             Scheduler.Cancel(m_SmoothHeadBufferEvent);
  403.                             m_SmoothHeadBufferEvent = null;
  404.                         }
  405.                         InitializeSmoothHeadBuffer();
  406.                     }
  407.                 } else {
  408.                     EventHandler.RegisterEvent<float>(m_Character, "OnHeightChangeAdjustHeight", AdjustVerticalOffset);
  409.                 }
  410.                 m_SmoothHeadBufferIndex = -1;
  411.                 m_SmoothHeadBufferCount = 0;
  412.  
  413.                 EventHandler.RegisterEvent<Transform>(m_Character, "OnCharacterChangeMovingPlatforms", OnCharacterChangeMovingPlatforms);
  414.                 EventHandler.RegisterEvent<bool>(m_Character, "OnCameraChangePerspectives", UpdateFirstPersonCamera);
  415.                 EventHandler.RegisterEvent<float>(m_Character, "OnCharacterLand", OnCharacterLand);
  416.                 EventHandler.RegisterEvent<float, float, float>(m_Character, "OnCharacterLean", OnCharacterLean);
  417.             }
  418.         }
  419.  
  420.         /// <summary>
  421.         /// Initializes the SmoothHeadBuffer after the character is grounded. This will allow the animator to be the correct height.
  422.         /// </summary>
  423.         private void InitializeSmoothHeadBuffer()
  424.         {
  425.             if (!m_CharacterLocomotion.Grounded || m_CharacterLocomotion.GroundRaycastHit.distance > m_CharacterLocomotion.ColliderSpacing + 0.011f) {
  426.                 m_SmoothHeadBufferEvent = Scheduler.Schedule(Time.fixedDeltaTime, InitializeSmoothHeadBuffer);
  427.                 return;
  428.             }
  429.  
  430.             m_CharacterAnchorOffset = m_CharacterTransform.InverseTransformPoint(m_CharacterAnchor.position);
  431.             m_SmoothHeadBufferEvent = null;
  432.         }
  433.  
  434.         void Update()
  435.         {
  436.         var viewType = cameraController.ActiveViewType;
  437.         if (viewType is FirstPerson)
  438.             {
  439.             var firstPerson = (FirstPerson)viewType;
  440.             Vector3 lookOffset = firstPerson.LookOffset;
  441.             lookOffset.y = 200;
  442.             firstPerson.LookOffset = lookOffset;
  443.             }
  444.         }
  445.  
  446.         /// <summary>
  447.         /// The view type has changed.
  448.         /// </summary>
  449.         /// <param name="activate">Should the current view type be activated?</param>
  450.         /// <param name="pitch">The pitch of the camera (in degrees).</param>
  451.         /// <param name="yaw">The yaw of the camera (in degrees).</param>
  452.         /// <param name="characterRotation">The rotation of the character.</param>
  453.         public override void ChangeViewType(bool activate, float pitch, float yaw, Quaternion characterRotation)
  454.         {
  455.             if (activate) {
  456.                 m_Pitch = pitch;
  457.                 m_Yaw = yaw;
  458.                 m_CharacterRotation = characterRotation;
  459.                 if (m_CharacterLocomotion.Platform != null) {
  460.                     UpdatePlatformRotationOffset(m_CharacterLocomotion.Platform);
  461.                 }
  462.  
  463.                 UpdateFirstPersonCamera(m_CharacterLocomotion.FirstPersonPerspective);
  464.             }
  465.         }
  466.  
  467.         /// <summary>
  468.         /// Reset the ViewType's variables.
  469.         /// </summary>
  470.         /// <param name="characterRotation">The rotation of the character.</param>
  471.         public override void Reset(Quaternion characterRotation)
  472.         {
  473.             m_Pitch = 0;
  474.             m_Yaw = 0;
  475.             m_Shake = Vector3.zero;
  476.             m_CharacterRotation = characterRotation;
  477.             m_BobVerticalOffset = float.MaxValue;
  478.             m_BobVerticalOffsetDecreasing = false;
  479.             m_PrevBobSpeed = 0;
  480.             if (m_CharacterLocomotion.Platform != null) {
  481.                 UpdatePlatformRotationOffset(m_CharacterLocomotion.Platform);
  482.             }
  483.             if (m_CharacterAnchor != null) {
  484.                 m_CharacterAnchorRotation = MathUtility.InverseTransformQuaternion(m_CharacterRotation, m_CharacterAnchor.rotation);
  485.             }
  486.  
  487.             InitializePositionSpringValue();
  488.             m_PositionSpring.Reset();
  489.             m_RotationSpring.Reset();
  490.             m_SecondaryPositionSpring.Reset();
  491.             m_SecondaryRotationSpring.Reset();
  492.  
  493.             // The head position should be reset to the current values.
  494.             m_SmoothHeadBufferIndex = -1;
  495.             m_SmoothHeadBufferCount = 0;
  496.             UpdateHeadOffset();
  497.         }
  498.  
  499.         /// <summary>
  500.         /// Sets the crosshairs to the specified transform.
  501.         /// </summary>
  502.         /// <param name="crosshairs">The transform of the crosshairs.</param>
  503.         public override void SetCrosshairs(Transform crosshairs)
  504.         {
  505.             m_CrosshairsTransform = crosshairs;
  506.  
  507.             if (m_CrosshairsTransform != null) {
  508.                 m_CrosshairsCanvas = crosshairs.GetComponentInParent<Canvas>();
  509.                 m_CrosshairsMonitor = crosshairs.gameObject.GetCachedComponent<UI.CrosshairsMonitor>();
  510.                 m_CrosshairsPosition = -m_CrosshairsTransform.position;
  511.             }
  512.         }
  513.  
  514.         /// <summary>
  515.         /// Returns the delta rotation caused by the crosshairs.
  516.         /// </summary>
  517.         /// <returns>The delta rotation caused by the crosshairs.</returns>
  518.         public override Quaternion GetCrosshairsDeltaRotation()
  519.         {
  520.             if (m_CrosshairsTransform == null) {
  521.                 return Quaternion.identity;
  522.             }
  523.  
  524.             // The crosshairs direction should only be updated when it changes.
  525.             if (m_CrosshairsPosition != m_CrosshairsTransform.position) {
  526.                 Vector3 direction;
  527.                 if (m_CrosshairsCanvas.renderMode == RenderMode.ScreenSpaceOverlay) {
  528.                     var screenPoint = RectTransformUtility.WorldToScreenPoint(null, m_CrosshairsTransform.position);
  529.                     direction = m_Camera.ScreenPointToRay(screenPoint).direction;
  530.                 } else {
  531.                     direction = (m_CrosshairsTransform.position - m_Camera.transform.position).normalized;
  532.                 }
  533.                 m_CrosshairsDeltaRotation = Quaternion.LookRotation(direction, m_Transform.up) * Quaternion.Inverse(m_Transform.rotation);
  534.                 m_CrosshairsPosition = m_CrosshairsTransform.position;
  535.             }
  536.  
  537.             return m_CrosshairsDeltaRotation;
  538.         }
  539.  
  540.         /// <summary>
  541.         /// The moving platform object has changed.
  542.         /// </summary>
  543.         /// <param name="movingPlatform">The moving platform to set. Can be null.</param>
  544.         private void OnCharacterChangeMovingPlatforms(Transform movingPlatform)
  545.         {
  546.             if (movingPlatform != null) {
  547.                 UpdatePlatformRotationOffset(movingPlatform);
  548.             } else {
  549.                 m_PlatformRotation = Quaternion.identity;
  550.             }
  551.         }
  552.  
  553.         /// <summary>
  554.         /// Updates the Character Platform Rotation Offset variable.
  555.         /// </summary>
  556.         /// <param name="platform">The platform that the character is on top of.</param>
  557.         private void UpdatePlatformRotationOffset(Transform platform)
  558.         {
  559.             m_CharacterPlatformRotationOffset = m_CharacterRotation * Quaternion.Inverse(platform.rotation);
  560.             if (!m_CharacterLocomotion.AlignToGravity) {
  561.                 // Only the local y rotation should affect the character's rotation.
  562.                 var localPlatformRotationOffset = MathUtility.InverseTransformQuaternion(m_CharacterRotation, m_CharacterPlatformRotationOffset).eulerAngles;
  563.                 localPlatformRotationOffset.x = localPlatformRotationOffset.z = 0;
  564.                 m_CharacterPlatformRotationOffset = MathUtility.TransformQuaternion(m_CharacterRotation, Quaternion.Euler(localPlatformRotationOffset));
  565.             }
  566.         }
  567.  
  568.         /// <summary>
  569.         /// Updates the first person camera and culling mask depending on if the first person camera is in use.
  570.         /// </summary>
  571.         /// <param name="firstPersonPerspective">Is the character in a first person perspective?</param>
  572.         private void UpdateFirstPersonCamera(bool firstPersonPerspective)
  573.         {
  574. #if ULTIMATE_CHARACTER_CONTROLLER_UNIVERSALRP|| ULTIMATE_CHARACTER_CONTROLLER_HDRP
  575.             if (m_OverlayRenderType == ObjectOverlayRenderType.None) {
  576. #else
  577.             if (!m_UseFirstPersonCamera) {
  578. #endif
  579.                 return;
  580.             }
  581.  
  582.             if (firstPersonPerspective) {
  583.                 if (m_FirstPersonCamera != null) {
  584.                     m_FirstPersonCamera.gameObject.SetActive(true);
  585.                 }
  586. #if ULTIMATE_CHARACTER_CONTROLLER_UNIVERSALRP|| ULTIMATE_CHARACTER_CONTROLLER_HDRP
  587.                 if (m_OverlayRenderType == ObjectOverlayRenderType.RenderPipeline) {
  588.                     m_Camera.cullingMask |= m_FirstPersonCullingMask;
  589.                 }
  590. #endif
  591.             } else {
  592.                 if (m_FirstPersonCamera != null) {
  593.                     m_FirstPersonCamera.gameObject.SetActive(false);
  594.                 }
  595. #if ULTIMATE_CHARACTER_CONTROLLER_UNIVERSALRP|| ULTIMATE_CHARACTER_CONTROLLER_HDRP
  596.                 if (m_OverlayRenderType == ObjectOverlayRenderType.RenderPipeline) {
  597.                     m_Camera.cullingMask &= ~m_FirstPersonCullingMask;
  598.                 }
  599. #endif
  600.             }
  601.         }
  602.  
  603.         /// <summary>
  604.         /// The view type has changed.
  605.         /// </summary>
  606.         /// <param name="viewType">The ViewType that was activated or deactivated.</param>
  607.         /// <param name="activate">Should the current view type be activated?</param>
  608.         private void OnChangeViewType(ViewType viewType, bool activate)
  609.         {
  610.             if (activate || viewType == this) {
  611.                 return;
  612.             }
  613.  
  614.             // Apply the spring/shake values so when switching between first person view types it is a continuous motion.
  615.             if (viewType is FirstPerson) {
  616.                 var firstPersonViewType = (viewType as FirstPerson);
  617.                 m_PositionSpring.Value = firstPersonViewType.PositionSpring.Value;
  618.                 m_PositionSpring.Velocity = firstPersonViewType.PositionSpring.Velocity;
  619.                 m_RotationSpring.Value = firstPersonViewType.RotationSpring.Value;
  620.                 m_RotationSpring.Velocity = firstPersonViewType.RotationSpring.Velocity;
  621.                 m_Shake = firstPersonViewType.Shake;
  622.             }
  623.         }
  624.  
  625.         /// <summary>
  626.         /// Updates the camera field of view.
  627.         /// </summary>
  628.         /// <param name="immediateUpdate">Should the camera be updated immediately?</param>
  629.         public override void UpdateFieldOfView(bool immediateUpdate)
  630.         {
  631.             base.UpdateFieldOfView(immediateUpdate);
  632.  
  633.             if (m_FirstPersonCamera != null) {
  634.                 if (m_SynchronizeFieldOfView) {
  635.                     m_FirstPersonCamera.fieldOfView = m_Camera.fieldOfView;
  636.                 } else if (m_FirstPersonCamera.fieldOfView != m_FirstPersonFieldOfView) {
  637.                     var zoom = immediateUpdate ? 1 : ((Time.time - m_FirstPersonFieldOfViewChangeTime) / (m_FirstPersonFieldOfViewDamping / m_CharacterLocomotion.TimeScale));
  638.                     m_FirstPersonCamera.fieldOfView = Mathf.SmoothStep(m_FirstPersonCamera.fieldOfView, m_FirstPersonFieldOfView, zoom);
  639.                 }
  640.             }
  641.  
  642.  
  643.         }
  644.  
  645.  
  646.         /// <summary>
  647.         /// Rotates the camera according to the horizontal and vertical movement values.
  648.         /// </summary>
  649.         /// <param name="horizontalMovement">-1 to 1 value specifying the amount of horizontal movement.</param>
  650.         /// <param name="verticalMovement">-1 to 1 value specifying the amount of vertical movement.</param>
  651.         /// <param name="immediateUpdate">Should the camera be updated immediately?</param>
  652.         /// <returns>The updated rotation.</returns>
  653.         public override Quaternion Rotate(float horizontalMovement, float verticalMovement, bool immediateUpdate)
  654.         {
  655.             UpdateShakes();
  656.  
  657.             // Rotate with the moving platform.
  658.             if (m_CharacterLocomotion.Platform != null) {
  659.                 m_PlatformRotation = MathUtility.InverseTransformQuaternion(m_CharacterLocomotion.Platform.rotation, m_CharacterPlatformRotationOffset) *
  660.                     Quaternion.Inverse(MathUtility.InverseTransformQuaternion(m_CharacterLocomotion.Platform.rotation, m_CharacterRotation *
  661.                     Quaternion.Inverse(m_CharacterLocomotion.Platform.rotation)));
  662.                 if (!m_CharacterLocomotion.AlignToGravity) {
  663.                     // Only the local y rotation should affect the character's rotation.
  664.                     var localPlatformTorque = MathUtility.InverseTransformQuaternion(m_CharacterTransform.rotation, m_PlatformRotation).eulerAngles;
  665.                     localPlatformTorque.x = localPlatformTorque.z = 0;
  666.                     m_PlatformRotation = MathUtility.TransformQuaternion(m_CharacterTransform.rotation, Quaternion.Euler(localPlatformTorque));
  667.                 }
  668.                 m_CharacterRotation *= m_PlatformRotation;
  669.             }
  670.  
  671.             // The camera should always stay aligned to the character's up direction.
  672.             if (m_CharacterLocomotion.AlignToGravity) {
  673.                 var localRotation = MathUtility.InverseTransformQuaternion(m_CharacterTransform.rotation, m_CharacterRotation).eulerAngles;
  674.                 localRotation.x = localRotation.z = 0;
  675.                 m_CharacterRotation = MathUtility.TransformQuaternion(m_CharacterTransform.rotation, Quaternion.Euler(localRotation));
  676.             }
  677.  
  678.             // Remember the offset so the delta can be compared the next update.
  679.             if (m_CharacterLocomotion.Platform != null) {
  680.                 UpdatePlatformRotationOffset(m_CharacterLocomotion.Platform);
  681.             }
  682.  
  683.             // Update the rotation. The pitch may have a limit.
  684.             if (Mathf.Abs(m_MinPitchLimit - m_MaxPitchLimit) < 180) {
  685.                 m_Pitch = MathUtility.ClampAngle(m_Pitch, -verticalMovement, m_MinPitchLimit, m_MaxPitchLimit);
  686.             } else {
  687.                 m_Pitch -= verticalMovement;
  688.             }
  689.  
  690.             // Prevent the values from getting too large.
  691.             m_Pitch = MathUtility.ClampInnerAngle(m_Pitch);
  692.             m_Yaw = MathUtility.ClampInnerAngle(m_Yaw);
  693.  
  694.             // If aim assist has a target then the camera should look in the specified direction.
  695.             if (m_AimAssist != null) {
  696.                 m_AimAssist.UpdateBreakForce(Mathf.Abs(horizontalMovement) + Mathf.Abs(verticalMovement));
  697.                 if (m_AimAssist.HasTarget()) {
  698.                     var rotation = MathUtility.TransformQuaternion(m_CharacterRotation, Quaternion.Euler(m_Pitch, m_Yaw, 0));
  699.                     var assistRotation = rotation * MathUtility.InverseTransformQuaternion(rotation, m_AimAssist.TargetRotation(rotation));
  700.                     // Set the pitch and yaw so when the target is lost the view type won't snap back to the previous rotation value.
  701.                     var localAssistRotation = MathUtility.InverseTransformQuaternion(m_CharacterRotation, assistRotation).eulerAngles;
  702.                     m_Pitch = MathUtility.ClampInnerAngle(localAssistRotation.x);
  703.                     m_Yaw = MathUtility.ClampInnerAngle(localAssistRotation.y);
  704.                 }
  705.             }
  706.  
  707.             var headRotation = Quaternion.identity;
  708.             if (m_RotateWithHead) {
  709.                 headRotation = MathUtility.InverseTransformQuaternion(m_CharacterRotation, m_CharacterAnchor.rotation) * Quaternion.Inverse(m_CharacterAnchorRotation);
  710.                 // The camera should only follow the pitch of the head rotation.
  711.                 var eulerHeadRotation = headRotation.eulerAngles;
  712.                 eulerHeadRotation.y = eulerHeadRotation.z = 0;
  713.                 headRotation = Quaternion.Euler(eulerHeadRotation);
  714.             }
  715.  
  716.             // Return the rotation.
  717.             return MathUtility.TransformQuaternion(m_CharacterRotation, Quaternion.Euler(m_Pitch, m_Yaw, 0)) *
  718.                                                         Quaternion.Euler(m_RotationSpring.Value) *
  719.                                                         Quaternion.Euler(m_SecondaryRotationSpring.Value) * headRotation;
  720.         }
  721.  
  722.         /// <summary>
  723.         /// Updates the procedular shaking of the camera.
  724.         /// </summary>
  725.         private void UpdateShakes()
  726.         {
  727.             if (m_ShakeSpeed == 0) {
  728.                 return;
  729.             }
  730.  
  731.             // Subtract shake from the last frame or the camera will drift.
  732.             m_Yaw -= m_Shake.x;
  733.             m_Pitch -= m_Shake.y;
  734.  
  735.             // Apply the new shake.
  736.             m_Shake = Vector3.Scale(SmoothRandom.GetVector3Centered(m_ShakeSpeed), m_ShakeAmplitude);
  737.             m_Yaw += m_Shake.x;
  738.             m_Pitch += m_Shake.y;
  739.             m_RotationSpring.AddForce(Vector3.forward * m_Shake.z * m_CharacterLocomotion.TimeScale * Time.timeScale);
  740.         }
  741.  
  742.         /// <summary>
  743.         /// Moves the camera according to the current pitch and yaw values.
  744.         /// </summary>
  745.         /// <param name="immediateUpdate">Should the camera be updated immediately?</param>
  746.         /// <returns>The updated position.</returns>
  747.         public override Vector3 Move(bool immediateUpdate)
  748.         {
  749.             UpdateSway();
  750.  
  751.             UpdateBob();
  752.  
  753.             UpdateHeadOffset();
  754.  
  755.             var targetPosition = GetTargetPosition();
  756.  
  757.             // Adjust the camera position to prevent the body from clipping with the camera's spring-based motions.
  758.             if (m_MaxPitchLimit != 0) {
  759.                 var lookDown = Mathf.Max(0, m_Pitch / m_MaxPitchLimit);
  760.                 lookDown = Mathf.SmoothStep(0, 1, lookDown);
  761.                 targetPosition += m_Transform.TransformDirection(m_LookDownOffset * lookDown);
  762.             }
  763.  
  764.             // Ensure there aren't any objects obstructing the distance between the anchor offset and the target position.
  765.             var collisionLayerEnabled = m_CharacterLocomotion.CollisionLayerEnabled;
  766.             m_CharacterLocomotion.EnableColliderCollisionLayer(false);
  767.             var offset = m_PositionSpring.Value + GetHeadOffset();
  768.             offset.x = offset.z = 0;
  769.             var startPosition = GetAnchorTransformPoint(offset);
  770.             var direction = targetPosition - startPosition;
  771.             if (Physics.SphereCast(startPosition, m_CollisionRadius, direction.normalized, out m_RaycastHit, direction.magnitude + m_Camera.nearClipPlane,
  772.                             m_CharacterLayerManager.IgnoreInvisibleCharacterWaterLayers, QueryTriggerInteraction.Ignore)) {
  773.                 // Move the camera in if an object obstructed the view.
  774.                 targetPosition -= direction.normalized * ((direction.magnitude + m_Camera.nearClipPlane) - m_RaycastHit.distance);
  775.             }
  776.             m_CharacterLocomotion.EnableColliderCollisionLayer(collisionLayerEnabled);
  777.  
  778.             return targetPosition;
  779.         }
  780.  
  781.         /// <summary>
  782.         /// Returns the target position accounting for the springs and head offset.
  783.         /// </summary>
  784.         /// <returns>The target position accounting for the springs and head offset.</returns>
  785.         public Vector3 GetTargetPosition()
  786.         {
  787.             var targetPosition = GetAnchorTransformPoint(m_PositionSpring.Value + m_SecondaryPositionSpring.Value + Vector3.up * m_VerticalOffsetAdjustment);
  788.  
  789.             // The camera should move with the head offset of the character.
  790.             targetPosition += GetHeadOffset();
  791.  
  792.             return targetPosition;
  793.         }
  794.  
  795.         /// <summary>
  796.         /// Updates the head offset to match the current animator head position.
  797.         /// </summary>
  798.         private void UpdateHeadOffset()
  799.         {
  800.             // Allow the camera to move with the character's neck/head so the body doesn't clip the camera.
  801.             if (m_SmoothHeadBufferEvent == null && m_CharacterAnchor != null && m_SmoothHeadOffsetBuffer != null && m_SmoothHeadOffsetSteps > 0) {
  802.                 var offset = m_CharacterTransform.InverseTransformPoint(m_CharacterAnchor.position) - m_CharacterAnchorOffset;
  803.                 // Allow the offset to settle before storing the difference.
  804.                 if (offset.sqrMagnitude > 0) {
  805.                     // Add the current offset to the buffer.
  806.                     m_SmoothHeadBufferIndex = (m_SmoothHeadBufferIndex + 1) % m_SmoothHeadOffsetBuffer.Length;
  807.                     m_SmoothHeadOffsetBuffer[m_SmoothHeadBufferIndex] = offset;
  808.                     if (m_SmoothHeadBufferCount <= m_SmoothHeadBufferIndex) {
  809.                         m_SmoothHeadBufferCount++;
  810.                     }
  811.                 }
  812.             }
  813.         }
  814.  
  815.         /// <summary>
  816.         /// Returns the smoothed head offset.
  817.         /// </summary>
  818.         /// <returns>The smoothed head offset.</returns>
  819.         private Vector3 GetHeadOffset()
  820.         {
  821.             if (m_SmoothHeadBufferCount > 0) {
  822.                 // Find the average.
  823.                 var total = Vector3.zero;
  824.                 for (int i = 0; i < m_SmoothHeadBufferCount; ++i) {
  825.                     var index = m_SmoothHeadBufferIndex - i;
  826.                     if (index < 0) { index = m_SmoothHeadBufferCount + m_SmoothHeadBufferIndex - i; }
  827.                     total += m_SmoothHeadOffsetBuffer[index];
  828.                 }
  829.                 return m_CharacterTransform.TransformDirection(total / m_SmoothHeadBufferCount);
  830.             }
  831.  
  832.             return Vector3.zero;
  833.         }
  834.  
  835.         /// <summary>
  836.         /// Applies a sway force on the camera in response to character controller motion.
  837.         /// </summary>
  838.         private void UpdateSway()
  839.         {
  840.             var localVelocity = m_Transform.InverseTransformDirection(m_CharacterLocomotion.LocomotionVelocity * 0.016f) * m_CharacterLocomotion.TimeScale * Time.timeScale;
  841.             m_RotationSpring.AddForce(Vector3.forward * localVelocity.x * m_RotationStrafeRoll);
  842.         }
  843.  
  844.         /// <summary>
  845.         /// Updates the first person bob.
  846.         /// </summary>
  847.         private void UpdateBob()
  848.         {
  849.             if ((m_BobPositionalRate == Vector3.zero || m_BobPositionalAmplitude == Vector3.zero) && (m_BobRollRate == 0 || m_BobRollAmplitude == 0)) {
  850.                 return;
  851.             }
  852.  
  853.             var bobSpeed = ((m_BobRequireGroundContact && !m_CharacterLocomotion.Grounded) ? 0 : m_CharacterLocomotion.LocomotionVelocity.sqrMagnitude);
  854.  
  855.             // Scale and limit the input velocity.
  856.             bobSpeed = Mathf.Min(bobSpeed * m_BobInputVelocityScale, m_BobMaxInputVelocity);
  857.  
  858.             // Reduce the number of decimals to avoid floating point imprecision issues.
  859.             bobSpeed = Mathf.Round(bobSpeed * 1000) / 1000;
  860.  
  861.             // If the bob speed is zero then fade out the last speed value. It is important to clamp the speed to the
  862.             // last bob speed value because a preset may have changed since the last last bob.
  863.             if (bobSpeed == 0) {
  864.                 bobSpeed = Mathf.Min((m_PrevBobSpeed * 0.93f), m_BobMaxInputVelocity);
  865.             }
  866.  
  867.             // Update the positional and roll bob value.
  868.             var currentPositionalBobAmplitude = (bobSpeed * (m_BobPositionalAmplitude * -0.0001f));
  869.             var currentRollBobAmplitude = (bobSpeed * (m_BobRollAmplitude * -0.0001f));
  870.             Vector3 currentBobOffsetValue;
  871.             currentBobOffsetValue.x = Mathf.Cos(m_BobPositionalRate.x * m_CharacterLocomotion.TimeScale * Time.time * 10) * currentPositionalBobAmplitude.x;
  872.             currentBobOffsetValue.y = Mathf.Cos(m_BobPositionalRate.y * m_CharacterLocomotion.TimeScale * Time.time * 10) * currentPositionalBobAmplitude.y;
  873.             currentBobOffsetValue.z = Mathf.Cos(m_BobPositionalRate.z * m_CharacterLocomotion.TimeScale * Time.time * 10) * currentPositionalBobAmplitude.z;
  874.             var currentBobRollValue = Mathf.Cos(m_BobRollRate * m_CharacterLocomotion.TimeScale * Time.time * 10) * currentRollBobAmplitude;
  875.  
  876.             // Add the bob value to the positional and rotational spring.
  877.             m_PositionSpring.AddForce(currentBobOffsetValue);
  878.             m_RotationSpring.AddForce(Vector3.forward * currentBobRollValue);
  879.             m_PrevBobSpeed = bobSpeed;
  880.  
  881.             // Detect if the bob was previously decreasing and is now moving back up. This will indicate that the bob was at the lowest position.
  882.             if (currentBobOffsetValue.y < m_BobMinTroughVerticalOffset && m_BobVerticalOffset < currentBobOffsetValue.y && m_BobVerticalOffsetDecreasing) {
  883.                 m_SecondaryPositionSpring.AddForce(m_BobTroughForce);
  884.             }
  885.             m_BobVerticalOffsetDecreasing = currentBobOffsetValue.y < m_BobVerticalOffset;
  886.             m_BobVerticalOffset = currentBobOffsetValue.y;
  887.         }
  888.  
  889.         /// <summary>
  890.         /// Returns the direction that the character is looking.
  891.         /// </summary>
  892.         /// <param name="characterLookDirection">Is the character look direction being retrieved?</param>
  893.         /// <returns>The direction that the character is looking.</returns>
  894.         public override Vector3 LookDirection(bool characterLookDirection)
  895.         {
  896.             var crosshairsDeltaRotation = characterLookDirection ? Quaternion.identity : GetCrosshairsDeltaRotation();
  897.             var shake = characterLookDirection ? Quaternion.Inverse(Quaternion.Euler(m_Shake.y, m_Shake.x, 0)) : Quaternion.identity;
  898.             var platformRotation = characterLookDirection ? Quaternion.Inverse(m_PlatformRotation) : Quaternion.identity;
  899.             return (m_Transform.rotation * crosshairsDeltaRotation * shake * platformRotation) * Vector3.forward;
  900.         }
  901.  
  902.         /// <summary>
  903.         /// Returns the direction that the character is looking.
  904.         /// </summary>
  905.         /// <param name="lookPosition">The position that the character is looking from.</param>
  906.         /// <param name="characterLookDirection">Is the character look direction being retrieved?</param>
  907.         /// <param name="layerMask">The LayerMask value of the objects that the look direction can hit.</param>
  908.         /// <param name="includeRecoil">Should recoil be included in the look direction?</param>
  909.         /// <param name="includeMovementSpread">Should the movement spread be included in the look direction?</param>
  910.         /// <returns>The direction that the character is looking.</returns>
  911.         public override Vector3 LookDirection(Vector3 lookPosition, bool characterLookDirection, int layerMask, bool includeRecoil, bool includeMovementSpread)
  912.         {
  913.             var collisionLayerEnabled = m_CharacterLocomotion.CollisionLayerEnabled;
  914.             m_CharacterLocomotion.EnableColliderCollisionLayer(false);
  915.  
  916.             // If a crosshairs is specified then the character should look at the crosshairs. Do not use the crosshairs delta for character look directions to prevent
  917.             // the character's rotation from being affected by the crosshairs.
  918.             var crosshairsDeltaRotation = characterLookDirection ? Quaternion.identity : GetCrosshairsDeltaRotation();
  919.             var shake = characterLookDirection ? Quaternion.Inverse(Quaternion.Euler(m_Shake.y, m_Shake.x, 0)) : Quaternion.identity;
  920.             var platformRotation = characterLookDirection ? Quaternion.Inverse(m_PlatformRotation) : Quaternion.identity;
  921.  
  922.             // Cast a ray from the camera point in the forward direction. The look direction is then the vector from the look position to the hit point.
  923.             var rotation = (includeRecoil ? m_Transform.rotation : MathUtility.TransformQuaternion(m_CharacterRotation, Quaternion.Euler(m_Pitch, m_Yaw, 0))) *
  924.                                                 crosshairsDeltaRotation * shake * platformRotation;
  925.             Vector3 hitPoint;
  926.             if (Physics.Raycast(m_Transform.position, rotation * Vector3.forward, out var hit, m_LookDirectionDistance, layerMask, QueryTriggerInteraction.Ignore)) {
  927.                 hitPoint = hit.point;
  928.             } else {
  929.                 Vector3 position;
  930.                 if (includeRecoil) {
  931.                     position = GetAnchorTransformPoint(m_PositionSpring.Value + m_SecondaryPositionSpring.Value);
  932.                 } else {
  933.                     position = lookPosition;
  934.                 }
  935.                 var lookDirection = Vector3.zero;
  936.                 lookDirection.Set(0, 0, m_LookDirectionDistance);
  937.                 hitPoint = MathUtility.TransformPoint(position, rotation, lookDirection);
  938.             }
  939.  
  940.             m_CharacterLocomotion.EnableColliderCollisionLayer(collisionLayerEnabled);
  941.             var direction = (hitPoint - lookPosition).normalized;
  942.             if (includeMovementSpread && m_CrosshairsMonitor != null) {
  943.                 var spread = m_CrosshairsMonitor.GetMovementSpread() * 180;
  944.                 if (spread > 0) {
  945.                     direction = (Quaternion.AngleAxis(Random.Range(-spread, spread), m_CharacterTransform.up) *
  946.                         Quaternion.AngleAxis(Random.Range(-spread, spread), m_CharacterTransform.right)) * m_Transform.forward;
  947.                 }
  948.             }
  949.             return direction;
  950.         }
  951.        
  952.         /// <summary>
  953.         /// Adds a positional force to the ViewType.
  954.         /// </summary>
  955.         /// <param name="force">The force to add.</param>
  956.         public override void AddPositionalForce(Vector3 force)
  957.         {
  958.             m_PositionSpring.AddForce(force);
  959.         }
  960.  
  961.         /// <summary>
  962.         /// Adds a rotational force to the ViewType. The secondary position spring is more stiff compared to the primary positional spring.
  963.         /// </summary>
  964.         /// <param name="force">The force to add.</param>
  965.         public override void AddRotationalForce(Vector3 force)
  966.         {
  967.             m_RotationSpring.AddForce(force);
  968.         }
  969.  
  970.         /// <summary>
  971.         /// Adds a secondary positional force to the ViewType.
  972.         /// </summary>
  973.         /// <param name="force">The force to add.</param>
  974.         /// <param name="restAccumulation">The percent of the force to accumulate to the rest value.</param>
  975.         public override void AddSecondaryPositionalForce(Vector3 force, float restAccumulation)
  976.         {
  977.             if (restAccumulation > 0 && (m_AimAssist == null || !m_AimAssist.HasTarget())) {
  978.                 m_SecondaryPositionSpring.RestValue += force * restAccumulation;
  979.             }
  980.             m_SecondaryPositionSpring.AddForce(force);
  981.         }
  982.  
  983.         /// <summary>
  984.         /// Adds a delayed rotational force to the ViewType.
  985.         /// </summary>
  986.         /// <param name="force">The force to add.</param>
  987.         /// <param name="restAccumulation">The percent of the force to accumulate to the rest value.</param>
  988.         public override void AddSecondaryRotationalForce(Vector3 force, float restAccumulation)
  989.         {
  990.             if (restAccumulation > 0 && (m_AimAssist == null || !m_AimAssist.HasTarget())) {
  991.                 m_Pitch += force.x * restAccumulation;
  992.                 m_Yaw += force.y * restAccumulation;
  993.                 var springRest = m_SecondaryRotationSpring.RestValue;
  994.                 springRest.z += force.z * restAccumulation;
  995.                 m_SecondaryRotationSpring.RestValue = springRest;
  996.             }
  997.             m_SecondaryRotationSpring.AddForce(force);
  998.         }
  999.  
  1000.         /// <summary>
  1001.         /// The character has landed on the ground.
  1002.         /// </summary>
  1003.         /// <param name="height">The height of the fall.</param>
  1004.         private void OnCharacterLand(float height)
  1005.         {
  1006.             var positionImpact = height * m_PositionFallImpact;
  1007.             var rotationImpact = height * m_RotationFallImpact;
  1008.  
  1009.             // Apply impact to camera position spring.
  1010.             m_PositionSpring.AddForce(positionImpact * -Vector3.up, m_PositionFallImpactSoftness);
  1011.  
  1012.             // Apply impact to camera rotation spring. Randomize the rotation upon landing.
  1013.             var roll = Random.value > 0.5f ? (rotationImpact * 2) : -(rotationImpact * 2);
  1014.             m_RotationSpring.AddForce(Vector3.forward * roll, m_RotationFallImpactSoftness);
  1015.         }
  1016.  
  1017.         /// <summary>
  1018.         /// The character has started to lean.
  1019.         /// </summary>
  1020.         /// <param name="distance">The distance that the character is leaning.</param>
  1021.         /// <param name="tilt">The amount of tilt to apply to the lean.</param>
  1022.         /// <param name="itemTiltMultiplier">The multiplier to apply to the tilt of an item.</param>
  1023.         private void OnCharacterLean(float distance, float tilt, float itemTiltMultiplier)
  1024.         {
  1025.             m_PositionSpring.RestValue = m_CameraController.AnchorOffset + m_LookOffset + distance * Vector3.right;
  1026.             m_RotationSpring.RestValue = tilt * Vector3.forward;
  1027.         }
  1028.  
  1029.         /// <summary>
  1030.         /// Adjusts the vertical offset by the given amount.
  1031.         /// </summary>
  1032.         /// <param name="amount">The amount to adjust the vertical offset height by.</param>
  1033.         private void AdjustVerticalOffset(float amount)
  1034.         {
  1035.             m_VerticalOffsetAdjustment += amount;
  1036.         }
  1037.  
  1038.         /// <summary>
  1039.         /// Callback when the StateManager will change the active state on the current object.
  1040.         /// </summary>
  1041.         public override void StateWillChange()
  1042.         {
  1043.             // Remember the interal spring values so they can be restored if a new spring is applied during the state change.
  1044.             m_PrevPositionSpringValue = m_PositionSpring.Value;
  1045.             m_PrevPositionSpringVelocity = m_PositionSpring.Velocity;
  1046.             m_PrevRotationSpringValue = m_RotationSpring.Value;
  1047.             m_PrevRotationSpringVelocity = m_RotationSpring.Velocity;
  1048.             m_PrevSecondaryPositionSpringValue = m_SecondaryPositionSpring.Value;
  1049.             m_PrevSecondaryPositionSpringVelocity = m_SecondaryPositionSpring.Velocity;
  1050.             m_PrevSecondaryRotationSpringValue = m_SecondaryRotationSpring.Value;
  1051.             m_PrevSecondaryRotationSpringVelocity = m_SecondaryRotationSpring.Velocity;
  1052.             // Multiple state changes can occur within the same frame. Only remember the first damping value.
  1053.             if (m_StateChangeFrame != Time.frameCount) {
  1054.                 m_PrevFieldOfViewDamping = m_FieldOfViewDamping;
  1055.                 m_PrevFirstPersonFieldOfViewDamping = m_FirstPersonFieldOfViewDamping;
  1056.             }
  1057.             m_StateChangeFrame = Time.frameCount;
  1058.         }
  1059.  
  1060.         /// <summary>
  1061.         /// Callback when the StateManager has changed the active state on the current object.
  1062.         /// </summary>
  1063.         public override void StateChange()
  1064.         {
  1065.             // Append the zoom state name so the combination of state names will be called, such as "CrouchZoom".
  1066.             if (!string.IsNullOrEmpty(m_CameraController.ZoomState) && !m_AppendingZoomState) {
  1067.                 m_AppendingZoomState = true;
  1068.                 for (int i = 0; i < m_States.Length; ++i) {
  1069.                     StateManager.SetState(m_GameObject, m_States[i].Name + m_CameraController.ZoomState, m_States[i].Active && m_CameraController.ZoomInput);
  1070.                 }
  1071.                 m_AppendingZoomState = false;
  1072.             }
  1073.  
  1074.             if (m_Camera.fieldOfView != m_FieldOfView) {
  1075.                 m_FieldOfViewChangeTime = Time.time;
  1076.                 // The field of view should get a head start if the damping was previously 0. This will allow the field of view to move back to the original value even
  1077.                 // when the state is no longer active.
  1078.                 if (m_CameraController.ActiveViewType == this && m_PrevFieldOfViewDamping == 0) {
  1079.                     m_Camera.fieldOfView = (m_Camera.fieldOfView + m_FieldOfView) * 0.5f;
  1080.                     if (m_FirstPersonCamera != null && m_SynchronizeFieldOfView) {
  1081.                         m_FirstPersonCamera.fieldOfView = m_Camera.fieldOfView;
  1082.                     }
  1083.                 }
  1084.             }
  1085.             if (m_FirstPersonCamera != null && m_FirstPersonCamera.fieldOfView != m_FirstPersonFieldOfView) {
  1086.                 m_FirstPersonFieldOfViewChangeTime = Time.time;
  1087.                 // The field of view should get a head start if the damping was previously 0. This will allow the field of view to move back to the original value even
  1088.                 // when the state is no longer active.
  1089.                 if (m_CameraController.ActiveViewType == this && m_PrevFirstPersonFieldOfViewDamping == 0) {
  1090.                     m_FirstPersonCamera.fieldOfView = (m_FirstPersonCamera.fieldOfView + m_FirstPersonFieldOfView) * 0.5f;
  1091.                 }
  1092.             }
  1093.  
  1094.             m_PositionSpring.Value = m_PrevPositionSpringValue;
  1095.             m_PositionSpring.Velocity = m_PrevPositionSpringVelocity;
  1096.             m_RotationSpring.Value = m_PrevRotationSpringValue;
  1097.             m_RotationSpring.Velocity = m_PrevRotationSpringVelocity;
  1098.             m_SecondaryPositionSpring.Value = m_PrevSecondaryPositionSpringValue;
  1099.             m_SecondaryPositionSpring.Velocity = m_PrevSecondaryPositionSpringVelocity;
  1100.             m_SecondaryRotationSpring.Value = m_PrevSecondaryRotationSpringValue;
  1101.             m_SecondaryRotationSpring.Velocity = m_PrevSecondaryRotationSpringVelocity;
  1102.         }
  1103.  
  1104.         /// <summary>
  1105.         /// The camera has been destroyed.
  1106.         /// </summary>
  1107.         public override void OnDestroy()
  1108.         {
  1109.             base.OnDestroy();
  1110.  
  1111.             m_PositionSpring.Destroy();
  1112.             m_RotationSpring.Destroy();
  1113.             m_SecondaryPositionSpring.Destroy();
  1114.             m_SecondaryRotationSpring.Destroy();
  1115.  
  1116.             EventHandler.UnregisterEvent(m_GameObject, "OnAnchorOffsetUpdated", InitializePositionSpringValue);
  1117.             EventHandler.UnregisterEvent<ViewType, bool>(m_GameObject, "OnCameraChangeViewTypes", OnChangeViewType);
  1118.         }
  1119.     }
  1120. }
  1121.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement