Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Camera Collision Raycast/Spherecast Help

Discussion in 'Scripting' started by PegasiStudios, Jun 22, 2018.

  1. PegasiStudios

    PegasiStudios

    Joined:
    Dec 22, 2014
    Posts:
    26
    I'm currently working on a 3D Platformer and have been trying to make my camera avoid going through collision with Spherecasts. I managed to get a basic spherecast working, but I'm not entirely sure what to do next with the actual camera zoom and collision.

    Any idea as to what should be executed to prevent clipping?

    Most of what should be looked at is in Update() I'm assuming at least.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class playerVerySmartCamera : MonoBehaviour {
    5.  
    6.     public bool AutoTrack = false;
    7.     public int CameraMode = 0;
    8.  
    9.     public GameObject CharacterMesh;
    10.  
    11.     public GameObject CameraFar;
    12.     public GameObject CameraNormal;
    13.     public GameObject CameraClose;
    14.  
    15.     //SPHERECAST STUFF
    16.     public GameObject currentHitObject;
    17.  
    18.     public float sphereRadius;
    19.     public float CastMaxDistance;
    20.     public LayerMask layerMask;
    21.  
    22.     private Vector3 origin;
    23.     public Vector3 castdirection;
    24.  
    25.     private float currentHitDistance;
    26.     //SPHERECAST STUFF
    27.  
    28.  
    29.     public float InitialPosition = 9.3f;
    30.  
    31.     public float YSensitivity = 45.0f;
    32.     public float XSensitivity = 45.0f;
    33.  
    34.     public float MinDistance = 5.0f;
    35.     public float MaxDistance = 15.0f;
    36.  
    37.     public float MinHeight = 2.0f;
    38.     public float MaxHeight = 8.0f;
    39.  
    40.     public float MinAngle = 10.0f;
    41.     public float MaxAngle = 30.0f;
    42.  
    43.     public float MinDampWeight = 0.75f;
    44.     public float MaxDampWeight = 0.3f;
    45.  
    46.     public float MinDropDistance = 10.0f;
    47.     public float MaxDropDistance = 25.0f;
    48.  
    49.     public float MinDropRotation = 0.0f;
    50.     public float MaxDropRotation = 60.0f;
    51.  
    52.     public float MinMaximumJumpHeight = 5.0f;
    53.     public float MaxMaximumJumpHeight = 8.0f;
    54.  
    55.     public float MinMaxHeightAdjustment = 5.0f;
    56.     public float MaxMaxHeightAdjustment = 12.0f;
    57.  
    58.     public Transform target { get; private set; }
    59.     private playerMachine player;
    60.     private playerInput input;
    61.     public playerSound sound;
    62.     private SuperCharacterController controller;
    63.  
    64.     // Lerp value for Distance, Height and Angle between 0 and 1
    65.     private float currentCameraPosition;
    66.     private float currentRotationHorizontal;
    67.     private float currentRotationVertical;
    68.  
    69.     private float currentRotationVelocity;
    70.  
    71.     private Vector3 liftoffPoint;
    72.     private Vector3 verticalPosition;
    73.     private Vector3 currentDampVelocity;
    74.  
    75.     private Vector3 planarPosition;
    76.     private Vector3 planarDampVelocity;
    77.     private bool planarDamping = false;
    78.  
    79.     private Vector3 cameraShakePosition;
    80.     private Vector3 constantShakePosition;
    81.  
    82.     private IEnumerator shakeCoroutine;
    83.  
    84.     void Start () {
    85.  
    86.         currentCameraPosition = InitialPosition;
    87.  
    88.         CameraMode = 0;
    89.  
    90.         target = GameObject.FindWithTag("Player").transform;
    91.  
    92.         input = target.GetComponent<playerInput>();
    93.         player = target.GetComponent<playerMachine>();
    94.         sound = target.GetComponent<playerSound>();
    95.         controller = target.GetComponent<SuperCharacterController>();
    96.  
    97.         currentRotationHorizontal = player.InitialRotation;
    98.  
    99.         var height = Mathf.Lerp(MinHeight, MaxHeight, currentCameraPosition);
    100.  
    101.         verticalPosition = Math3d.ProjectPointOnLine(Vector3.zero, controller.up, target.position + height * controller.up);
    102.  
    103.         StartCoroutine(ConstantShake());
    104.  
    105.     }
    106.  
    107.     float currentShakeMagnitude;
    108.  
    109.     public void ConstantShake(float magnitude)
    110.     {
    111.         currentShakeMagnitude = Mathf.Max(currentShakeMagnitude, magnitude);
    112.     }
    113.  
    114.         public void Shake(float magnitude, float speed, float duration)
    115.     {
    116.         StopShake();
    117.         shakeCoroutine = CameraShake(magnitude, speed, duration, true);
    118.         StartCoroutine(shakeCoroutine);
    119.     }
    120.  
    121.     public void StopShake()
    122.     {
    123.         if (shakeCoroutine != null)
    124.             StopCoroutine(shakeCoroutine);
    125.     }
    126.  
    127.  
    128.  
    129.     IEnumerator CameraShake(float magnitude, float speed, float duration, bool damp)
    130.     {
    131.         cameraShakePosition = Vector3.zero;
    132.  
    133.         Vector3 targetPosition = cameraShakePosition;
    134.  
    135.         float shakeStartTime = Time.time;
    136.  
    137.         while (!SuperMath.Timer(shakeStartTime, duration))
    138.         {
    139.             cameraShakePosition = Vector3.MoveTowards(cameraShakePosition, targetPosition, speed * Time.deltaTime);
    140.  
    141.             float magModifier = 1.0f - Mathf.InverseLerp(shakeStartTime, shakeStartTime + duration, Time.time);
    142.  
    143.             if (cameraShakePosition == targetPosition)
    144.             {
    145.                 targetPosition = Vector3.zero + Random.insideUnitSphere * magnitude * magModifier;
    146.             }
    147.  
    148.             yield return 0;
    149.         }
    150.  
    151.         while (cameraShakePosition != Vector3.zero)
    152.         {
    153.             cameraShakePosition = Vector3.MoveTowards(cameraShakePosition, Vector3.zero, speed * Time.deltaTime);
    154.  
    155.             yield return 0;
    156.         }
    157.     }
    158.  
    159.     IEnumerator ConstantShake()
    160.     {
    161.         constantShakePosition = Vector3.zero;
    162.  
    163.         Vector3 targetPosition = constantShakePosition;
    164.  
    165.         while (true)
    166.         {
    167.             if (currentShakeMagnitude != 0)
    168.             {
    169.                 constantShakePosition = Vector3.MoveTowards(constantShakePosition, targetPosition, 10.0f * Time.deltaTime);
    170.  
    171.                 if (constantShakePosition == targetPosition)
    172.                 {
    173.                     targetPosition = Vector3.zero + Random.insideUnitSphere * currentShakeMagnitude;
    174.                 }
    175.             }
    176.             else
    177.             {
    178.                 constantShakePosition = Vector3.MoveTowards(constantShakePosition, Vector3.zero, 10.0f * Time.deltaTime);
    179.             }
    180.  
    181.             yield return 0;
    182.         }
    183.     }
    184.  
    185.     void Update () {
    186.  
    187.         var height = Mathf.Lerp(MinHeight, MaxHeight, currentCameraPosition);
    188.         var maxHeight = Mathf.Lerp(MinMaximumJumpHeight, MaxMaximumJumpHeight, currentCameraPosition);
    189.         var maxHeightAdjustment = Mathf.Lerp(MinMaxHeightAdjustment, MaxMaxHeightAdjustment, currentCameraPosition);
    190.         var distance = Mathf.Lerp(MinDistance, MaxDistance, currentCameraPosition);
    191.         var angle = Mathf.Lerp(MinAngle, MaxAngle, currentCameraPosition);
    192.         var weight = Mathf.Lerp(MinDampWeight, MaxDampWeight, currentCameraPosition);
    193.  
    194.         Vector3 targetPoint = target.position;
    195.  
    196.         origin = transform.position;
    197.         castdirection = -transform.forward;
    198.         RaycastHit hit;
    199.         if (Physics.SphereCast(origin, sphereRadius, castdirection, out hit, CastMaxDistance, layerMask, QueryTriggerInteraction.UseGlobal))
    200.         {
    201.             currentHitObject = hit.transform.gameObject;
    202.             currentHitDistance = hit.distance;
    203.         }
    204.         else
    205.         {
    206.             currentHitDistance = CastMaxDistance;
    207.             currentHitObject = null;
    208.         }
    209.  
    210.         if (player.StateCompare(playerMachine.playerStates.Climb))
    211.         {
    212.             targetPoint = player.ClimbTarget();
    213.  
    214.             if (!planarDamping)
    215.             {
    216.                 SetPlanarDamping(true);
    217.             }
    218.         }
    219.         else
    220.         {
    221.             if (planarDamping)
    222.             {
    223.                 SetPlanarDamping(false);
    224.             }
    225.         }
    226.  
    227.         if (!player.Airborn())
    228.         {
    229.             liftoffPoint = targetPoint;
    230.  
    231.             verticalPosition = Vector3.SmoothDamp(verticalPosition, Math3d.ProjectPointOnLine(Vector3.zero, controller.up, targetPoint + height * controller.up), ref currentDampVelocity, 0.2f);
    232.  
    233.             currentRotationVertical = Mathf.SmoothDamp(currentRotationVertical, 0, ref currentRotationVelocity, 0.2f);
    234.         }
    235.         else
    236.         {
    237.             Vector3 groundPosition = Math3d.ProjectPointOnLine(Vector3.zero, controller.up, liftoffPoint);
    238.             Vector3 airPosition = Math3d.ProjectPointOnLine(Vector3.zero, controller.up, targetPoint);
    239.  
    240.             float jumpHeight = Vector3.Distance(groundPosition, airPosition);
    241.  
    242.             var dropRotation = Mathf.Lerp(MinDropRotation, MaxDropRotation, Mathf.InverseLerp(MinDropDistance, MaxDropDistance, jumpHeight));
    243.  
    244.             if (SuperMath.PointAbovePlane(controller.up, liftoffPoint, targetPoint))
    245.             {
    246.                 float extraJumpHeight = 0;
    247.  
    248.                 if (jumpHeight > maxHeight)
    249.                 {
    250.                     extraJumpHeight = Mathf.Clamp(jumpHeight - maxHeight, 0, maxHeightAdjustment);
    251.                 }
    252.  
    253.                 verticalPosition = Vector3.SmoothDamp(verticalPosition, groundPosition + controller.up * ((jumpHeight * weight) + height + extraJumpHeight), ref currentDampVelocity, 0.1f);
    254.             }
    255.             else if (SuperMath.PointAbovePlane(controller.up, liftoffPoint - controller.up * MinDropDistance, targetPoint))
    256.             {
    257.                 verticalPosition = Vector3.SmoothDamp(verticalPosition, Math3d.ProjectPointOnLine(Vector3.zero, controller.up, targetPoint + height * controller.up), ref currentDampVelocity, 0.1f);
    258.  
    259.             }
    260.             else
    261.             {
    262.                 currentRotationVertical = Mathf.SmoothDamp(currentRotationVertical, dropRotation, ref currentRotationVelocity, 0.5f);
    263.             }
    264.         }
    265.  
    266.         Vector3 direction = Math3d.ProjectVectorOnPlane(controller.up, (targetPoint - transform.position).normalized);
    267.  
    268.         float angleAdjustment = Vector3.Angle(direction, Math3d.ProjectVectorOnPlane(controller.up, transform.forward));
    269.  
    270.         if (!AutoTrack)
    271.             angleAdjustment = 0;
    272.  
    273.         angleAdjustment = SuperMath.PointAbovePlane(transform.right, transform.position, targetPoint) ? angleAdjustment : -angleAdjustment;
    274.  
    275.         currentRotationHorizontal = SuperMath.ClampAngle(currentRotationHorizontal - input.Current.CameraInput.x * XSensitivity + angleAdjustment);
    276.  
    277.         transform.rotation = Quaternion.AngleAxis(currentRotationHorizontal, controller.up);
    278.  
    279.         currentCameraPosition = Mathf.Clamp(currentCameraPosition - input.Current.CameraInput.y * YSensitivity, 0, 1);
    280.  
    281.         if (planarDamping)
    282.         {
    283.             planarPosition = Vector3.SmoothDamp(planarPosition, Math3d.ProjectPointOnPlane(controller.up, Vector3.zero, targetPoint), ref planarDampVelocity, 0.2f);
    284.         }
    285.         else
    286.         {
    287.             planarPosition = Math3d.ProjectPointOnPlane(controller.up, Vector3.zero, targetPoint);
    288.         }
    289.  
    290.         transform.position = planarPosition + verticalPosition - transform.forward * distance + cameraShakePosition + constantShakePosition;
    291.  
    292.         transform.rotation = Quaternion.AngleAxis(angle + currentRotationVertical, transform.right) * transform.rotation;
    293.  
    294.         currentShakeMagnitude = 0;
    295.  
    296.         if (Input.GetButtonDown("CameraSwitch"))
    297.         {
    298.             {
    299.                 CameraMode += 1;
    300.                 ModeCheck();
    301.             }
    302.  
    303.             if (CameraMode >= 3)
    304.             {
    305.                 CameraMode = 0;
    306.                 ModeCheck();
    307.             }
    308.         }
    309.     }
    310.  
    311.     private void OnDrawGizmosSelected()
    312.     {
    313.         Gizmos.color = Color.red;
    314.         Debug.DrawLine(origin, origin + castdirection * currentHitDistance);
    315.         Gizmos.DrawWireSphere(origin + castdirection * currentHitDistance, sphereRadius);
    316.     }
    317.  
    318.     void ModeCheck()
    319.     {
    320.         /*if (CameraMode == -1) //First Person
    321.         {
    322.             CharacterMesh.SetActive(false);
    323.             AutoTrack = false;
    324.             CameraNormal.SetActive(false);
    325.             CameraFar.SetActive(false);
    326.             CameraClose.SetActive(true);
    327.             MinDistance = -0.1f;
    328.             MaxDistance = -0.1f;
    329.             MinHeight = 2;
    330.             MaxHeight = 2;
    331.             MinAngle = -10;
    332.             MaxAngle = 70;
    333.             sound.JellyOn();
    334.             return;
    335.         }*/
    336.         if (CameraMode == 0) //Normal Camera
    337.         {
    338.             CharacterMesh.SetActive(true);
    339.             AutoTrack = true;
    340.             CameraNormal.SetActive(true);
    341.             CameraFar.SetActive(false);
    342.             CameraClose.SetActive(false);
    343.             MinDistance = 5.5f;
    344.             MaxDistance = 6.2f;
    345.             MinHeight = 2;
    346.             MaxHeight = 4;
    347.             MinAngle = -10;
    348.             MaxAngle = 30;
    349.             sound.JellyOff();
    350.             return;
    351.         }
    352.         if (CameraMode == 1) //Far Camera
    353.         {
    354.             CharacterMesh.SetActive(true);
    355.             AutoTrack = true;
    356.             CameraNormal.SetActive(false);
    357.             CameraFar.SetActive(true);
    358.             CameraClose.SetActive(false);
    359.             MinDistance = 6.0f;
    360.             MaxDistance = 8.5f;
    361.             MinHeight = 2.5f;
    362.             MaxHeight = 7;
    363.             MinAngle = 10;
    364.             MaxAngle = 40;
    365.             sound.JellyOff();
    366.             return;
    367.         }
    368.         if (CameraMode == 2) //CloseCamera
    369.         {
    370.             CharacterMesh.SetActive(true);
    371.             AutoTrack = true;
    372.             CameraNormal.SetActive(false);
    373.             CameraFar.SetActive(false);
    374.             CameraClose.SetActive(true);
    375.             MinDistance = 2.0f;
    376.             MaxDistance = 3.0f;
    377.             MinHeight = 2f;
    378.             MaxHeight = 3f;
    379.             MinAngle = 0;
    380.             MaxAngle = 20;
    381.             sound.JellyOn();
    382.             return;
    383.         }
    384.     }
    385.     void SetPlanarDamping(bool enabled)
    386.     {
    387.         planarDamping = enabled;
    388.         planarDampVelocity = Vector3.zero;
    389.     }
    390. }
    391.