Search Unity

Question Is there a way to have a different collision follow target than the virtual camera follow target?

Discussion in 'Cinemachine' started by kazumio, Jan 2, 2022.

  1. kazumio

    kazumio

    Joined:
    Mar 9, 2017
    Posts:
    10
    My situation is like this i have a virtual camera which i only use when i lock on to an enemy
    that camera follow my player with a regular transposer
    and it looks at a target group with a composer
    the target group consists of the player and the enemy that is currently locked on
    so in a situation when the player has a wall in front him (between the player and the target)
    the camera would not be behind the player and would snap to the wall and continue to aim at the group target

    upload_2022-1-2_18-36-6.png
    as shown in the picture
    any suggestions on how to avoid this scenario?
     
    Last edited: Jan 2, 2022
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,730
    You could try to make a custom version of CinemachineCollider that uses the follow target instead of the lookat target. Just copy it, rename, and modify. The new version will be available automatically in the Extensions dropdown of the vcam inspector.
     
    kazumio likes this.
  3. kazumio

    kazumio

    Joined:
    Mar 9, 2017
    Posts:
    10


    sorry for responding so late i haven't seen the notification and kinda abandoned the idea for the time,
    im back to trying again now

    at some function i can replace state.ReferenceLookAt with vcam.Follow.position
    but some functions dont have a reference to the vcam

    i think ill just add a transform field to the collider and use that
     
    Last edited: Apr 26, 2022
  4. kazumio

    kazumio

    Joined:
    Mar 9, 2017
    Posts:
    10
    Code (CSharp):
    1. #define CINEMACHINE_PHYSICS
    2. #define CINEMACHINE_PHYSICS_2D
    3.  
    4. #if CINEMACHINE_PHYSICS
    5.  
    6. using UnityEngine;
    7. using System.Collections.Generic;
    8. using Cinemachine.Utility;
    9. using UnityEngine.Serialization;
    10. using System;
    11.  
    12. namespace Cinemachine
    13. {
    14.  
    15.     /// <summary>
    16.     /// An add-on module for Cinemachine Virtual Camera that post-processes
    17.     /// the final position of the virtual camera. Based on the supplied settings,
    18.     /// the Collider will attempt to preserve the line of sight
    19.     /// with the LookAt target of the virtual camera by moving
    20.     /// away from objects that will obstruct the view.
    21.     ///
    22.     /// Additionally, the Collider can be used to assess the shot quality and
    23.     /// report this as a field in the camera State.
    24.     /// </summary>
    25.     [DocumentationSorting(DocumentationSortingAttribute.Level.UserRef)]
    26.     [AddComponentMenu("")] // Hide in menu
    27.     [SaveDuringPlay]
    28. #if UNITY_2018_3_OR_NEWER
    29.     [ExecuteAlways]
    30. #else
    31.    [ExecuteInEditMode]
    32. #endif
    33.     public class CinemachineColliderAlteredFollow : CinemachineExtension
    34.     {
    35.  
    36.         [SerializeField]
    37.         private Transform collisionFollowTarget;
    38.  
    39.         /// <summary>Objects on these layers will be detected.</summary>
    40.         [Header("Obstacle Detection")]
    41.         [Tooltip("Objects on these layers will be detected")]
    42.         public LayerMask m_CollideAgainst = 1;
    43.  
    44.         /// <summary>Obstacles with this tag will be ignored.  It is a good idea to set this field to the target's tag</summary>
    45.         [TagField]
    46.         [Tooltip("Obstacles with this tag will be ignored.  It is a good idea to set this field to the target's tag")]
    47.         public string m_IgnoreTag = string.Empty;
    48.  
    49.         /// <summary>Objects on these layers will never obstruct view of the target.</summary>
    50.         [Tooltip("Objects on these layers will never obstruct view of the target")]
    51.         public LayerMask m_TransparentLayers = 0;
    52.  
    53.         /// <summary>Obstacles closer to the target than this will be ignored</summary>
    54.         [Tooltip("Obstacles closer to the target than this will be ignored")]
    55.         public float m_MinimumDistanceFromTarget = 0.1f;
    56.  
    57.         /// <summary>
    58.         /// When enabled, will attempt to resolve situations where the line of sight to the
    59.         /// target is blocked by an obstacle
    60.         /// </summary>
    61.         [Space]
    62.         [Tooltip("When enabled, will attempt to resolve situations where the line of sight to the target is blocked by an obstacle")]
    63.         [FormerlySerializedAs("m_PreserveLineOfSight")]
    64.         public bool m_AvoidObstacles = true;
    65.  
    66.         /// <summary>
    67.         /// The raycast distance to test for when checking if the line of sight to this camera's target is clear.
    68.         /// </summary>
    69.         [Tooltip("The maximum raycast distance when checking if the line of sight to this camera's target is clear.  If the setting is 0 or less, the current actual distance to target will be used.")]
    70.         [FormerlySerializedAs("m_LineOfSightFeelerDistance")]
    71.         public float m_DistanceLimit = 0f;
    72.  
    73.         /// <summary>
    74.         /// Don't take action unless occlusion has lasted at least this long.
    75.         /// </summary>
    76.         [Tooltip("Don't take action unless occlusion has lasted at least this long.")]
    77.         public float m_MinimumOcclusionTime = 0f;
    78.  
    79.         /// <summary>
    80.         /// Camera will try to maintain this distance from any obstacle.
    81.         /// Increase this value if you are seeing inside obstacles due to a large
    82.         /// FOV on the camera.
    83.         /// </summary>
    84.         [Tooltip("Camera will try to maintain this distance from any obstacle.  Try to keep this value small.  Increase it if you are seeing inside obstacles due to a large FOV on the camera.")]
    85.         public float m_CameraRadius = 0.1f;
    86.  
    87.         /// <summary>The way in which the Collider will attempt to preserve sight of the target.</summary>
    88.         public enum ResolutionStrategy
    89.         {
    90.             /// <summary>Camera will be pulled forward along its Z axis until it is in front of
    91.             /// the nearest obstacle</summary>
    92.             PullCameraForward,
    93.             /// <summary>In addition to pulling the camera forward, an effort will be made to
    94.             /// return the camera to its original height</summary>
    95.             PreserveCameraHeight,
    96.             /// <summary>In addition to pulling the camera forward, an effort will be made to
    97.             /// return the camera to its original distance from the target</summary>
    98.             PreserveCameraDistance
    99.         };
    100.         /// <summary>The way in which the Collider will attempt to preserve sight of the target.</summary>
    101.         [Tooltip("The way in which the Collider will attempt to preserve sight of the target.")]
    102.         public ResolutionStrategy m_Strategy = ResolutionStrategy.PreserveCameraHeight;
    103.  
    104.         /// <summary>
    105.         /// Upper limit on how many obstacle hits to process.  Higher numbers may impact performance.
    106.         /// In most environments, 4 is enough.
    107.         /// </summary>
    108.         [Range(1, 10)]
    109.         [Tooltip("Upper limit on how many obstacle hits to process.  Higher numbers may impact performance.  In most environments, 4 is enough.")]
    110.         public int m_MaximumEffort = 4;
    111.  
    112.         /// <summary>
    113.         /// Smoothing to apply to obstruction resolution.  Nearest camera point is held for at least this long.
    114.         /// </summary>
    115.         [Range(0, 2)]
    116.         [Tooltip("Smoothing to apply to obstruction resolution.  Nearest camera point is held for at least this long")]
    117.         public float m_SmoothingTime = 0;
    118.  
    119.         /// <summary>
    120.         /// How gradually the camera returns to its normal position after having been corrected.
    121.         /// Higher numbers will move the camera more gradually back to normal.
    122.         /// </summary>
    123.         [Range(0, 10)]
    124.         [Tooltip("How gradually the camera returns to its normal position after having been corrected.  Higher numbers will move the camera more gradually back to normal.")]
    125.         [FormerlySerializedAs("m_Smoothing")]
    126.         public float m_Damping = 0;
    127.  
    128.         /// <summary>
    129.         /// How gradually the camera moves to resolve an occlusion.
    130.         /// Higher numbers will move the camera more gradually.
    131.         /// </summary>
    132.         [Range(0, 10)]
    133.         [Tooltip("How gradually the camera moves to resolve an occlusion.  Higher numbers will move the camera more gradually.")]
    134.         public float m_DampingWhenOccluded = 0;
    135.  
    136.         /// <summary>If greater than zero, a higher score will be given to shots when the target is closer to
    137.         /// this distance.  Set this to zero to disable this feature</summary>
    138.         [Header("Shot Evaluation")]
    139.         [Tooltip("If greater than zero, a higher score will be given to shots when the target is closer to this distance.  Set this to zero to disable this feature.")]
    140.         public float m_OptimalTargetDistance = 0;
    141.  
    142.         /// <summary>See wheter an object is blocking the camera's view of the target</summary>
    143.         /// <param name="vcam">The virtual camera in question.  This might be different from the
    144.         /// virtual camera that owns the collider, in the event that the camera has children</param>
    145.         /// <returns>True if something is blocking the view</returns>
    146.         public bool IsTargetObscured(ICinemachineCamera vcam)
    147.         {
    148.             return GetExtraState<VcamExtraState>(vcam).targetObscured;
    149.         }
    150.  
    151.         /// <summary>See whether the virtual camera has been moved nby the collider</summary>
    152.         /// <param name="vcam">The virtual camera in question.  This might be different from the
    153.         /// virtual camera that owns the collider, in the event that the camera has children</param>
    154.         /// <returns>True if the virtual camera has been displaced due to collision or
    155.         /// target obstruction</returns>
    156.         public bool CameraWasDisplaced(ICinemachineCamera vcam)
    157.         {
    158.             return GetExtraState<VcamExtraState>(vcam).colliderDisplacement > 0;
    159.         }
    160.  
    161.         private void OnValidate()
    162.         {
    163.             m_DistanceLimit = Mathf.Max(0, m_DistanceLimit);
    164.             m_MinimumOcclusionTime = Mathf.Max(0, m_MinimumOcclusionTime);
    165.             m_CameraRadius = Mathf.Max(0, m_CameraRadius);
    166.             m_MinimumDistanceFromTarget = Mathf.Max(0.01f, m_MinimumDistanceFromTarget);
    167.             m_OptimalTargetDistance = Mathf.Max(0, m_OptimalTargetDistance);
    168.         }
    169.  
    170.  
    171.         /// This must be small but greater than 0 - reduces false results due to precision
    172.         const float PrecisionSlush = 0.001f;
    173.  
    174.         /// <summary>
    175.         /// Per-vcam extra state info
    176.         /// </summary>
    177.         class VcamExtraState
    178.         {
    179.             public Vector3 m_previousDisplacement;
    180.             public Vector3 m_previousDisplacementCorrection;
    181.             public float colliderDisplacement;
    182.             public bool targetObscured;
    183.             public float occlusionStartTime;
    184.             public List<Vector3> debugResolutionPath;
    185.  
    186.             public void AddPointToDebugPath(Vector3 p)
    187.             {
    188. #if UNITY_EDITOR
    189.                 if (debugResolutionPath == null)
    190.                     debugResolutionPath = new List<Vector3>();
    191.                 debugResolutionPath.Add(p);
    192. #endif
    193.             }
    194.  
    195.             // Thanks to Sebastien LeTouze from Exiin Studio for the smoothing idea
    196.             private float m_SmoothedDistance;
    197.             private float m_SmoothedTime;
    198.             public float ApplyDistanceSmoothing(float distance, float smoothingTime)
    199.             {
    200.                 if (m_SmoothedTime != 0 && smoothingTime > Epsilon)
    201.                 {
    202.                     float now = Time.timeSinceLevelLoad;
    203.                     if (now - m_SmoothedTime < smoothingTime)
    204.                         return Mathf.Min(distance, m_SmoothedDistance);
    205.                 }
    206.                 return distance;
    207.             }
    208.             public void UpdateDistanceSmoothing(float distance, float smoothingTime)
    209.             {
    210.                 float now = Time.timeSinceLevelLoad;
    211.                 if (m_SmoothedDistance == 0 || distance <= m_SmoothedDistance)
    212.                 {
    213.                     m_SmoothedDistance = distance;
    214.                     m_SmoothedTime = now;
    215.                 }
    216.             }
    217.             public void ResetDistanceSmoothing(float smoothingTime)
    218.             {
    219.                 float now = Time.timeSinceLevelLoad;
    220.                 if (now - m_SmoothedTime >= smoothingTime)
    221.                     m_SmoothedDistance = m_SmoothedTime = 0;
    222.             }
    223.         };
    224.  
    225.         /// <summary>Inspector API for debugging collision resolution path</summary>
    226.         public List<List<Vector3>> DebugPaths
    227.         {
    228.             get
    229.             {
    230.                 List<List<Vector3>> list = new List<List<Vector3>>();
    231.                 List<VcamExtraState> extraStates = GetAllExtraStates<VcamExtraState>();
    232.                 foreach (var v in extraStates)
    233.                     if (v.debugResolutionPath != null && v.debugResolutionPath.Count > 0)
    234.                         list.Add(v.debugResolutionPath);
    235.                 return list;
    236.             }
    237.         }
    238.  
    239.         /// <summary>Callback to do the collision resolution and shot evaluation</summary>
    240.         protected override void PostPipelineStageCallback(
    241.             CinemachineVirtualCameraBase vcam,
    242.             CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
    243.         {
    244.             VcamExtraState extra = null;
    245.             if (stage == CinemachineCore.Stage.Body)
    246.             {
    247.                 extra = GetExtraState<VcamExtraState>(vcam);
    248.                 extra.targetObscured = false;
    249.                 extra.colliderDisplacement = 0;
    250.                 if (extra.debugResolutionPath != null)
    251.                     extra.debugResolutionPath.RemoveRange(0, extra.debugResolutionPath.Count);
    252.             }
    253.  
    254.             // Move the body before the Aim is calculated
    255.             if (stage == CinemachineCore.Stage.Body)
    256.             {
    257.                 if (m_AvoidObstacles)
    258.                 {
    259.                     Vector3 displacement = Vector3.zero;
    260.                     displacement = PreserveLignOfSight(ref state, ref extra);
    261.                     if (m_MinimumOcclusionTime > Epsilon)
    262.                     {
    263.                         float now = Time.timeSinceLevelLoad;
    264.                         if (displacement.sqrMagnitude < Epsilon)
    265.                             extra.occlusionStartTime = 0;
    266.                         else
    267.                         {
    268.                             if (extra.occlusionStartTime <= 0)
    269.                                 extra.occlusionStartTime = now;
    270.                             if (now - extra.occlusionStartTime < m_MinimumOcclusionTime)
    271.                                 displacement = extra.m_previousDisplacement;
    272.                         }
    273.                     }
    274.  
    275.                     // Apply distance smoothing
    276.                     if (m_SmoothingTime > Epsilon)
    277.                     {
    278.                         Vector3 pos = state.CorrectedPosition + displacement;
    279.                         Vector3 dir = pos - collisionFollowTarget.position;
    280.                         float distance = dir.magnitude;
    281.                         if (distance > Epsilon)
    282.                         {
    283.                             dir /= distance;
    284.                             if (!displacement.AlmostZero())
    285.                                 extra.UpdateDistanceSmoothing(distance, m_SmoothingTime);
    286.                             distance = extra.ApplyDistanceSmoothing(distance, m_SmoothingTime);
    287.                             displacement += (collisionFollowTarget.position + dir * distance) - pos;
    288.                         }
    289.                     }
    290.  
    291.                     float damping = m_Damping;
    292.                     if (displacement.AlmostZero())
    293.                         extra.ResetDistanceSmoothing(m_SmoothingTime);
    294.                     else
    295.                         damping = m_DampingWhenOccluded;
    296.                     if (damping > 0 && deltaTime >= 0)
    297.                     {
    298.                         Vector3 delta = displacement - extra.m_previousDisplacement;
    299.                         delta = Damper.Damp(delta, damping, deltaTime);
    300.                         displacement = extra.m_previousDisplacement + delta;
    301.                     }
    302.                     extra.m_previousDisplacement = displacement;
    303.                     Vector3 correction = RespectCameraRadius(state.CorrectedPosition + displacement, ref state);
    304.                     if (damping > 0 && deltaTime >= 0)
    305.                     {
    306.                         Vector3 delta = correction - extra.m_previousDisplacementCorrection;
    307.                         delta = Damper.Damp(delta, damping, deltaTime);
    308.                         correction = extra.m_previousDisplacementCorrection + delta;
    309.                     }
    310.                     displacement += correction;
    311.                     extra.m_previousDisplacementCorrection = correction;
    312.                     state.PositionCorrection += displacement;
    313.                     extra.colliderDisplacement += displacement.magnitude;
    314.                 }
    315.             }
    316.             // Rate the shot after the aim was set
    317.             if (stage == CinemachineCore.Stage.Aim)
    318.             {
    319.                 extra = GetExtraState<VcamExtraState>(vcam);
    320.                 extra.targetObscured = IsTargetOffscreen(state) || CheckForTargetObstructions(state);
    321.  
    322.                 // GML these values are an initial arbitrary attempt at rating quality
    323.                 if (extra.targetObscured)
    324.                     state.ShotQuality *= 0.2f;
    325.                 if (extra.colliderDisplacement > 0)
    326.                     state.ShotQuality *= 0.8f;
    327.  
    328.                 float nearnessBoost = 0;
    329.                 const float kMaxNearBoost = 0.2f;
    330.                 if (m_OptimalTargetDistance > 0 && state.HasLookAt)
    331.                 {
    332.                     float distance = Vector3.Magnitude(collisionFollowTarget.position - state.FinalPosition);
    333.                     if (distance <= m_OptimalTargetDistance)
    334.                     {
    335.                         float threshold = m_OptimalTargetDistance / 2;
    336.                         if (distance >= threshold)
    337.                             nearnessBoost = kMaxNearBoost * (distance - threshold)
    338.                                 / (m_OptimalTargetDistance - threshold);
    339.                     }
    340.                     else
    341.                     {
    342.                         distance -= m_OptimalTargetDistance;
    343.                         float threshold = m_OptimalTargetDistance * 3;
    344.                         if (distance < threshold)
    345.                             nearnessBoost = kMaxNearBoost * (1f - (distance / threshold));
    346.                     }
    347.                     state.ShotQuality *= (1f + nearnessBoost);
    348.                 }
    349.             }
    350.         }
    351.  
    352.         private Vector3 PreserveLignOfSight(ref CameraState state, ref VcamExtraState extra)
    353.         {
    354.             Vector3 displacement = Vector3.zero;
    355.             if (state.HasLookAt && m_CollideAgainst != 0
    356.                 && m_CollideAgainst != m_TransparentLayers)
    357.             {
    358.                 Vector3 cameraPos = state.CorrectedPosition;
    359.                 Vector3 lookAtPos = collisionFollowTarget.position;
    360.                 RaycastHit hitInfo = new RaycastHit();
    361.                 displacement = PullCameraInFrontOfNearestObstacle(
    362.                     cameraPos, lookAtPos, m_CollideAgainst & ~m_TransparentLayers, ref hitInfo);
    363.                 Vector3 pos = cameraPos + displacement;
    364.                 if (hitInfo.collider != null)
    365.                 {
    366.                     extra.AddPointToDebugPath(pos);
    367.                     if (m_Strategy != ResolutionStrategy.PullCameraForward)
    368.                     {
    369.                         Vector3 targetToCamera = cameraPos - lookAtPos;
    370.                         pos = PushCameraBack(
    371.                             pos, targetToCamera, hitInfo, lookAtPos,
    372.                             new Plane(state.ReferenceUp, cameraPos),
    373.                             targetToCamera.magnitude, m_MaximumEffort, ref extra);
    374.                     }
    375.                 }
    376.                 displacement = pos - cameraPos;
    377.             }
    378.             return displacement;
    379.         }
    380.  
    381.         private Vector3 PullCameraInFrontOfNearestObstacle(
    382.             Vector3 cameraPos, Vector3 lookAtPos, int layerMask, ref RaycastHit hitInfo)
    383.         {
    384.             Vector3 displacement = Vector3.zero;
    385.             Vector3 dir = cameraPos - lookAtPos;
    386.             float targetDistance = dir.magnitude;
    387.             if (targetDistance > Epsilon)
    388.             {
    389.                 dir /= targetDistance;
    390.                 float minDistanceFromTarget = Mathf.Max(m_MinimumDistanceFromTarget, Epsilon);
    391.                 if (targetDistance < minDistanceFromTarget + Epsilon)
    392.                     displacement = dir * (minDistanceFromTarget - targetDistance);
    393.                 else
    394.                 {
    395.                     float rayLength = targetDistance - minDistanceFromTarget;
    396.                     if (m_DistanceLimit > Epsilon)
    397.                         rayLength = Mathf.Min(m_DistanceLimit, rayLength);
    398.  
    399.                     // Make a ray that looks towards the camera, to get the obstacle closest to target
    400.                     Ray ray = new Ray(cameraPos - rayLength * dir, dir);
    401.                     rayLength += PrecisionSlush;
    402.                     if (rayLength > Epsilon)
    403.                     {
    404.                         if (RaycastIgnoreTag(ray, out hitInfo, rayLength, layerMask))
    405.                         {
    406.                             // Pull camera forward in front of obstacle
    407.                             float adjustment = Mathf.Max(0, hitInfo.distance - PrecisionSlush);
    408.                             displacement = ray.GetPoint(adjustment) - cameraPos;
    409.                         }
    410.                     }
    411.                 }
    412.             }
    413.             return displacement;
    414.         }
    415.  
    416.         private bool RaycastIgnoreTag(
    417.             Ray ray, out RaycastHit hitInfo, float rayLength, int layerMask)
    418.         {
    419.             float extraDistance = 0;
    420.             while (Physics.Raycast(
    421.                 ray, out hitInfo, rayLength, layerMask,
    422.                 QueryTriggerInteraction.Ignore))
    423.             {
    424.                 if (m_IgnoreTag.Length == 0 || !hitInfo.collider.CompareTag(m_IgnoreTag))
    425.                 {
    426.                     hitInfo.distance += extraDistance;
    427.                     return true;
    428.                 }
    429.  
    430.                 // Ignore the hit.  Pull ray origin forward in front of obstacle
    431.                 Ray inverseRay = new Ray(ray.GetPoint(rayLength), -ray.direction);
    432.                 if (!hitInfo.collider.Raycast(inverseRay, out hitInfo, rayLength))
    433.                     break;
    434.                 float deltaExtraDistance = rayLength - (hitInfo.distance - PrecisionSlush);
    435.                 if (deltaExtraDistance < Epsilon)
    436.                     break;
    437.                 extraDistance += deltaExtraDistance;
    438.                 rayLength = hitInfo.distance - PrecisionSlush;
    439.                 if (rayLength < Epsilon)
    440.                     break;
    441.                 ray.origin = inverseRay.GetPoint(rayLength);
    442.             }
    443.             return false;
    444.         }
    445.  
    446.         private Vector3 PushCameraBack(
    447.             Vector3 currentPos, Vector3 pushDir, RaycastHit obstacle,
    448.             Vector3 lookAtPos, Plane startPlane, float targetDistance, int iterations,
    449.             ref VcamExtraState extra)
    450.         {
    451.             // Take a step along the wall.
    452.             Vector3 pos = currentPos;
    453.             Vector3 dir = Vector3.zero;
    454.             if (!GetWalkingDirection(pos, pushDir, obstacle, ref dir))
    455.                 return pos;
    456.  
    457.             Ray ray = new Ray(pos, dir);
    458.             float distance = GetPushBackDistance(ray, startPlane, targetDistance, lookAtPos);
    459.             if (distance <= Epsilon)
    460.                 return pos;
    461.  
    462.             // Check only as far as the obstacle bounds
    463.             float clampedDistance = ClampRayToBounds(ray, distance, obstacle.collider.bounds);
    464.             distance = Mathf.Min(distance, clampedDistance + PrecisionSlush);
    465.  
    466.             RaycastHit hitInfo;
    467.             if (RaycastIgnoreTag(ray, out hitInfo, distance,
    468.                     m_CollideAgainst & ~m_TransparentLayers))
    469.             {
    470.                 // We hit something.  Stop there and take a step along that wall.
    471.                 float adjustment = hitInfo.distance - PrecisionSlush;
    472.                 pos = ray.GetPoint(adjustment);
    473.                 extra.AddPointToDebugPath(pos);
    474.                 if (iterations > 1)
    475.                     pos = PushCameraBack(
    476.                         pos, dir, hitInfo,
    477.                         lookAtPos, startPlane,
    478.                         targetDistance, iterations - 1, ref extra);
    479.  
    480.                 return pos;
    481.             }
    482.  
    483.             // Didn't hit anything.  Can we push back all the way now?
    484.             pos = ray.GetPoint(distance);
    485.  
    486.             // First check if we can still see the target.  If not, abort
    487.             dir = pos - lookAtPos;
    488.             float d = dir.magnitude;
    489.             RaycastHit hitInfo2;
    490.             if (d < Epsilon || RaycastIgnoreTag(
    491.                     new Ray(lookAtPos, dir), out hitInfo2, d - PrecisionSlush,
    492.                     m_CollideAgainst & ~m_TransparentLayers))
    493.                 return currentPos;
    494.  
    495.             // All clear
    496.             ray = new Ray(pos, dir);
    497.             extra.AddPointToDebugPath(pos);
    498.             distance = GetPushBackDistance(ray, startPlane, targetDistance, lookAtPos);
    499.             if (distance > Epsilon)
    500.             {
    501.                 if (!RaycastIgnoreTag(ray, out hitInfo, distance,
    502.                         m_CollideAgainst & ~m_TransparentLayers))
    503.                 {
    504.                     pos = ray.GetPoint(distance); // no obstacles - all good
    505.                     extra.AddPointToDebugPath(pos);
    506.                 }
    507.                 else
    508.                 {
    509.                     // We hit something.  Stop there and maybe take a step along that wall
    510.                     float adjustment = hitInfo.distance - PrecisionSlush;
    511.                     pos = ray.GetPoint(adjustment);
    512.                     extra.AddPointToDebugPath(pos);
    513.                     if (iterations > 1)
    514.                         pos = PushCameraBack(
    515.                             pos, dir, hitInfo, lookAtPos, startPlane,
    516.                             targetDistance, iterations - 1, ref extra);
    517.                 }
    518.             }
    519.             return pos;
    520.         }
    521.  
    522.         private RaycastHit[] m_CornerBuffer = new RaycastHit[4];
    523.         private bool GetWalkingDirection(
    524.             Vector3 pos, Vector3 pushDir, RaycastHit obstacle, ref Vector3 outDir)
    525.         {
    526.             Vector3 normal2 = obstacle.normal;
    527.  
    528.             // Check for nearby obstacles.  Are we in a corner?
    529.             float nearbyDistance = PrecisionSlush * 5;
    530.             int numFound = Physics.SphereCastNonAlloc(
    531.                 pos, nearbyDistance, pushDir.normalized, m_CornerBuffer, 0,
    532.                 m_CollideAgainst & ~m_TransparentLayers, QueryTriggerInteraction.Ignore);
    533.             if (numFound > 1)
    534.             {
    535.                 // Calculate the second normal
    536.                 for (int i = 0; i < numFound; ++i)
    537.                 {
    538.                     if (m_CornerBuffer[i].collider == null)
    539.                         continue;
    540.                     if (m_IgnoreTag.Length > 0 && m_CornerBuffer[i].collider.CompareTag(m_IgnoreTag))
    541.                         continue;
    542.                     Type type = m_CornerBuffer[i].collider.GetType();
    543.                     if (type == typeof(BoxCollider)
    544.                         || type == typeof(SphereCollider)
    545.                         || type == typeof(CapsuleCollider))
    546.                     {
    547.                         Vector3 p = m_CornerBuffer[i].collider.ClosestPoint(pos);
    548.                         Vector3 d = p - pos;
    549.                         if (d.magnitude > Vector3.kEpsilon)
    550.                         {
    551.                             if (m_CornerBuffer[i].collider.Raycast(
    552.                                 new Ray(pos, d), out m_CornerBuffer[i], nearbyDistance))
    553.                             {
    554.                                 if (!(m_CornerBuffer[i].normal - obstacle.normal).AlmostZero())
    555.                                     normal2 = m_CornerBuffer[i].normal;
    556.                                 break;
    557.                             }
    558.                         }
    559.                     }
    560.                 }
    561.             }
    562.  
    563.             // Walk along the wall.  If we're in a corner, walk their intersecting line
    564.             Vector3 dir = Vector3.Cross(obstacle.normal, normal2);
    565.             if (dir.AlmostZero())
    566.                 dir = Vector3.ProjectOnPlane(pushDir, obstacle.normal);
    567.             else
    568.             {
    569.                 float dot = Vector3.Dot(dir, pushDir);
    570.                 if (Mathf.Abs(dot) < Epsilon)
    571.                     return false;
    572.                 if (dot < 0)
    573.                     dir = -dir;
    574.             }
    575.             if (dir.AlmostZero())
    576.                 return false;
    577.  
    578.             outDir = dir.normalized;
    579.             return true;
    580.         }
    581.  
    582.         const float AngleThreshold = 0.1f;
    583.         float GetPushBackDistance(Ray ray, Plane startPlane, float targetDistance, Vector3 lookAtPos)
    584.         {
    585.             float maxDistance = targetDistance - (ray.origin - lookAtPos).magnitude;
    586.             if (maxDistance < Epsilon)
    587.                 return 0;
    588.             if (m_Strategy == ResolutionStrategy.PreserveCameraDistance)
    589.                 return maxDistance;
    590.  
    591.             float distance;
    592.             if (!startPlane.Raycast(ray, out distance))
    593.                 distance = 0;
    594.             distance = Mathf.Min(maxDistance, distance);
    595.             if (distance < Epsilon)
    596.                 return 0;
    597.  
    598.             // If we are close to parallel to the plane, we have to take special action
    599.             float angle = Mathf.Abs(UnityVectorExtensions.Angle(startPlane.normal, ray.direction) - 90);
    600.             if (angle < AngleThreshold)
    601.                 distance = Mathf.Lerp(0, distance, angle / AngleThreshold);
    602.             return distance;
    603.         }
    604.  
    605.         float ClampRayToBounds(Ray ray, float distance, Bounds bounds)
    606.         {
    607.             float d;
    608.             if (Vector3.Dot(ray.direction, Vector3.up) > 0)
    609.             {
    610.                 if (new Plane(Vector3.down, bounds.max).Raycast(ray, out d) && d > Epsilon)
    611.                     distance = Mathf.Min(distance, d);
    612.             }
    613.             else if (Vector3.Dot(ray.direction, Vector3.down) > 0)
    614.             {
    615.                 if (new Plane(Vector3.up, bounds.min).Raycast(ray, out d) && d > Epsilon)
    616.                     distance = Mathf.Min(distance, d);
    617.             }
    618.  
    619.             if (Vector3.Dot(ray.direction, Vector3.right) > 0)
    620.             {
    621.                 if (new Plane(Vector3.left, bounds.max).Raycast(ray, out d) && d > Epsilon)
    622.                     distance = Mathf.Min(distance, d);
    623.             }
    624.             else if (Vector3.Dot(ray.direction, Vector3.left) > 0)
    625.             {
    626.                 if (new Plane(Vector3.right, bounds.min).Raycast(ray, out d) && d > Epsilon)
    627.                     distance = Mathf.Min(distance, d);
    628.             }
    629.  
    630.             if (Vector3.Dot(ray.direction, Vector3.forward) > 0)
    631.             {
    632.                 if (new Plane(Vector3.back, bounds.max).Raycast(ray, out d) && d > Epsilon)
    633.                     distance = Mathf.Min(distance, d);
    634.             }
    635.             else if (Vector3.Dot(ray.direction, Vector3.back) > 0)
    636.             {
    637.                 if (new Plane(Vector3.forward, bounds.min).Raycast(ray, out d) && d > Epsilon)
    638.                     distance = Mathf.Min(distance, d);
    639.             }
    640.             return distance;
    641.         }
    642.  
    643.         private Collider[] mColliderBuffer = new Collider[5];
    644.         private static SphereCollider mCameraCollider;
    645.         private static GameObject mCameraColliderGameObject;
    646.         private Vector3 RespectCameraRadius(Vector3 cameraPos, ref CameraState state)
    647.         {
    648.             Vector3 result = Vector3.zero;
    649.             if (m_CameraRadius < Epsilon || m_CollideAgainst == 0)
    650.                 return result;
    651.  
    652.             Vector3 dir = state.HasLookAt ? (cameraPos - collisionFollowTarget.position) : Vector3.zero;
    653.             Ray ray = new Ray();
    654.             float distance = dir.magnitude;
    655.             if (distance > Epsilon)
    656.             {
    657.                 dir /= distance;
    658.                 ray = new Ray(state.ReferenceLookAt, dir);
    659.             }
    660.             // Pull it out of any intersecting obstacles
    661.             RaycastHit hitInfo;
    662.             int numObstacles = Physics.OverlapSphereNonAlloc(
    663.                 cameraPos, m_CameraRadius, mColliderBuffer,
    664.                 m_CollideAgainst, QueryTriggerInteraction.Ignore);
    665.             if (numObstacles == 0 && m_TransparentLayers != 0
    666.                 && distance > m_MinimumDistanceFromTarget + Epsilon)
    667.             {
    668.                 // Make sure the camera position isn't completely inside an obstacle.
    669.                 // OverlapSphereNonAlloc won't catch those.
    670.                 float d = distance - m_MinimumDistanceFromTarget;
    671.                 Vector3 targetPos = collisionFollowTarget.position + dir * m_MinimumDistanceFromTarget;
    672.                 if (RaycastIgnoreTag(new Ray(targetPos, dir), out hitInfo, d, m_CollideAgainst))
    673.                 {
    674.                     // Only count it if there's an incoming collision but not an outgoing one
    675.                     Collider c = hitInfo.collider;
    676.                     if (!c.Raycast(new Ray(cameraPos, -dir), out hitInfo, d))
    677.                         mColliderBuffer[numObstacles++] = c;
    678.                 }
    679.             }
    680.             if (numObstacles > 0 && distance == 0 || distance > m_MinimumDistanceFromTarget)
    681.             {
    682.                 if (mCameraColliderGameObject == null)
    683.                 {
    684.                     mCameraColliderGameObject = new GameObject("CinemachineCollider Collider");
    685.                     mCameraColliderGameObject.hideFlags = HideFlags.HideAndDontSave;
    686.                     mCameraColliderGameObject.transform.position = Vector3.zero;
    687.                     mCameraColliderGameObject.SetActive(true);
    688.                     mCameraCollider = mCameraColliderGameObject.AddComponent<SphereCollider>();
    689.                     mCameraCollider.isTrigger = true;
    690.                     var rb = mCameraColliderGameObject.AddComponent<Rigidbody>();
    691.                     rb.detectCollisions = false;
    692.                     rb.isKinematic = true;
    693.                 }
    694.                 mCameraCollider.radius = m_CameraRadius;
    695.                 Vector3 offsetDir;
    696.                 float offsetDistance;
    697.                 Vector3 newCamPos = cameraPos;
    698.                 for (int i = 0; i < numObstacles; ++i)
    699.                 {
    700.                     Collider c = mColliderBuffer[i];
    701.                     if (m_IgnoreTag.Length > 0 && c.CompareTag(m_IgnoreTag))
    702.                         continue;
    703.  
    704.                     // If we have a lookAt target, move the camera to the nearest edge of obstacle
    705.                     if (distance > m_MinimumDistanceFromTarget)
    706.                     {
    707.                         dir = newCamPos - collisionFollowTarget.position;
    708.                         float d = dir.magnitude;
    709.                         if (d > Epsilon)
    710.                         {
    711.                             dir /= d;
    712.                             ray = new Ray(collisionFollowTarget.position, dir);
    713.                             if (c.Raycast(ray, out hitInfo, d + m_CameraRadius))
    714.                                 newCamPos = ray.GetPoint(hitInfo.distance) - (dir * PrecisionSlush);
    715.                         }
    716.                     }
    717.                     if (Physics.ComputePenetration(
    718.                         mCameraCollider, newCamPos, Quaternion.identity,
    719.                         c, c.transform.position, c.transform.rotation,
    720.                         out offsetDir, out offsetDistance))
    721.                     {
    722.                         newCamPos += offsetDir * offsetDistance;
    723.                     }
    724.                 }
    725.                 result = newCamPos - cameraPos;
    726.             }
    727.  
    728.             // Respect the minimum distance from target - push camera back if we have to
    729.             if (distance > Epsilon)
    730.             {
    731.                 float minDistance = Mathf.Max(m_MinimumDistanceFromTarget, m_CameraRadius) + PrecisionSlush;
    732.                 Vector3 newOffset = cameraPos + result - collisionFollowTarget.position;
    733.                 if (newOffset.magnitude < minDistance)
    734.                     result = state.ReferenceLookAt - cameraPos + dir * minDistance;
    735.             }
    736.  
    737.             return result;
    738.         }
    739.  
    740.         private bool CheckForTargetObstructions(CameraState state)
    741.         {
    742.             if (state.HasLookAt)
    743.             {
    744.                 Vector3 lookAtPos = collisionFollowTarget.position;
    745.                 Vector3 pos = state.CorrectedPosition;
    746.                 Vector3 dir = lookAtPos - pos;
    747.                 float distance = dir.magnitude;
    748.                 if (distance < Mathf.Max(m_MinimumDistanceFromTarget, Epsilon))
    749.                     return true;
    750.                 Ray ray = new Ray(pos, dir.normalized);
    751.                 RaycastHit hitInfo;
    752.                 if (RaycastIgnoreTag(ray, out hitInfo,
    753.                         distance - m_MinimumDistanceFromTarget,
    754.                         m_CollideAgainst & ~m_TransparentLayers))
    755.                     return true;
    756.             }
    757.             return false;
    758.         }
    759.  
    760.         private bool IsTargetOffscreen(CameraState state)
    761.         {
    762.             if (state.HasLookAt)
    763.             {
    764.                 Vector3 dir = collisionFollowTarget.position - state.CorrectedPosition;
    765.                 dir = Quaternion.Inverse(state.CorrectedOrientation) * dir;
    766.                 if (state.Lens.Orthographic)
    767.                 {
    768.                     if (Mathf.Abs(dir.y) > state.Lens.OrthographicSize)
    769.                         return true;
    770.                     if (Mathf.Abs(dir.x) > state.Lens.OrthographicSize * state.Lens.Aspect)
    771.                         return true;
    772.                 }
    773.                 else
    774.                 {
    775.                     float fov = state.Lens.FieldOfView / 2;
    776.                     float angle = UnityVectorExtensions.Angle(dir.ProjectOntoPlane(Vector3.right), Vector3.forward);
    777.                     if (angle > fov)
    778.                         return true;
    779.  
    780.                     fov = Mathf.Rad2Deg * Mathf.Atan(Mathf.Tan(fov * Mathf.Deg2Rad) * state.Lens.Aspect);
    781.                     angle = UnityVectorExtensions.Angle(dir.ProjectOntoPlane(Vector3.up), Vector3.forward);
    782.                     if (angle > fov)
    783.                         return true;
    784.                 }
    785.             }
    786.             return false;
    787.         }
    788.  
    789.     }
    790. }
    791. #endif
    Don't think i did it right , it doesn't seem to work

    #Edit nvm it works i just forgot to setup the collision layers after switching the new collision component
    Thanks for the help
     
    Last edited: Apr 27, 2022
    Gregoryl likes this.