Пример #1
0
 /// <summary>
 /// Update is called once per frame
 /// </summary>
 public override void UpdateCameraPosition(float lookHorizontal, float lookVertical)
 {
     desiredPosition = GetCameraDesiredPosition(lookHorizontal, lookVertical);
     if (movementSpringDampingEnabled)
     {
         transform.position = Damping.SpringDamping(transform.position, desiredPosition, ref movementVelocity, movementSpringStiffness, movementSpringDamping);
     }
     else
     {
         transform.position = desiredPosition;
     }
 }
Пример #2
0
    /**
     * This is the optimal camera position that the camera moves towards
     */
    public Vector3 GetCameraDesiredPosition(float lookHorizontal, float lookVertical)
    {
        if (target == null)
        {
            return(lastCameraTargetPosition);
        }

        if (cameraType == ChaseCameraType.StayBehind)
        {
            Vector3 rotation = target.transform.rotation.eulerAngles;
            idealSpherical.polar = -rotation.y * Mathf.Deg2Rad - (Mathf.PI * 0.5f);
            if (lookHorizontalSpringDamped)
            {
                lookHorizontalActual = Damping.SpringDamping(lookHorizontalActual, lookHorizontal, ref lookHorizontalVelocity,
                                                             lookHorizontalSpringStiffness, lookHorizontalSpringDamping);
                idealSpherical.polar += lookHorizontalActual * (Mathf.PI * 0.99f);
            }
            if (lookVerticalSpringDamped)
            {
                lookVerticalActual = Damping.SpringDamping(lookVerticalActual, lookVertical, ref lookVerticalVelocity,
                                                           lookVerticalSpringStiffness, lookVerticalSpringDamping);

                idealSpherical.elevation = Mathf.Clamp(cameraPitch + lookVerticalActual * Mathf.PI, -Mathf.PI * 0.45f, Mathf.PI * 0.45f);
            }
            Quaternion q = Quaternion.FromToRotation(transform.TransformDirection(Vector3.up), target.position);
            transform.rotation = q * transform.rotation;
        }
        else
        {
            if (cameraType == ChaseCameraType.LooseAllowMovementUnderCamera)
            {
                Vector3 displacement = transform.position - target.position;
                if (displacement.sqrMagnitude < distance * distance)
                {
                    return(lastCameraTargetPosition);
                }
            }
            idealSpherical.polar = Mathf.Atan2(transform.position.z - target.position.z,
                                               transform.position.x - target.position.x);
        }
        Vector3 direction = idealSpherical.ToCartesian();

        lastCameraTargetPosition = target.position + direction;
        if (virtualCameraCollisionTest)
        {
            raycastCounter++;
            if (raycastCounter > 2)
            {
                raycastCounter = 0;
            }
            raycastResult[raycastCounter] = Physics.Raycast(target.position + raycastOffset[raycastCounter], direction, distance);

            RaycastHit[] hitInfo = Physics.SphereCastAll(target.position, virtualCameraCollisionRadius, direction, distance);

            float newCameraDistance = distance;
            bool  partialOcclusion  = !raycastResult[0] || !raycastResult[1] || !raycastResult[2];
            // allow partially occluded object if hit distance is less than 25% of pref. distance
            if (hitInfo.Length > 0)
            {
                for (int i = 0; i < hitInfo.Length; i++)
                {
                    bool partiallyOcclusionDistance = hitInfo[i].distance < distance * 0.25f;
                    if (!partiallyOcclusionDistance || !partialOcclusion)
                    {
                        newCameraDistance = hitInfo[i].distance;
                        break;
                    }
                }
            }

            float currentDistance = idealSpherical.radius;
            if (newCameraDistance < currentDistance ||
                newCameraDistance - currentDistance <= Mathf.Epsilon)              // don't damp if target is reached
            {
                idealSpherical.radius = newCameraDistance;
                vccMoveBackVelocity   = 0;
            }
            else
            {
                idealSpherical.radius = Damping.SpringDamping(idealSpherical.radius, newCameraDistance, ref vccMoveBackVelocity, vccMoveBackSpringStiffness, vccMoveBackSpringDamping);
            }

            // if distance was updated, then recalculate position
            if (currentDistance != idealSpherical.radius)
            {
                direction = idealSpherical.ToCartesian();
                lastCameraTargetPosition = target.position + direction;
            }
        }
        return(lastCameraTargetPosition);
    }