예제 #1
0
        Vector3 ComputeGroupBounds(CinemachineTargetGroup group, ref CameraState curState)
        {
            Vector3 cameraPos = curState.RawPosition;
            Vector3 fwd       = curState.RawOrientation * Vector3.forward;

            // Get the bounding box from camera's direction in view space
            LastBoundsMatrix = Matrix4x4.TRS(cameraPos, curState.RawOrientation, Vector3.one);
            Bounds  b           = group.GetViewSpaceBoundingBox(LastBoundsMatrix);
            Vector3 groupCenter = LastBoundsMatrix.MultiplyPoint3x4(b.center);
            float   boundsDepth = b.extents.z;

            if (!curState.Lens.Orthographic)
            {
                // Parallax might change bounds - refine
                float d = (Quaternion.Inverse(curState.RawOrientation) * (groupCenter - cameraPos)).z;
                cameraPos = groupCenter - fwd * (Mathf.Max(d, boundsDepth) + boundsDepth);

                // Will adjust cameraPos
                b = GetScreenSpaceGroupBoundingBox(group, ref cameraPos, curState.RawOrientation);
                LastBoundsMatrix = Matrix4x4.TRS(cameraPos, curState.RawOrientation, Vector3.one);
                groupCenter      = LastBoundsMatrix.MultiplyPoint3x4(b.center);
            }
            LastBounds = b;
            return(groupCenter - fwd * boundsDepth);
        }
        public override void MutateCameraState(ref CameraState curState, float deltaTime)
        {
            CinemachineTargetGroup targetGroup = this.TargetGroup;

            if (targetGroup == null)
            {
                base.MutateCameraState(ref curState, deltaTime);
                return;
            }
            if (!this.IsValid || !curState.HasLookAt)
            {
                this.m_prevTargetHeight = 0f;
                return;
            }
            curState.ReferenceLookAt = this.GetLookAtPointAndSetTrackedPoint(targetGroup.transform.position);
            Vector3 v         = base.TrackedPoint - curState.RawPosition;
            float   magnitude = v.magnitude;

            if (magnitude < 0.0001f)
            {
                return;
            }
            Vector3 vector      = v.AlmostZero() ? Vector3.forward : v.normalized;
            Bounds  boundingBox = targetGroup.BoundingBox;

            this.m_lastBoundsMatrix = Matrix4x4.TRS(boundingBox.center - vector * boundingBox.extents.magnitude, Quaternion.LookRotation(vector, curState.ReferenceUp), Vector3.one);
            this.m_LastBounds       = targetGroup.GetViewSpaceBoundingBox(this.m_lastBoundsMatrix);
            float   num = this.GetTargetHeight(this.m_LastBounds);
            Vector3 a   = this.m_lastBoundsMatrix.MultiplyPoint3x4(this.m_LastBounds.center);

            if (deltaTime >= 0f)
            {
                float num2 = num - this.m_prevTargetHeight;
                num2 = Damper.Damp(num2, this.m_FrameDamping, deltaTime);
                num  = this.m_prevTargetHeight + num2;
            }
            this.m_prevTargetHeight = num;
            if (!curState.Lens.Orthographic && this.m_AdjustmentMode != CinemachineGroupComposer.AdjustmentMode.ZoomOnly)
            {
                float fieldOfView = curState.Lens.FieldOfView;
                float num3        = num / (2f * Mathf.Tan(fieldOfView * 0.0174532924f / 2f)) + this.m_LastBounds.extents.z;
                num3 = Mathf.Clamp(num3, magnitude - this.m_MaxDollyIn, magnitude + this.m_MaxDollyOut);
                num3 = Mathf.Clamp(num3, this.m_MinimumDistance, this.m_MaximumDistance);
                curState.PositionCorrection += a - vector * num3 - curState.RawPosition;
            }
            if (curState.Lens.Orthographic || this.m_AdjustmentMode != CinemachineGroupComposer.AdjustmentMode.DollyOnly)
            {
                float num4  = (base.TrackedPoint - curState.CorrectedPosition).magnitude - this.m_LastBounds.extents.z;
                float value = 179f;
                if (num4 > 0.0001f)
                {
                    value = 2f * Mathf.Atan(num / (2f * num4)) * 57.29578f;
                }
                LensSettings lens = curState.Lens;
                lens.FieldOfView      = Mathf.Clamp(value, this.m_MinimumFOV, this.m_MaximumFOV);
                lens.OrthographicSize = Mathf.Clamp(num / 2f, this.m_MinimumOrthoSize, this.m_MaximumOrthoSize);
                curState.Lens         = lens;
            }
            base.MutateCameraState(ref curState, deltaTime);
        }
예제 #3
0
        static Bounds GetScreenSpaceGroupBoundingBox(
            CinemachineTargetGroup group, ref Vector3 pos, Quaternion orientation)
        {
            Matrix4x4 observer = Matrix4x4.TRS(pos, orientation, Vector3.one);
            Vector2   minAngles, maxAngles, zRange;

            group.GetViewSpaceAngularBounds(observer, out minAngles, out maxAngles, out zRange);

            Quaternion q                 = Quaternion.identity.ApplyCameraRotation((minAngles + maxAngles) / 2, Vector3.up);
            Vector3    localPosAdustment = q * new Vector3(0, 0, (zRange.y + zRange.x) / 2);

            localPosAdustment.z = 0;
            pos      = observer.MultiplyPoint3x4(localPosAdustment);
            observer = Matrix4x4.TRS(pos, orientation, Vector3.one);
            group.GetViewSpaceAngularBounds(observer, out minAngles, out maxAngles, out zRange);

            float   zSize  = zRange.y - zRange.x;
            float   z      = zRange.x + (zSize / 2);
            Vector2 angles = new Vector2(89.5f, 89.5f);

            if (zRange.x > 0)
            {
                angles = Vector3.Max(maxAngles, UnityVectorExtensions.Abs(minAngles)) * Mathf.Deg2Rad;
                angles = Vector2.Min(angles, new Vector2(89.5f, 89.5f));
            }
            return(new Bounds(new Vector3(0, 0, z),
                              new Vector3(Mathf.Tan(angles.y) * z * 2, Mathf.Tan(angles.x) * z * 2, zSize)));
        }
예제 #4
0
 public void RemoveMe()
 {
     if (test)
     {
         test.RemoveMember(gameObject.transform);
         test = null;
     }
 }
        float AdjustCameraDepthAndLensForGroupFraming(
            CinemachineTargetGroup group, float targetZ, 
            ref CameraState curState, float deltaTime)
        {
            float cameraOffset = 0;

            // Get the bounding box from that POV in view space, and find its height
            Bounds bounds = group.BoundingBox;
            Vector3 fwd = curState.RawOrientation * Vector3.forward;
            m_lastBoundsMatrix = Matrix4x4.TRS(
                    bounds.center - (fwd * bounds.extents.magnitude),
                    curState.RawOrientation, Vector3.one);
            m_LastBounds = group.GetViewSpaceBoundingBox(m_lastBoundsMatrix);
            float targetHeight = GetTargetHeight(m_LastBounds);

            // Apply damping
            if (deltaTime >= 0)
            {
                float delta = targetHeight - m_prevTargetHeight;
                delta = Damper.Damp(delta, m_ZDamping, deltaTime);
                targetHeight = m_prevTargetHeight + delta;
            }
            m_prevTargetHeight = targetHeight;

            // Move the camera
            if (!curState.Lens.Orthographic && m_AdjustmentMode != AdjustmentMode.ZoomOnly)
            {
                // What distance would be needed to get the target height, at the current FOV
                float desiredDistance 
                    = targetHeight / (2f * Mathf.Tan(curState.Lens.FieldOfView * Mathf.Deg2Rad / 2f));

                // target the near surface of the bounding box
                desiredDistance += m_LastBounds.extents.z;

                // Clamp to respect min/max distance settings
                desiredDistance = Mathf.Clamp(
                        desiredDistance, targetZ - m_MaxDollyIn, targetZ + m_MaxDollyOut);
                desiredDistance = Mathf.Clamp(desiredDistance, m_MinimumDistance, m_MaximumDistance);

                // Apply
                cameraOffset += desiredDistance - targetZ;
            }

            // Apply zoom
            if (curState.Lens.Orthographic || m_AdjustmentMode != AdjustmentMode.DollyOnly)
            {
                float nearBoundsDistance = (targetZ + cameraOffset) - m_LastBounds.extents.z;
                float currentFOV = 179;
                if (nearBoundsDistance > Epsilon)
                    currentFOV = 2f * Mathf.Atan(targetHeight / (2 * nearBoundsDistance)) * Mathf.Rad2Deg;

                LensSettings lens = curState.Lens;
                lens.FieldOfView = Mathf.Clamp(currentFOV, m_MinimumFOV, m_MaximumFOV);
                lens.OrthographicSize = Mathf.Clamp(targetHeight / 2, m_MinimumOrthoSize, m_MaximumOrthoSize);
                curState.Lens = lens;
            }
            return -cameraOffset;
        }
예제 #6
0
 void UpdateFollowTargetCache()
 {
     mCachedFollowTargetVcam  = null;
     mCachedFollowTargetGroup = null;
     mCachedFollowTarget      = FollowTarget;
     if (mCachedFollowTarget != null)
     {
         mCachedFollowTargetVcam  = mCachedFollowTarget.GetComponent <CinemachineVirtualCameraBase>();
         mCachedFollowTargetGroup = mCachedFollowTarget.GetComponent <CinemachineTargetGroup>();
     }
 }
예제 #7
0
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Setting TARGET GROUP");
        group  = GetComponent <Cinemachine.CinemachineTargetGroup>();
        player = FindObjectOfType <Player>().transform;
        push   = player.GetChild(14);
        group.m_Targets[1].target = push;
        group.m_Targets[1].weight = 1.0f;
        group.m_Targets[0].target = player;
        group.m_Targets[0].weight = 1.0f;
        int count = 0;

        foreach (Cinemachine.CinemachineTargetGroup.Target g in group.m_Targets)
        {
            Debug.Log(++count + " " + g.target);
        }
    }
예제 #8
0
    void Start()
    {
        targetGroup = GetComponent <Cinemachine.CinemachineTargetGroup>();
        int numPieces = piecesGroup.transform.childCount;
        int radius    = 2;

        for (int i = 0; i < numPieces; i++)
        {
            if (i == numPieces - 1)
            {
                radius = 10;
            }
            targetGroup.AddMember(piecesGroup.transform.GetChild(i), 1, radius);
        }

        StartCoroutine(RemoveStartTargetMembers(waitTime));
    }
예제 #9
0
        /// <param name="observer">Point of view</param>
        /// <param name="newFwd">New forward direction to use when interpreting the return value</param>
        /// <returns>Bounding box in a slightly rotated version of observer, as specified by newFwd</returns>
        static Bounds GetScreenSpaceGroupBoundingBox(
            CinemachineTargetGroup group, Matrix4x4 observer, out Vector3 newFwd)
        {
            Vector2 minAngles, maxAngles, zRange;

            group.GetViewSpaceAngularBounds(observer, out minAngles, out maxAngles, out zRange);
            Vector2 shift = (minAngles + maxAngles) / 2;

            newFwd = Quaternion.identity.ApplyCameraRotation(shift, Vector3.up) * Vector3.forward;
            newFwd = observer.MultiplyVector(newFwd);

            float   d      = (zRange.y + zRange.x);
            Vector2 angles = (maxAngles - shift) * Mathf.Deg2Rad;

            angles = Vector2.Min(angles, new Vector2(89.5f, 89.5f));
            return(new Bounds(
                       new Vector3(0, 0, d / 2),
                       new Vector3(Mathf.Tan(angles.y) * d, Mathf.Tan(angles.x) * d, zRange.y - zRange.x)));
        }
예제 #10
0
    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
            Physics2D.IgnoreLayerCollision(8, 8);
            Physics2D.IgnoreLayerCollision(8, 9);

            meteorManager = FindObjectOfType <MeteorManager>();
            targetGroup   = FindObjectOfType <Cinemachine.CinemachineTargetGroup>();

            foreach (Human human in humans)
            {
                human.onDeath.AddListener(new UnityAction(() => {
                    targetGroup.RemoveMember(human.transform);
                }));

                targetGroup.AddMember(human.transform, 1, 2);
            }
        }
    }
예제 #11
0
        private float AdjustCameraDepthAndLensForGroupFraming(CinemachineTargetGroup group, float targetZ, ref CameraState curState, float deltaTime)
        {
            float   num         = 0f;
            Bounds  boundingBox = group.BoundingBox;
            Vector3 a           = curState.RawOrientation * Vector3.forward;

            this.m_lastBoundsMatrix = Matrix4x4.TRS(boundingBox.center - a * boundingBox.extents.magnitude, curState.RawOrientation, Vector3.one);
            this.m_LastBounds       = group.GetViewSpaceBoundingBox(this.m_lastBoundsMatrix);
            float num2 = this.GetTargetHeight(this.m_LastBounds);

            if (deltaTime >= 0f)
            {
                float num3 = num2 - this.m_prevTargetHeight;
                num3 = Damper.Damp(num3, this.m_ZDamping, deltaTime);
                num2 = this.m_prevTargetHeight + num3;
            }
            this.m_prevTargetHeight = num2;
            if (!curState.Lens.Orthographic && this.m_AdjustmentMode != CinemachineFramingTransposer.AdjustmentMode.ZoomOnly)
            {
                float num4 = num2 / (2f * Mathf.Tan(curState.Lens.FieldOfView * 0.0174532924f / 2f));
                num4 += this.m_LastBounds.extents.z;
                num4  = Mathf.Clamp(num4, targetZ - this.m_MaxDollyIn, targetZ + this.m_MaxDollyOut);
                num4  = Mathf.Clamp(num4, this.m_MinimumDistance, this.m_MaximumDistance);
                num  += num4 - targetZ;
            }
            if (curState.Lens.Orthographic || this.m_AdjustmentMode != CinemachineFramingTransposer.AdjustmentMode.DollyOnly)
            {
                float num5  = targetZ + num - this.m_LastBounds.extents.z;
                float value = 179f;
                if (num5 > 0.0001f)
                {
                    value = 2f * Mathf.Atan(num2 / (2f * num5)) * 57.29578f;
                }
                LensSettings lens = curState.Lens;
                lens.FieldOfView      = Mathf.Clamp(value, this.m_MinimumFOV, this.m_MaximumFOV);
                lens.OrthographicSize = Mathf.Clamp(num2 / 2f, this.m_MinimumOrthoSize, this.m_MaximumOrthoSize);
                curState.Lens         = lens;
            }
            return(-num);
        }
예제 #12
0
        public override void MutateCameraState(ref CameraState curState, float deltaTime)
        {
            if (deltaTime < 0f)
            {
                this.m_Predictor.Reset();
                this.m_PreviousCameraPosition = curState.RawPosition + curState.RawOrientation * Vector3.back * this.m_CameraDistance;
            }
            if (!this.IsValid)
            {
                return;
            }
            Vector3 previousCameraPosition = this.m_PreviousCameraPosition;

            curState.ReferenceLookAt   = base.FollowTarget.position;
            this.m_Predictor.Smoothing = this.m_LookaheadSmoothing;
            this.m_Predictor.AddPosition(curState.ReferenceLookAt);
            this.TrackedPoint = ((this.m_LookaheadTime > 0f) ? this.m_Predictor.PredictPosition(this.m_LookaheadTime) : curState.ReferenceLookAt);
            Quaternion rawOrientation = curState.RawOrientation;
            Quaternion rotation       = Quaternion.Inverse(rawOrientation);
            Vector3    vector         = rotation * previousCameraPosition;
            Vector3    vector2        = rotation * this.TrackedPoint - vector;
            Vector3    vector3        = Vector3.zero;
            float      num            = Mathf.Max(0.01f, this.m_CameraDistance - this.m_DeadZoneDepth / 2f);
            float      num2           = Mathf.Max(num, this.m_CameraDistance + this.m_DeadZoneDepth / 2f);

            if (vector2.z < num)
            {
                vector3.z = vector2.z - num;
            }
            if (vector2.z > num2)
            {
                vector3.z = vector2.z - num2;
            }
            CinemachineTargetGroup targetGroup = this.TargetGroup;

            if (targetGroup != null && this.m_GroupFramingMode != CinemachineFramingTransposer.FramingMode.None)
            {
                vector3.z += this.AdjustCameraDepthAndLensForGroupFraming(targetGroup, vector2.z - vector3.z, ref curState, deltaTime);
            }
            vector2.z -= vector3.z;
            float orthoSize  = curState.Lens.Orthographic ? curState.Lens.OrthographicSize : (Mathf.Tan(0.5f * curState.Lens.FieldOfView * 0.0174532924f) * vector2.z);
            Rect  screenRect = this.ScreenToOrtho(this.SoftGuideRect, orthoSize, curState.Lens.Aspect);

            if (deltaTime < 0f)
            {
                Rect screenRect2 = new Rect(screenRect.center, Vector2.zero);
                vector3 += this.OrthoOffsetToScreenBounds(vector2, screenRect2);
            }
            else
            {
                vector3 += this.OrthoOffsetToScreenBounds(vector2, screenRect);
                Vector3 vector4 = Vector3.zero;
                if (!this.m_UnlimitedSoftZone)
                {
                    Rect screenRect3 = this.ScreenToOrtho(this.HardGuideRect, orthoSize, curState.Lens.Aspect);
                    vector4 = this.OrthoOffsetToScreenBounds(vector2, screenRect3);
                    float d = Mathf.Max(vector4.x / (vector3.x + 0.0001f), vector4.y / (vector3.y + 0.0001f));
                    vector4 = vector3 * d;
                }
                vector3 = vector4 + Damper.Damp(vector3 - vector4, new Vector3(this.m_XDamping, this.m_YDamping, this.m_ZDamping), deltaTime);
            }
            curState.RawPosition = (this.m_PreviousCameraPosition = rawOrientation * (vector + vector3));
        }
예제 #13
0
 private void Awake()
 {
     targetGroup = GetComponent <Cinemachine.CinemachineTargetGroup>();
 }
예제 #14
0
        /// <summary>Positions the virtual camera according to the transposer rules.</summary>
        /// <param name="curState">The current camera state</param>
        /// <param name="deltaTime">Used for damping.  If less than 0, no damping is done.</param>
        public override void MutateCameraState(ref CameraState curState, float deltaTime)
        {
            Vector3 followTargetPosition = FollowTargetPosition;

            if (deltaTime < 0)
            {
                m_Predictor.Reset();
                m_PreviousCameraPosition = FollowTargetPosition
                                           + (curState.RawOrientation * Vector3.back) * m_CameraDistance;
                m_prevFOV = 0;
            }
            if (!IsValid)
            {
                return;
            }

            // Compute group bounds and adjust follow target for group framing
            CinemachineTargetGroup group = FollowTargetGroup;
            bool isGroupFraming          = group != null && m_GroupFramingMode != FramingMode.None;

            if (isGroupFraming)
            {
                followTargetPosition = ComputeGroupBounds(group, ref curState);
            }

            if (m_LookaheadTime > Epsilon)
            {
                m_Predictor.IgnoreY   = m_LookaheadIgnoreY;
                m_Predictor.Smoothing = m_LookaheadSmoothing;
                m_Predictor.AddPosition(followTargetPosition);
                var p = m_Predictor.PredictPosition(m_LookaheadTime);
                if (isGroupFraming)
                {
                    var b = LastBounds;
                    b.center  += p - followTargetPosition;
                    LastBounds = b;
                }
                followTargetPosition = p;
            }

            TrackedPoint = followTargetPosition;
            if (!curState.HasLookAt)
            {
                curState.ReferenceLookAt = followTargetPosition;
            }

            // Adjust the desired depth for group framing
            float targetDistance = m_CameraDistance;
            bool  isOrthographic = curState.Lens.Orthographic;
            float targetHeight   = isGroupFraming ? GetTargetHeight(LastBounds.size / m_GroupFramingSize) : 0;

            if (!isOrthographic && isGroupFraming)
            {
                // Adjust height for perspective - we want the height at the near surface
                float boundsDepth = LastBounds.extents.z;
                float z           = LastBounds.center.z;
                if (z > boundsDepth)
                {
                    targetHeight = Mathf.Lerp(0, targetHeight, (z - boundsDepth) / z);
                }

                if (m_AdjustmentMode != AdjustmentMode.ZoomOnly)
                {
                    // What distance from near edge would be needed to get the adjusted
                    // target height, at the current FOV
                    targetDistance = targetHeight / (2f * Mathf.Tan(curState.Lens.FieldOfView * Mathf.Deg2Rad / 2f));

                    // Clamp to respect min/max distance settings to the near surface of the bounds
                    targetDistance = Mathf.Clamp(targetDistance, m_MinimumDistance, m_MaximumDistance);

                    // Clamp to respect min/max camera movement
                    float targetDelta = targetDistance - m_CameraDistance;
                    targetDelta    = Mathf.Clamp(targetDelta, -m_MaxDollyIn, m_MaxDollyOut);
                    targetDistance = m_CameraDistance + targetDelta;
                }
            }

            // Work in camera-local space
            Vector3    camPosWorld  = m_PreviousCameraPosition;
            Quaternion localToWorld = curState.RawOrientation;
            Quaternion worldToLocal = Quaternion.Inverse(localToWorld);
            Vector3    cameraPos    = worldToLocal * camPosWorld;
            Vector3    targetPos    = (worldToLocal * TrackedPoint) - cameraPos;

            // Move along camera z
            Vector3 cameraOffset = Vector3.zero;
            float   cameraMin    = Mathf.Max(kMinimumCameraDistance, targetDistance - m_DeadZoneDepth / 2);
            float   cameraMax    = Mathf.Max(cameraMin, targetDistance + m_DeadZoneDepth / 2);

            if (targetPos.z < cameraMin)
            {
                cameraOffset.z = targetPos.z - cameraMin;
            }
            if (targetPos.z > cameraMax)
            {
                cameraOffset.z = targetPos.z - cameraMax;
            }

            // Move along the XY plane
            float screenSize = curState.Lens.Orthographic
                ? curState.Lens.OrthographicSize
                : Mathf.Tan(0.5f * curState.Lens.FieldOfView * Mathf.Deg2Rad)
                               * (targetPos.z - cameraOffset.z);
            Rect softGuideOrtho = ScreenToOrtho(SoftGuideRect, screenSize, curState.Lens.Aspect);

            if (deltaTime < 0)
            {
                // No damping or hard bounds, just snap to central bounds, skipping the soft zone
                Rect rect = softGuideOrtho;
                if (m_CenterOnActivate)
                {
                    rect = new Rect(rect.center, Vector2.zero); // Force to center
                }
                cameraOffset += OrthoOffsetToScreenBounds(targetPos, rect);
            }
            else
            {
                // Move it through the soft zone
                cameraOffset += OrthoOffsetToScreenBounds(targetPos, softGuideOrtho);

                // Find where it intersects the hard zone
                Vector3 hard = Vector3.zero;
                if (!m_UnlimitedSoftZone)
                {
                    Rect hardGuideOrtho = ScreenToOrtho(HardGuideRect, screenSize, curState.Lens.Aspect);
                    hard = OrthoOffsetToScreenBounds(targetPos, hardGuideOrtho);
                    float t = Mathf.Max(hard.x / (cameraOffset.x + Epsilon), hard.y / (cameraOffset.y + Epsilon));
                    hard = cameraOffset * t;
                }
                // Apply damping, but only to the portion of the move that's inside the hard zone
                cameraOffset = hard + Damper.Damp(
                    cameraOffset - hard, new Vector3(m_XDamping, m_YDamping, m_ZDamping), deltaTime);
            }
            curState.RawPosition = m_PreviousCameraPosition = localToWorld * (cameraPos + cameraOffset);

            // Adjust lens for group framing
            if (isGroupFraming)
            {
                if (isOrthographic)
                {
                    targetHeight = Mathf.Clamp(targetHeight, m_MinimumOrthoSize, m_MaximumOrthoSize);

                    // ApplyDamping
                    if (deltaTime >= 0)
                    {
                        targetHeight = m_prevFOV + Damper.Damp(targetHeight - m_prevFOV, m_ZDamping, deltaTime);
                    }
                    m_prevFOV = targetHeight;

                    LensSettings lens = curState.Lens;
                    lens.OrthographicSize = Mathf.Clamp(targetHeight / 2, m_MinimumOrthoSize, m_MaximumOrthoSize);
                    curState.Lens         = lens;
                }
                else if (m_AdjustmentMode != AdjustmentMode.DollyOnly)
                {
                    var localTarget = Quaternion.Inverse(curState.RawOrientation)
                                      * (followTargetPosition - curState.RawPosition);
                    float nearBoundsDistance = localTarget.z;
                    float targetFOV          = 179;
                    if (nearBoundsDistance > Epsilon)
                    {
                        targetFOV = 2f * Mathf.Atan(targetHeight / (2 * nearBoundsDistance)) * Mathf.Rad2Deg;
                    }
                    targetFOV = Mathf.Clamp(targetFOV, m_MinimumFOV, m_MaximumFOV);

                    // ApplyDamping
                    if (deltaTime >= 0 && m_prevFOV != 0)
                    {
                        targetFOV = m_prevFOV + Damper.Damp(targetFOV - m_prevFOV, m_ZDamping, deltaTime);
                    }
                    m_prevFOV = targetFOV;

                    LensSettings lens = curState.Lens;
                    lens.FieldOfView = targetFOV;
                    curState.Lens    = lens;
                }
            }
        }
예제 #15
0
        /// <summary>Applies the composer rules and orients the camera accordingly</summary>
        /// <param name="curState">The current camera state</param>
        /// <param name="deltaTime">Used for calculating damping.  If less than
        /// zero, then target will snap to the center of the dead zone.</param>
        public override void MutateCameraState(ref CameraState curState, float deltaTime)
        {
            // Can't do anything without a group to look at
            CinemachineTargetGroup group = LookAtTargetGroup;

            if (group == null)
            {
                base.MutateCameraState(ref curState, deltaTime);
                return;
            }

            if (!IsValid || !curState.HasLookAt)
            {
                m_prevTargetHeight = 0;
                m_prevCameraOffset = Vector3.zero;
                return;
            }

            bool canMoveCamera
                = !curState.Lens.Orthographic && m_AdjustmentMode != AdjustmentMode.ZoomOnly;

            // Get the bounding box from camera's POV in view space
            Vector3        observerPosition = curState.RawPosition;
            BoundingSphere s               = group.Sphere;
            Vector3        groupCenter     = s.position;
            Vector3        currentOffset   = groupCenter - observerPosition;
            float          currentDistance = currentOffset.magnitude;

            if (currentDistance < Epsilon)
            {
                return;  // navel-gazing, get outa here
            }
            Vector3 fwd = currentOffset / currentDistance;

            LastBoundsMatrix = Matrix4x4.TRS(observerPosition,
                                             Quaternion.LookRotation(fwd, curState.ReferenceUp), Vector3.one);
            Bounds b;

            if (curState.Lens.Orthographic)
            {
                b = group.GetViewSpaceBoundingBox(LastBoundsMatrix);
                Vector3 sizeDelta = new Vector3(b.center.x, b.center.y, 0);
                b.size    += sizeDelta.Abs() * 2;
                b.center   = new Vector3(0, 0, b.center.z);
                LastBounds = b;
            }
            else
            {
                if (canMoveCamera)
                {
                    // Get an upper bound on the distance
                    b           = group.GetViewSpaceBoundingBox(LastBoundsMatrix);
                    groupCenter = LastBoundsMatrix.MultiplyPoint3x4(b.center);

                    // Now try to get closer
                    float distance = GetTargetHeight(b)
                                     / (2f * Mathf.Tan(curState.Lens.FieldOfView * Mathf.Deg2Rad / 2f));
                    Vector3 nearCenter = b.center; nearCenter.z -= b.extents.z;
                    nearCenter = LastBoundsMatrix.MultiplyPoint3x4(nearCenter);
                    Vector3 newFwd = (groupCenter - nearCenter).normalized;
                    if (!newFwd.AlmostZero())
                    {
                        fwd = newFwd;
                    }
                    observerPosition = nearCenter - (fwd * distance);
                    LastBoundsMatrix = Matrix4x4.TRS(observerPosition,
                                                     Quaternion.LookRotation(fwd, curState.ReferenceUp), Vector3.one);
                }

                b = GetScreenSpaceGroupBoundingBox(group, LastBoundsMatrix, out fwd);
                LastBoundsMatrix = Matrix4x4.TRS(observerPosition,
                                                 Quaternion.LookRotation(fwd, curState.ReferenceUp), Vector3.one);
                LastBounds      = b;
                groupCenter     = LastBoundsMatrix.MultiplyPoint3x4(b.center);
                currentOffset   = groupCenter - curState.RawPosition;
                currentDistance = currentOffset.magnitude;
            }

            // Adjust bounds for framing size
            Vector3 extents = b.extents / m_GroupFramingSize;

            extents.z = Mathf.Min(b.extents.z, extents.z);
            b.extents = extents;

            // Apply damping
            float targetHeight = GetTargetHeight(b);

            if (deltaTime >= 0)
            {
                float delta = targetHeight - m_prevTargetHeight;
                delta        = Damper.Damp(delta, m_FrameDamping, deltaTime);
                targetHeight = m_prevTargetHeight + delta;
            }
            m_prevTargetHeight = targetHeight;

            // Move the camera
            if (canMoveCamera)
            {
                // What distance would be needed to get the target height, at the current FOV
                float depth            = b.extents.z;
                float d                = (groupCenter - observerPosition).magnitude;
                float nearTargetHeight = targetHeight * (d - depth) / d;
                float targetDistance   = nearTargetHeight
                                         / (2f * Mathf.Tan(curState.Lens.FieldOfView * Mathf.Deg2Rad / 2f));

                // Clamp to respect min/max distance settings to the near surface of the bounds
                float cameraDistance = targetDistance;
                cameraDistance  = Mathf.Clamp(cameraDistance, currentDistance - m_MaxDollyIn, currentDistance + m_MaxDollyOut);
                cameraDistance -= depth;
                cameraDistance  = Mathf.Clamp(cameraDistance, m_MinimumDistance, m_MaximumDistance);
                cameraDistance += depth;

                // Apply
                Vector3 newCamOffset
                    = (groupCenter - (fwd * (cameraDistance + depth))) - curState.RawPosition;
                if (deltaTime >= 0)
                {
                    Vector3 delta = newCamOffset - m_prevCameraOffset;
                    delta        = Damper.Damp(delta, m_FrameDamping, deltaTime);
                    newCamOffset = m_prevCameraOffset + delta;
                }
                m_prevCameraOffset           = newCamOffset;
                curState.PositionCorrection += newCamOffset;
            }

            // Apply zoom
            if (curState.Lens.Orthographic || m_AdjustmentMode != AdjustmentMode.DollyOnly)
            {
                float nearBoundsDistance = (groupCenter - curState.CorrectedPosition).magnitude;
                float currentFOV         = 179;
                if (nearBoundsDistance > Epsilon)
                {
                    currentFOV = 2f * Mathf.Atan(targetHeight / (2 * nearBoundsDistance)) * Mathf.Rad2Deg;
                }

                LensSettings lens = curState.Lens;
                lens.FieldOfView      = Mathf.Clamp(currentFOV, m_MinimumFOV, m_MaximumFOV);
                lens.OrthographicSize = Mathf.Clamp(targetHeight / 2, m_MinimumOrthoSize, m_MaximumOrthoSize);
                curState.Lens         = lens;
            }

            // Now compose normally
            curState.ReferenceLookAt = GetLookAtPointAndSetTrackedPoint(groupCenter);
            base.MutateCameraState(ref curState, deltaTime);
        }
예제 #16
0
        /// <summary>Applies the composer rules and orients the camera accordingly</summary>
        /// <param name="curState">The current camera state</param>
        /// <param name="deltaTime">Used for calculating damping.  If less than
        /// zero, then target will snap to the center of the dead zone.</param>
        public override void MutateCameraState(ref CameraState curState, float deltaTime)
        {
            // Can't do anything without a group to look at
            CinemachineTargetGroup group = LookAtTargetGroup;

            if (group == null)
            {
                base.MutateCameraState(ref curState, deltaTime);
                return;
            }

            if (!IsValid || !curState.HasLookAt)
            {
                m_prevFramingDistance = 0;
                m_prevFOV             = 0;
                return;
            }

            bool isOrthographic = curState.Lens.Orthographic;
            bool canMoveCamera  = !isOrthographic && m_AdjustmentMode != AdjustmentMode.ZoomOnly;

            // Get the bounding box from camera's POV in view space
            Vector3        up          = curState.ReferenceUp;
            var            cameraPos   = curState.RawPosition;
            BoundingSphere s           = group.Sphere;
            Vector3        groupCenter = s.position;
            Vector3        fwd         = groupCenter - cameraPos;
            float          d           = fwd.magnitude;

            if (d < Epsilon)
            {
                return;  // navel-gazing, get outa here
            }
            // Approximate looking at the group center
            fwd /= d;
            LastBoundsMatrix = Matrix4x4.TRS(
                cameraPos, Quaternion.LookRotation(fwd, up), Vector3.one);

            // Correction for the actual center
            Bounds b;

            if (isOrthographic)
            {
                b                = group.GetViewSpaceBoundingBox(LastBoundsMatrix);
                groupCenter      = LastBoundsMatrix.MultiplyPoint3x4(b.center);
                fwd              = (groupCenter - cameraPos).normalized;
                LastBoundsMatrix = Matrix4x4.TRS(cameraPos, Quaternion.LookRotation(fwd, up), Vector3.one);
                b                = group.GetViewSpaceBoundingBox(LastBoundsMatrix);
                LastBounds       = b;
            }
            else
            {
                b = GetScreenSpaceGroupBoundingBox(group, LastBoundsMatrix, out fwd);
                LastBoundsMatrix = Matrix4x4.TRS(cameraPos, Quaternion.LookRotation(fwd, up), Vector3.one);
                LastBounds       = b;
                groupCenter      = cameraPos + fwd * b.center.z;
                fwd = (groupCenter - cameraPos).normalized;
            }

            // Adjust bounds for framing size, and get target height
            float boundsDepth  = b.extents.z;
            float targetHeight = GetTargetHeight(b.size / m_GroupFramingSize);

            if (isOrthographic)
            {
                targetHeight = Mathf.Clamp(targetHeight, m_MinimumOrthoSize, m_MaximumOrthoSize);

                // ApplyDamping
                if (deltaTime >= 0)
                {
                    targetHeight = m_prevFOV + Damper.Damp(targetHeight - m_prevFOV, m_FrameDamping, deltaTime);
                }
                m_prevFOV = targetHeight;

                LensSettings lens = curState.Lens;
                lens.OrthographicSize = Mathf.Clamp(targetHeight / 2, m_MinimumOrthoSize, m_MaximumOrthoSize);
                curState.Lens         = lens;
            }
            else
            {
                // Adjust height for perspective - we want the height at the near surface
                float z = b.center.z;
                if (z > boundsDepth)
                {
                    targetHeight = Mathf.Lerp(0, targetHeight, (z - boundsDepth) / z);
                }

                // Move the camera
                if (canMoveCamera)
                {
                    // What distance from near edge would be needed to get the adjusted
                    // target height, at the current FOV
                    float targetDistance = boundsDepth
                                           + targetHeight / (2f * Mathf.Tan(curState.Lens.FieldOfView * Mathf.Deg2Rad / 2f));

                    // Clamp to respect min/max distance settings to the near surface of the bounds
                    targetDistance = Mathf.Clamp(
                        targetDistance, boundsDepth + m_MinimumDistance, boundsDepth + m_MaximumDistance);

                    // Clamp to respect min/max camera movement
                    float targetDelta = targetDistance - Vector3.Distance(curState.RawPosition, groupCenter);
                    targetDelta = Mathf.Clamp(targetDelta, -m_MaxDollyIn, m_MaxDollyOut);

                    // ApplyDamping
                    if (deltaTime >= 0)
                    {
                        float delta = targetDelta - m_prevFramingDistance;
                        delta       = Damper.Damp(delta, m_FrameDamping, deltaTime);
                        targetDelta = m_prevFramingDistance + delta;
                    }
                    m_prevFramingDistance        = targetDelta;
                    curState.PositionCorrection -= fwd * targetDelta;
                    cameraPos -= fwd * targetDelta;
                }

                // Apply zoom
                if (m_AdjustmentMode != AdjustmentMode.DollyOnly)
                {
                    float nearBoundsDistance = (groupCenter - cameraPos).magnitude - boundsDepth;
                    float targetFOV          = 179;
                    if (nearBoundsDistance > Epsilon)
                    {
                        targetFOV = 2f * Mathf.Atan(targetHeight / (2 * nearBoundsDistance)) * Mathf.Rad2Deg;
                    }
                    targetFOV = Mathf.Clamp(targetFOV, m_MinimumFOV, m_MaximumFOV);

                    // ApplyDamping
                    if (deltaTime >= 0 && m_prevFOV != 0)
                    {
                        targetFOV = m_prevFOV + Damper.Damp(targetFOV - m_prevFOV, m_FrameDamping, deltaTime);
                    }
                    m_prevFOV = targetFOV;

                    LensSettings lens = curState.Lens;
                    lens.FieldOfView = targetFOV;
                    curState.Lens    = lens;
                }
            }
            // Now compose normally
            curState.ReferenceLookAt = GetLookAtPointAndSetTrackedPoint(groupCenter);
            base.MutateCameraState(ref curState, deltaTime);
        }
예제 #17
0
        /// <summary>Applies the composer rules and orients the camera accordingly</summary>
        /// <param name="state">The current camera state</param>
        /// <param name="deltaTime">Used for calculating damping.  If less than
        /// zero, then target will snap to the center of the dead zone.</param>
        public override void MutateCameraState(ref CameraState curState, float deltaTime)
        {
            // Can't do anything without a group to look at
            CinemachineTargetGroup group = TargetGroup;

            if (group == null)
            {
                base.MutateCameraState(ref curState, deltaTime);
                return;
            }

            if (!IsValid || !curState.HasLookAt)
            {
                m_prevTargetHeight = 0;
                return;
            }

            // The following line shouldn't be necessary.  You can try enabling it as a
            // last resort if you're getting inexplicable jitter.  That can sometimes come
            // about because the group's target members are not animated in a consistent way.
            //group.LateUpdate(); // Make sure the group's position is fully updated.

            curState.ReferenceLookAt = group.transform.position;
            Vector3 lookAtPosition  = GetTrackedPoint(curState.ReferenceLookAt);
            Vector3 currentOffset   = lookAtPosition - curState.RawPosition;
            float   currentDistance = currentOffset.magnitude;

            if (currentDistance < Epsilon)
            {
                return;  // navel-gazing, get outa here
            }
            //UnityEngine.Profiling.Profiler.BeginSample("CinemachineGroupComposer.MutateCameraState");

            // Get the camera axis
            Vector3 fwd = currentOffset.AlmostZero() ? Vector3.forward : currentOffset.normalized;

            // Get the bounding box from that POV in view space, and find its width
            Bounds bounds = group.BoundingBox;

            m_lastBoundsMatrix = Matrix4x4.TRS(
                bounds.center - (fwd * bounds.extents.magnitude),
                Quaternion.LookRotation(fwd, curState.ReferenceUp), Vector3.one);
            m_LastBounds = group.GetViewSpaceBoundingBox(m_lastBoundsMatrix);
            float   targetHeight = GetTargetHeight(m_LastBounds);
            Vector3 targetPos    = m_lastBoundsMatrix.MultiplyPoint3x4(m_LastBounds.center);

            // Apply damping
            if (deltaTime >= 0)
            {
                float delta = targetHeight - m_prevTargetHeight;
                delta        = Damper.Damp(delta, m_FrameDamping, deltaTime);
                targetHeight = m_prevTargetHeight + delta;
            }
            m_prevTargetHeight = targetHeight;

            // Move the camera
            if (!curState.Lens.Orthographic && m_AdjustmentMode != AdjustmentMode.ZoomOnly)
            {
                // What distance would be needed to get the target height, at the current FOV
                float currentFOV     = curState.Lens.FieldOfView;
                float targetDistance = targetHeight / (2f * Mathf.Tan(currentFOV * Mathf.Deg2Rad / 2f));

                // target the near surface of the bounding box
                float cameraDistance = targetDistance + m_LastBounds.extents.z;

                // Clamp to respect min/max distance settings
                cameraDistance = Mathf.Clamp(
                    cameraDistance, currentDistance - m_MaxDollyIn, currentDistance + m_MaxDollyOut);
                cameraDistance = Mathf.Clamp(cameraDistance, m_MinimumDistance, m_MaximumDistance);

                // Apply
                curState.PositionCorrection += targetPos - fwd * cameraDistance - curState.RawPosition;
            }

            // Apply zoom
            if (curState.Lens.Orthographic || m_AdjustmentMode != AdjustmentMode.DollyOnly)
            {
                float nearBoundsDistance = (lookAtPosition - curState.CorrectedPosition).magnitude
                                           - m_LastBounds.extents.z;
                float currentFOV = 179;
                if (nearBoundsDistance > Epsilon)
                {
                    currentFOV = 2f * Mathf.Atan(targetHeight / (2 * nearBoundsDistance)) * Mathf.Rad2Deg;
                }

                LensSettings lens = curState.Lens;
                lens.FieldOfView      = Mathf.Clamp(currentFOV, m_MinimumFOV, m_MaximumFOV);
                lens.OrthographicSize = Mathf.Clamp(targetHeight / 2, m_MinimumOrthoSize, m_MaximumOrthoSize);
                curState.Lens         = lens;
            }

            // Now compose normally
            base.MutateCameraState(ref curState, deltaTime);
            //UnityEngine.Profiling.Profiler.EndSample();
        }
예제 #18
0
 // Start is called before the first frame update
 void Start()
 {
     actuallyFollowing = GetComponent <Cinemachine.CinemachineTargetGroup>();
     actuallyFollowing.AddMember(GameObject.Find("Character").transform, 2, 4.5f);
 }
        /// <summary>Positions the virtual camera according to the transposer rules.</summary>
        /// <param name="curState">The current camera state</param>
        /// <param name="deltaTime">Used for damping.  If less than 0, no damping is done.</param>
        public override void MutateCameraState(ref CameraState curState, float deltaTime)
        {
            if (deltaTime < 0)
                m_PreviousCameraPosition = curState.RawPosition 
                    + (curState.RawOrientation * Vector3.back) * m_CameraDistance;
            if (!IsValid)
                return;

            //UnityEngine.Profiling.Profiler.BeginSample("CinemachineFramingTransposer.MutateCameraState");
            Vector3 camPosWorld = m_PreviousCameraPosition;
            curState.ReferenceLookAt = FollowTarget.position;

            // Work in camera-local space
            Quaternion localToWorld = curState.RawOrientation;
            Quaternion worldToLocal = Quaternion.Inverse(localToWorld);
            Vector3 cameraPos = worldToLocal * camPosWorld;
            Vector3 targetPos = (worldToLocal * curState.ReferenceLookAt) - cameraPos;

            // Move along camera z
            Vector3 cameraOffset = Vector3.zero;
            float cameraMin = Mathf.Max(kMinimumCameraDistance, m_CameraDistance - m_DeadZoneDepth/2);
            float cameraMax = Mathf.Max(cameraMin, m_CameraDistance + m_DeadZoneDepth/2);
            if (targetPos.z < cameraMin)
                cameraOffset.z = targetPos.z - cameraMin;
            if (targetPos.z > cameraMax)
                cameraOffset.z = targetPos.z - cameraMax;

            // Adjust for group framing
            CinemachineTargetGroup group = TargetGroup;
            if (group != null && m_GroupFramingMode != FramingMode.None)
                cameraOffset.z += AdjustCameraDepthAndLensForGroupFraming(
                    group, targetPos.z - cameraOffset.z, ref curState, deltaTime);

            // Move along the XY plane
            targetPos.z -= cameraOffset.z;
            float screenSize = curState.Lens.Orthographic 
                ? curState.Lens.OrthographicSize 
                : Mathf.Tan(0.5f * curState.Lens.FieldOfView * Mathf.Deg2Rad) * targetPos.z;
            Rect softGuideOrtho = ScreenToOrtho(SoftGuideRect, screenSize, curState.Lens.Aspect);
            if (deltaTime < 0)
            {
                // No damping or hard bounds, just snap to central bounds, skipping the soft zone
                Rect rect = new Rect(softGuideOrtho.center, Vector2.zero); // Force to center
                cameraOffset += OrthoOffsetToScreenBounds(targetPos, rect);
            }
            else
            {
                // Move it through the soft zone
                cameraOffset += OrthoOffsetToScreenBounds(targetPos, softGuideOrtho);

                // Find where it intersects the hard zone
                Vector3 hard = Vector3.zero;
                if (!m_UnlimitedSoftZone)
                {
                    Rect hardGuideOrtho = ScreenToOrtho(HardGuideRect, screenSize, curState.Lens.Aspect);
                    hard = OrthoOffsetToScreenBounds(targetPos, hardGuideOrtho);
                    float t = Mathf.Max(hard.x / (cameraOffset.x + Epsilon), hard.y / (cameraOffset.y + Epsilon));
                    hard = cameraOffset * t;
                }
                // Apply damping, but only to the portion of the move that's inside the hard zone
                cameraOffset = hard + Damper.Damp(
                    cameraOffset - hard, new Vector3(m_XDamping, m_YDamping, m_ZDamping), deltaTime);
            }
            curState.RawPosition = m_PreviousCameraPosition = localToWorld * (cameraPos + cameraOffset);
            //UnityEngine.Profiling.Profiler.EndSample();
        }
예제 #20
0
    /// <summary>
    /// Initialize the instance if not created
    /// </summary>
    private void Awake()
    {
        // Check if instance already exists
        if (instance == null)
        {
            // if not set it to this
            instance = this;
        }
        // If instance exists and is not this
        else if (instance != this)
        {
            // Destroy old GameManager
            Destroy(instance.gameObject);
            instance = this;
        }

        // Sets this to not be destroyed when reloading scene
        //DontDestroyOnLoad(gameObject);

        if (m_EnableLoadingScreen && m_BlackCanvas)
        {
            Color newColor = m_BlackCanvas.GetComponent <Image>().color;
            newColor.a = 1.0f;
            m_BlackCanvas.GetComponent <Image>().color = newColor;
        }

        m_HingeRopePlayers = GameObject.Find("HingeRope");

        // Initializes an empty game object that tracks the
        // camera Y angle for player movement direction
        cameraAngle = new GameObject("GetsCameraYAngle");
        cameraAngle.AddComponent <CameraAngle>();

        // Set up grandma and baby input controllers
        m_GrandmaObj = GameObject.Find("Grandma");
        m_BBcatObj   = GameObject.Find("BbCat");
        m_RopeObj    = GameObject.Find("Obi Rope");

        InputController  babyInput = m_BBcatObj.GetComponent <InputController>();
        InputController  gmaInput  = m_GrandmaObj.GetComponent <InputController>();
        PickupController gmaPickup = m_GrandmaObj.GetComponent <PickupController>();

        gmaInput.grandma       = babyInput.grandma = gmaInput;
        gmaInput.baby          = babyInput.baby = babyInput;
        gmaInput.gmaPickupCont = babyInput.gmaPickupCont = gmaPickup;

        // Get camera
        m_Camera = GameObject.Find("Main Camera");

        // Get camera holder
        m_CameraHolder = GameObject.Find("TargetGroupFollow");

        // Update camera tracking
        targetGroup = m_CameraHolder.GetComponent <Cinemachine.CinemachineTargetGroup>();

        targetGroup.m_Targets[0].target = m_GrandmaObj.transform;
        targetGroup.m_Targets[1].target = m_BBcatObj.transform;

        if (m_PuzzleCameras)
        {
            foreach (Transform child in m_PuzzleCameras.transform)
            {
                child.gameObject.GetComponent <PuzzleCameraCine>().Reset(m_GrandmaObj, m_BBcatObj);
            }
        }
        else
        {
            Debug.Log("NO PUZZLE CAMERAS");
        }

        // Update level start positions
        // TODO: find a better way to get all level start points, instead of get manually
        level1StartPoint  = GameObject.Find("Level1 start point");
        level2StartPoint  = GameObject.Find("Level2 start point");
        level3StartPoint  = GameObject.Find("Level3 start point");
        level4StartPoint  = GameObject.Find("Level4 start point");
        level5StartPoint  = GameObject.Find("Level5 start point");
        level6StartPoint  = GameObject.Find("Level6 start point");
        level7StartPoint  = GameObject.Find("Level7 start point");
        level8StartPoint  = GameObject.Find("Level8 start point");
        level9StartPoint  = GameObject.Find("Level9 start point");
        level10StartPoint = GameObject.Find("Level10 start point");
        level11StartPoint = GameObject.Find("Level11 start point");

        // Update pause menu
        m_PauseMenu = GameObject.Find("PauseMenu");

        Debug.Log("players set");

        if (m_PauseMenu)
        {
            m_PauseMenu.SetActive(false);
        }

        m_Player0 = ReInput.players.GetPlayer(0);
        m_Player1 = ReInput.players.GetPlayer(1);

        // Find UI element
        if (GameObject.Find("UIElementPlaceHolder"))
        {
            m_UIElementPlaceHolder = GameObject.Find("UIElementPlaceHolder");
        }
    }
예제 #21
0
 void Start()
 {
     m_group = GetComponent <CinemachineTargetGroup>();
 }
예제 #22
0
        Vector3 AdjustCameraPositionAndLensForGroupFraming(
            CinemachineTargetGroup group, float initialZ,
            ref CameraState curState, float deltaTime)
        {
            Vector3 cameraOffset = Vector3.zero;

            bool canMoveCameraInZ
                = !curState.Lens.Orthographic &&
                  m_AdjustmentMode != AdjustmentMode.ZoomOnly;

            // Work in camera-local space
            Vector3 fwd = curState.RawOrientation * Vector3.forward;
            Vector3 cameraWorldStartPos = TrackedPoint - (fwd * initialZ);

            LastBoundsMatrix = Matrix4x4.TRS(cameraWorldStartPos, curState.RawOrientation, Vector3.one);

            // Get the bounding box from camera's direction in view space
            Bounds b = group.GetViewSpaceBoundingBox(LastBoundsMatrix);

            LastBounds = b;

            // Recenter the camera in x-y, don't touch the depth
            cameraOffset   = b.center;
            cameraOffset.z = 0;

            float firstApproxCameraOffsetZ = 0;

            if (!curState.Lens.Orthographic)
            {
                // Now get a more refined bounding box in screen space
                if (canMoveCameraInZ)
                {
                    float newZ = GetPositionForNearBounds(
                        b, GetTargetHeight(b), curState.Lens.FieldOfView, false);
                    firstApproxCameraOffsetZ = Mathf.Clamp(newZ, -m_MaxDollyOut, m_MaxDollyIn);
                    cameraOffset.z           = firstApproxCameraOffsetZ;
                }
                Vector3 worldObserverPos = LastBoundsMatrix.MultiplyPoint3x4(cameraOffset);
                Vector3 localPosAdustmentXY;
                b = GetScreenSpaceGroupBoundingBox(
                    group, ref worldObserverPos, curState.RawOrientation, out localPosAdustmentXY);
                cameraOffset += localPosAdustmentXY;
                // worldObserverPos has been adjusted
                LastBoundsMatrix = Matrix4x4.TRS(worldObserverPos, curState.RawOrientation, Vector3.one);
                LastBounds       = b;
            }
            // Bring it back to local space
            b.center      += cameraOffset;
            cameraOffset.z = 0;

            // Adjust bounds for framing size
            Vector3 extents = b.extents / m_GroupFramingSize;

            extents.z = Mathf.Min(b.extents.z, extents.z);
            b.extents = extents;

            // Apply damping
            float targetHeight = GetTargetHeight(b);

            if (deltaTime >= 0)
            {
                float delta = targetHeight - m_prevTargetHeight;
                delta        = Damper.Damp(delta, m_ZDamping, deltaTime);
                targetHeight = m_prevTargetHeight + delta;
            }
            m_prevTargetHeight = targetHeight;

            // Move the camera in Z
            if (canMoveCameraInZ)
            {
                float newZ = GetPositionForNearBounds(
                    new Bounds(b.center - new Vector3(0, 0, firstApproxCameraOffsetZ), b.size),
                    targetHeight, curState.Lens.FieldOfView, true);
                newZ          += firstApproxCameraOffsetZ;
                cameraOffset.z = Mathf.Clamp(newZ, -m_MaxDollyOut, m_MaxDollyIn);
            }

            // Apply zoom
            if (curState.Lens.Orthographic || m_AdjustmentMode != AdjustmentMode.DollyOnly)
            {
                float targetDistance = b.center.z - cameraOffset.z;
                float currentFOV     = 179;
                if (targetDistance > Epsilon)
                {
                    currentFOV = 2f * Mathf.Atan(targetHeight / (2 * targetDistance)) * Mathf.Rad2Deg;
                }

                LensSettings lens = curState.Lens;
                lens.FieldOfView      = Mathf.Clamp(currentFOV, m_MinimumFOV, m_MaximumFOV);
                lens.OrthographicSize = Mathf.Clamp(targetHeight / 2, m_MinimumOrthoSize, m_MaximumOrthoSize);
                curState.Lens         = lens;
            }

            return(cameraOffset);
        }
예제 #23
0
        /// <summary>Positions the virtual camera according to the transposer rules.</summary>
        /// <param name="curState">The current camera state</param>
        /// <param name="deltaTime">Used for damping.  If 0 or less, no damping is done.</param>
        public virtual void MutateCameraState(ref CameraState curState, float deltaTime)
        {
            if (deltaTime <= 0)
            {
                m_PreviousCameraPosition = curState.RawPosition
                                           + (curState.RawOrientation * Vector3.back) * m_CameraDistance;
            }
            if (!IsValid)
            {
                return;
            }

            //UnityEngine.Profiling.Profiler.BeginSample("CinemachineFramingTransposer.MutateCameraState");
            Vector3 camPosWorld = m_PreviousCameraPosition;

            curState.ReferenceLookAt = VirtualCamera.Follow.position;

            // Work in camera-local space
            Quaternion localToWorld = curState.RawOrientation;
            Quaternion worldToLocal = Quaternion.Inverse(localToWorld);
            Vector3    cameraPos    = worldToLocal * camPosWorld;
            Vector3    targetPos    = (worldToLocal * curState.ReferenceLookAt) - cameraPos;

            // Move along camera z
            Vector3 cameraOffset = Vector3.zero;
            float   cameraMin    = Mathf.Max(kMinimumCameraDistance, m_CameraDistance - m_DistanceDeadZoneSize / 2);
            float   cameraMax    = Mathf.Max(cameraMin, m_CameraDistance + m_DistanceDeadZoneSize / 2);

            if (targetPos.z < cameraMin)
            {
                cameraOffset.z = targetPos.z - cameraMin;
            }
            if (targetPos.z > cameraMax)
            {
                cameraOffset.z = targetPos.z - cameraMax;
            }
            if (deltaTime > 0 && Mathf.Abs(cameraOffset.z) > UnityVectorExtensions.Epsilon)
            {
                cameraOffset.z *= deltaTime / Mathf.Max(m_ZDamping * kDampingScale, deltaTime);
            }

            // Adjust for group framing
            CinemachineTargetGroup group = TargetGroup;

            if (group != null)
            {
                cameraOffset.z += AdjustCameraDepthAndLensForGroupFraming(
                    group, targetPos.z - cameraOffset.z, ref curState, deltaTime);
            }

            targetPos.z -= cameraOffset.z;

            // Move along the XY plane
            float screenSize = curState.Lens.Orthographic
                ? curState.Lens.OrthographicSize
                : Mathf.Tan(0.5f * curState.Lens.FieldOfView * Mathf.Deg2Rad) * targetPos.z;
            Rect softGuideOrtho = ScreenToOrtho(SoftGuideRect, screenSize, curState.Lens.Aspect);

            if (deltaTime <= 0)
            {
                // No damping, just snap to central bounds, skipping the soft zone
                Rect rect = new Rect(softGuideOrtho.center, Vector2.zero); // Force to center
                cameraOffset += OrthoOffsetToScreenBounds(targetPos, rect, 0);
            }
            else
            {
                // First force the previous position into the hard bounds, no damping
                Rect hardGuideOrtho = ScreenToOrtho(HardGuideRect, screenSize, curState.Lens.Aspect);
                cameraOffset += OrthoOffsetToScreenBounds(targetPos, hardGuideOrtho, 0);
                targetPos.x  -= cameraOffset.x;
                targetPos.y  -= cameraOffset.y;

                // Now move it through the soft zone, with damping
                cameraOffset += OrthoOffsetToScreenBounds(targetPos, softGuideOrtho, deltaTime);
            }
            curState.RawPosition = m_PreviousCameraPosition = localToWorld * (cameraPos + cameraOffset);
            //UnityEngine.Profiling.Profiler.EndSample();
        }
        /// <summary>Applies the composer rules and orients the camera accordingly</summary>
        /// <param name="state">The current camera state</param>
        /// <param name="statePrevFrame">The camera state on the previous frame (unused)</param>
        /// <param name="deltaTime">Used for calculating damping.  If less than
        /// or equal to zero, then target will snap to the center of the dead zone.</param>
        /// <returns>curState with RawOrientation applied</returns>
        public override CameraState MutateCameraState(
            CameraState state, CameraState statePrevFrame, float deltaTime)
        {
            if (!IsValid || !state.HasLookAt)
            {
                return(state);
            }

            // Can't do anything without a group to look at
            CinemachineTargetGroup group = VirtualCamera.LookAt.GetComponent <CinemachineTargetGroup>();

            if (group == null)
            {
                return(base.MutateCameraState(state, statePrevFrame, deltaTime));
            }

            group.Update(); // Make sure the group's position is fully updated.
            state.ReferenceLookAt = group.transform.position;
            Vector3 lookAtPosition  = GetTrackedPoint(state.ReferenceLookAt);
            Vector3 currentOffset   = lookAtPosition - state.CorrectedPosition;
            float   currentDistance = currentOffset.magnitude;

            if (currentDistance < UnityVectorExtensions.Epsilon)
            {
                return(state);  // navel-gazing, get outa here
            }
            // Get the camera axis
            Vector3 fwd = currentOffset.AlmostZero() ? Vector3.forward : currentOffset.normalized;

            // Get the bounding box from that POV in view space, and find its width
            Bounds bounds = group.BoundingBox;

            m_lastBoundsMatrix = Matrix4x4.TRS(
                bounds.center - (fwd * bounds.extents.magnitude),
                Quaternion.LookRotation(fwd, state.ReferenceUp), Vector3.one);
            m_LastBounds = group.GetViewSpaceBoundingBox(m_lastBoundsMatrix);
            float   targetHeight = GetTargetHeight(m_LastBounds);
            Vector3 targetPos    = m_lastBoundsMatrix.MultiplyPoint3x4(m_LastBounds.center);

            // Apply damping
            if (deltaTime > 0 && m_FrameDamping > 0)
            {
                float delta = targetHeight - m_prevTargetHeight;
                delta       *= deltaTime / Mathf.Max(m_FrameDamping * kHumanReadableDampingScale, deltaTime);
                targetHeight = m_prevTargetHeight + delta;
            }
            m_prevTargetHeight = targetHeight;

            // Move the camera
            if (!state.Lens.Orthographic && m_AdjustmentMode != AdjustmentMode.ZoomOnly)
            {
                // What distance would be needed to get the target height, at the current FOV
                float currentFOV     = state.Lens.FieldOfView;
                float targetDistance = targetHeight / (2f * Mathf.Tan(currentFOV * Mathf.Deg2Rad / 2f));

                // target the near surface of the bounding box
                float cameraDistance = targetDistance + m_LastBounds.extents.z;

                // Clamp to respect min/max distance settings
                cameraDistance = Mathf.Clamp(
                    cameraDistance, currentDistance - m_MaxDollyIn, currentDistance + m_MaxDollyOut);
                cameraDistance = Mathf.Clamp(cameraDistance, m_MinimumDistance, m_MaximumDistance);

                // Apply
                state.PositionCorrection += targetPos - fwd * cameraDistance - state.CorrectedPosition;
            }

            // Apply zoom
            if (state.Lens.Orthographic || m_AdjustmentMode != AdjustmentMode.DollyOnly)
            {
                float nearBoundsDistance = (lookAtPosition - state.CorrectedPosition).magnitude
                                           - m_LastBounds.extents.z;
                float currentFOV = 179;
                if (nearBoundsDistance > UnityVectorExtensions.Epsilon)
                {
                    currentFOV = 2f * Mathf.Atan(targetHeight / (2 * nearBoundsDistance)) * Mathf.Rad2Deg;
                }

                LensSettings lens = state.Lens;
                lens.FieldOfView      = Mathf.Clamp(currentFOV, m_MinimumFOV, m_MaximumFOV);
                lens.OrthographicSize = targetHeight / 2;
                state.Lens            = lens;
            }

            // Now compose normally
            return(base.MutateCameraState(state, statePrevFrame, deltaTime));
        }