From b339a7dbe5b49f5673e4ef72ccc331f7503382f8 Mon Sep 17 00:00:00 2001 From: Greg Labute Date: Tue, 8 Aug 2023 08:03:04 -0400 Subject: [PATCH] group framing: nullrefs, remove FramingOffset, improve gameview indicator --- com.unity.cinemachine/CHANGELOG.md | 8 +- .../Documentation~/CinemachineGroupFraming.md | 1 - .../Editors/CinemachineGroupFramingEditor.cs | 39 +++++--- .../CinemachinePositionComposerEditor.cs | 5 +- .../CinemachineRotationComposerEditor.cs | 5 +- .../Obsolete/CinemachineComposerEditor.cs | 5 +- .../CinemachineFramingTransposerEditor.cs | 11 +-- .../CinemachineGroupComposerEditor.cs | 4 +- .../Editor/Upgrader/UpgradeObjectToCm3.cs | 2 +- .../CmPipelineComponentInspectorUtility.cs | 97 ++++++++++++------- .../Behaviours/CinemachineGroupFraming.cs | 27 +----- .../Behaviours/CinemachineTargetGroup.cs | 8 ++ .../Core/CinemachineVirtualCameraBase.cs | 2 +- .../Runtime/Core/UnityVectorExtensions.cs | 2 +- .../CinemachineFramingTransposer.cs | 2 +- .../Deprecated/CinemachineGroupComposer.cs | 2 +- 16 files changed, 114 insertions(+), 106 deletions(-) diff --git a/com.unity.cinemachine/CHANGELOG.md b/com.unity.cinemachine/CHANGELOG.md index 0a603d980..c8fa851bc 100644 --- a/com.unity.cinemachine/CHANGELOG.md +++ b/com.unity.cinemachine/CHANGELOG.md @@ -12,14 +12,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Bugfix: CinemachineDeoccluder was causing a pop when OnTargetObjectWarped was called. - Bugfix: Spurious camera cut events were being issued, especially in HDRP. - Bugfix: Mull reference exceptions when inspector is hidden behind another tab. -- Bugfix: Group Framing inspector was displaying incorrect warning when LookAt target is a group. -- Group Framing: Added a setting to control framing offset, allowing groups to be not centered on the screen. -- Added Recentering Target to OrbitalFollow. Recentering is now possible with Lazy Follow +- Bugfix: GroupFraming inspector was displaying incorrect warning when LookAt target is a group. +- Bugfix: GroupFraming displays more accurate group size indicator in the game view. +- Bugfix: nullrefs in log when target group was deleted but was still being referenced by vcams. +- Added Recentering Target to OrbitalFollow. Recentering is now possible with Lazy Follow. - Deoccluder accommodates camera radius in all modes. - StateDrivenCamera: child camera enabled status and priority are now taken into account when choosing the current active camera. - Renamed CinemachineSplineDolly.CameraUp to CameraRotation, which more accurately reflects what it does. - Renamed InputAxis.DoRecentering() to InputAxis.UpdateRecentering() - Added API in Deoccluder and ThirdPersonFollow to access which collision objects are impacting the camera position. +- Added ICinemachineTargetGroup.IsValid property to detect deleted groups. - Removed CinemachineToolSettings overlay. diff --git a/com.unity.cinemachine/Documentation~/CinemachineGroupFraming.md b/com.unity.cinemachine/Documentation~/CinemachineGroupFraming.md index f06a7a2e8..1e8460267 100644 --- a/com.unity.cinemachine/Documentation~/CinemachineGroupFraming.md +++ b/com.unity.cinemachine/Documentation~/CinemachineGroupFraming.md @@ -20,7 +20,6 @@ For this to work, the CinemachineCamera's Tracking Target must be a CinemachineT | | _Change Position_ | Camera is moved horizontally and vertically until the desired framing is achieved. | | | _Change Rotation_ | Camera is rotated to achieve the desired framing. | | __Framing Size__ || The screen-space bounding box that the targets should occupy. Use 1 to fill the whole screen, 0.5 to fill half the screen, and so on. | -| __Framing Offset__ || How to offset the group's bounding shape on the screen, so that the group is not necessarily presented at screen center. 0 is screen center, 1 and -1 are the edges of the screen. | | __Damping__ || How gradually to make the framing adjustment. A larger number gives a slower response, smaller numbers a snappier one. | | __Dolly Range__ || The allowable range that the camera may be moved in order to achieve the desired framing. A negative distance is towards the target, and a positive distance is away from the target. | | __FOV Range__ || If adjusting FOV, it will be clamped to this range. | diff --git a/com.unity.cinemachine/Editor/Editors/CinemachineGroupFramingEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachineGroupFramingEditor.cs index 89ec03d18..76f624e1a 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachineGroupFramingEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachineGroupFramingEditor.cs @@ -27,26 +27,24 @@ void OnDisable() public override VisualElement CreateInspectorGUI() { - var serializedTarget = new SerializedObject(Target); var ux = new VisualElement(); this.AddMissingCmCameraHelpBox(ux, CmPipelineComponentInspectorUtility.RequiredTargets.Group); var groupSizeIsZeroHelp = ux.AddChild(new HelpBox("Group size is zero, cannot frame.", HelpBoxMessageType.Warning)); - ux.Add(new PropertyField(serializedTarget.FindProperty(() => Target.FramingMode))); - ux.Add(new PropertyField(serializedTarget.FindProperty(() => Target.FramingSize))); - ux.Add(new PropertyField(serializedTarget.FindProperty(() => Target.Damping))); - ux.Add(new PropertyField(serializedTarget.FindProperty(() => Target.FramingOffset))); + ux.Add(new PropertyField(serializedObject.FindProperty(() => Target.FramingMode))); + ux.Add(new PropertyField(serializedObject.FindProperty(() => Target.FramingSize))); + ux.Add(new PropertyField(serializedObject.FindProperty(() => Target.Damping))); var perspectiveControls = ux.AddChild(new VisualElement()); - var sizeAdjustmentProperty = serializedTarget.FindProperty(() => Target.SizeAdjustment); + var sizeAdjustmentProperty = serializedObject.FindProperty(() => Target.SizeAdjustment); perspectiveControls.Add(new PropertyField(sizeAdjustmentProperty)); - perspectiveControls.AddChild(new PropertyField(serializedTarget.FindProperty(() => Target.LateralAdjustment))); - var fovRange = perspectiveControls.AddChild(new PropertyField(serializedTarget.FindProperty(() => Target.FovRange))); - var dollyRange = perspectiveControls.AddChild(new PropertyField(serializedTarget.FindProperty(() => Target.DollyRange))); + perspectiveControls.AddChild(new PropertyField(serializedObject.FindProperty(() => Target.LateralAdjustment))); + var fovRange = perspectiveControls.AddChild(new PropertyField(serializedObject.FindProperty(() => Target.FovRange))); + var dollyRange = perspectiveControls.AddChild(new PropertyField(serializedObject.FindProperty(() => Target.DollyRange))); var orthoControls = ux.AddChild(new VisualElement()); - orthoControls.Add(new PropertyField(serializedTarget.FindProperty(() => Target.OrthoSizeRange))); + orthoControls.Add(new PropertyField(serializedObject.FindProperty(() => Target.OrthoSizeRange))); ux.TrackPropertyValue(sizeAdjustmentProperty, (prop) => { @@ -67,7 +65,11 @@ public override VisualElement CreateInspectorGUI() { var vcam = (targets[i] as CinemachineGroupFraming).ComponentOwner; if (vcam != null) + { group = vcam.FollowTargetAsGroup; + if (group != null && !group.IsValid) + group = null; + } } groupSizeIsZeroHelp.SetVisible(group != null && group.Sphere.radius < 0.01f); @@ -88,23 +90,28 @@ protected virtual void OnGuiHandler(CinemachineBrain brain) return; var vcam = Target.ComponentOwner; - if (!brain.IsValidChannel(vcam)) + if (!brain.IsValidChannel(vcam) || !brain.IsLiveChild(vcam)) return; var group = vcam.LookAtTargetAsGroup; - if (group == null) + group ??= vcam.FollowTargetAsGroup; + if (group == null || !group.IsValid) return; CmPipelineComponentInspectorUtility.OnGUI_DrawOnscreenTargetMarker( - group, group.Sphere.position, - vcam.State.GetFinalOrientation(), brain.OutputCamera); + group.Sphere.position, brain.OutputCamera); + CmPipelineComponentInspectorUtility.OnGUI_DrawOnscreenGroupSizeMarker( + Target.GroupBounds, Target.GroupBoundsMatrix, brain.OutputCamera); } [DrawGizmo(GizmoType.Active | GizmoType.InSelectionHierarchy, typeof(CinemachineGroupFraming))] static void DrawGroupComposerGizmos(CinemachineGroupFraming target, GizmoType selectionType) { // Show the group bounding box, as viewed from the camera position - if (target.enabled && target.ComponentOwner != null && target.ComponentOwner.FollowTargetAsGroup != null) + var vcam = target.ComponentOwner; + if (!target.enabled && vcam != null + && (vcam.FollowTargetAsGroup != null && vcam.FollowTargetAsGroup.IsValid) + || (vcam.LookAtTargetAsGroup != null && vcam.LookAtTargetAsGroup.IsValid)) { var oldM = Gizmos.matrix; var oldC = Gizmos.color; @@ -112,7 +119,7 @@ static void DrawGroupComposerGizmos(CinemachineGroupFraming target, GizmoType se Gizmos.matrix = target.GroupBoundsMatrix; Bounds b = target.GroupBounds; Gizmos.color = Color.yellow; - if (target.ComponentOwner.State.Lens.Orthographic) + if (vcam.State.Lens.Orthographic) Gizmos.DrawWireCube(b.center, b.size); else { diff --git a/com.unity.cinemachine/Editor/Editors/CinemachinePositionComposerEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachinePositionComposerEditor.cs index 47cc1880a..83176426d 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachinePositionComposerEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachinePositionComposerEditor.cs @@ -76,11 +76,8 @@ protected virtual void OnGuiHandler(CinemachineBrain brain) // Draw an on-screen gizmo for the target if (Target.FollowTarget != null && isLive) - { CmPipelineComponentInspectorUtility.OnGUI_DrawOnscreenTargetMarker( - null, Target.TrackedPoint, - vcam.State.GetFinalOrientation(), brain.OutputCamera); - } + Target.TrackedPoint, brain.OutputCamera); } void OnSceneGUI() diff --git a/com.unity.cinemachine/Editor/Editors/CinemachineRotationComposerEditor.cs b/com.unity.cinemachine/Editor/Editors/CinemachineRotationComposerEditor.cs index 7c301ee67..ffbd8a4e9 100644 --- a/com.unity.cinemachine/Editor/Editors/CinemachineRotationComposerEditor.cs +++ b/com.unity.cinemachine/Editor/Editors/CinemachineRotationComposerEditor.cs @@ -74,11 +74,8 @@ protected virtual void OnGuiHandler(CinemachineBrain brain) // Draw an on-screen gizmo for the target if (Target.LookAtTarget != null && isLive) - { CmPipelineComponentInspectorUtility.OnGUI_DrawOnscreenTargetMarker( - null, Target.TrackedPoint, - vcam.State.GetFinalOrientation(), brain.OutputCamera); - } + Target.TrackedPoint, brain.OutputCamera); } void OnSceneGUI() diff --git a/com.unity.cinemachine/Editor/Obsolete/CinemachineComposerEditor.cs b/com.unity.cinemachine/Editor/Obsolete/CinemachineComposerEditor.cs index 933114046..c94917147 100644 --- a/com.unity.cinemachine/Editor/Obsolete/CinemachineComposerEditor.cs +++ b/com.unity.cinemachine/Editor/Obsolete/CinemachineComposerEditor.cs @@ -74,11 +74,8 @@ protected virtual void OnGuiHandler(CinemachineBrain brain) // Draw an on-screen gizmo for the target if (Target.LookAtTarget != null && isLive) - { CmPipelineComponentInspectorUtility.OnGUI_DrawOnscreenTargetMarker( - Target.LookAtTargetAsGroup, Target.TrackedPoint, - vcam.State.GetFinalOrientation(), brain.OutputCamera); - } + Target.TrackedPoint, brain.OutputCamera); } void OnSceneGUI() diff --git a/com.unity.cinemachine/Editor/Obsolete/CinemachineFramingTransposerEditor.cs b/com.unity.cinemachine/Editor/Obsolete/CinemachineFramingTransposerEditor.cs index 15e0161d8..f2d6efc53 100644 --- a/com.unity.cinemachine/Editor/Obsolete/CinemachineFramingTransposerEditor.cs +++ b/com.unity.cinemachine/Editor/Obsolete/CinemachineFramingTransposerEditor.cs @@ -25,7 +25,7 @@ protected override void GetExcludedPropertiesInInspector(List excluded) excluded.Add(FieldPath(x => x.m_BiasY)); } ICinemachineTargetGroup group = Target.FollowTargetAsGroup; - if (group == null || Target.m_GroupFramingMode == CinemachineFramingTransposer.FramingMode.None) + if (group == null || !group.IsValid || Target.m_GroupFramingMode == CinemachineFramingTransposer.FramingMode.None) { excluded.Add(FieldPath(x => x.m_GroupFramingSize)); excluded.Add(FieldPath(x => x.m_AdjustmentMode)); @@ -37,7 +37,7 @@ protected override void GetExcludedPropertiesInInspector(List excluded) excluded.Add(FieldPath(x => x.m_MaximumFOV)); excluded.Add(FieldPath(x => x.m_MinimumOrthoSize)); excluded.Add(FieldPath(x => x.m_MaximumOrthoSize)); - if (group == null) + if (group == null || !group.IsValid) excluded.Add(FieldPath(x => x.m_GroupFramingMode)); } else @@ -143,18 +143,15 @@ protected virtual void OnGuiHandler(CinemachineBrain brain) // Draw an on-screen gizmo for the target if (Target.FollowTarget != null && isLive) - { CmPipelineComponentInspectorUtility.OnGUI_DrawOnscreenTargetMarker( - Target.LookAtTargetAsGroup, Target.TrackedPoint, - vcam.State.GetFinalOrientation(), brain.OutputCamera); - } + Target.TrackedPoint, brain.OutputCamera); } [DrawGizmo(GizmoType.Active | GizmoType.InSelectionHierarchy, typeof(CinemachineFramingTransposer))] private static void DrawGroupComposerGizmos(CinemachineFramingTransposer target, GizmoType selectionType) { // Show the group bounding box, as viewed from the camera position - if (target.FollowTargetAsGroup != null + if (target.FollowTargetAsGroup != null && target.FollowTargetAsGroup.IsValid && target.m_GroupFramingMode != CinemachineFramingTransposer.FramingMode.None) { Matrix4x4 m = Gizmos.matrix; diff --git a/com.unity.cinemachine/Editor/Obsolete/CinemachineGroupComposerEditor.cs b/com.unity.cinemachine/Editor/Obsolete/CinemachineGroupComposerEditor.cs index 4a58ec0ba..1ca817b95 100644 --- a/com.unity.cinemachine/Editor/Obsolete/CinemachineGroupComposerEditor.cs +++ b/com.unity.cinemachine/Editor/Obsolete/CinemachineGroupComposerEditor.cs @@ -60,7 +60,7 @@ protected override void GetExcludedPropertiesInInspector(List excluded) public override void OnInspectorGUI() { - if (MyTarget.IsValid && MyTarget.LookAtTargetAsGroup == null) + if (MyTarget.IsValid && (MyTarget.LookAtTargetAsGroup == null || !MyTarget.LookAtTargetAsGroup.IsValid)) EditorGUILayout.HelpBox( "The Framing settings will be ignored because the LookAt target is not a kind of ICinemachineTargetGroup", MessageType.Info); @@ -72,7 +72,7 @@ public override void OnInspectorGUI() static void DrawGroupComposerGizmos(CinemachineGroupComposer target, GizmoType selectionType) { // Show the group bounding box, as viewed from the camera position - if (target.LookAtTargetAsGroup != null) + if (target.LookAtTargetAsGroup != null && target.LookAtTargetAsGroup.IsValid) { Matrix4x4 m = Gizmos.matrix; Bounds b = target.LastBounds; diff --git a/com.unity.cinemachine/Editor/Upgrader/UpgradeObjectToCm3.cs b/com.unity.cinemachine/Editor/Upgrader/UpgradeObjectToCm3.cs index 26ee4d784..7016ade9a 100644 --- a/com.unity.cinemachine/Editor/Upgrader/UpgradeObjectToCm3.cs +++ b/com.unity.cinemachine/Editor/Upgrader/UpgradeObjectToCm3.cs @@ -78,7 +78,7 @@ public GameObject UpgradeComponents(GameObject go) { var ft = go.GetComponent(); ft.UpgradeToCm3(go.GetComponent()); - if (ft.FollowTargetAsGroup != null + if (ft.FollowTargetAsGroup != null && ft.FollowTargetAsGroup.IsValid && ft.m_GroupFramingMode != CinemachineFramingTransposer.FramingMode.None && !go.TryGetComponent(out var _)) { diff --git a/com.unity.cinemachine/Editor/Utility/CmPipelineComponentInspectorUtility.cs b/com.unity.cinemachine/Editor/Utility/CmPipelineComponentInspectorUtility.cs index 26d7f3d7c..1d8b3753c 100644 --- a/com.unity.cinemachine/Editor/Utility/CmPipelineComponentInspectorUtility.cs +++ b/com.unity.cinemachine/Editor/Utility/CmPipelineComponentInspectorUtility.cs @@ -56,23 +56,32 @@ public static void AddMissingCmCameraHelpBox( { if (targets[i] is CinemachineComponentBase c) { - noCamera |= c.VirtualCamera == null || c.VirtualCamera is CinemachineCameraManagerBase; + var vcam = c.VirtualCamera; + noCamera |= vcam == null || vcam is CinemachineCameraManagerBase; + if (vcam != null) + vcam.UpdateTargetCache(); switch (requiredTargets) { case RequiredTargets.Tracking: noTarget |= c.FollowTarget == null; break; case RequiredTargets.LookAt: noTarget |= c.LookAtTarget == null; break; - case RequiredTargets.Group: noTarget |= c.FollowTargetAsGroup == null && c.LookAtTargetAsGroup == null; break; + case RequiredTargets.Group: noTarget |= + (c.FollowTargetAsGroup == null || !c.FollowTargetAsGroup.IsValid) + && (c.LookAtTargetAsGroup == null || !c.LookAtTargetAsGroup.IsValid); break; } } else if (targets[i] is CinemachineExtension x) { - noCamera |= x.ComponentOwner == null; + var vcam = x.ComponentOwner; + noCamera |= vcam == null; + if (vcam != null) + vcam.UpdateTargetCache(); switch (requiredTargets) { - case RequiredTargets.Tracking: noTarget |= noCamera || x.ComponentOwner.Follow == null; break; - case RequiredTargets.LookAt: noTarget |= noCamera || x.ComponentOwner.LookAt == null; break; + case RequiredTargets.Tracking: noTarget |= noCamera || vcam.Follow == null; break; + case RequiredTargets.LookAt: noTarget |= noCamera || vcam.LookAt == null; break; case RequiredTargets.Group: noTarget |= noCamera - || (x.ComponentOwner.FollowTargetAsGroup == null && x.ComponentOwner.LookAtTargetAsGroup == null); break; + || ((vcam.FollowTargetAsGroup == null || !vcam.FollowTargetAsGroup.IsValid) + && (vcam.LookAtTargetAsGroup == null || !vcam.LookAtTargetAsGroup.IsValid)); break; } } else if (targets[i] is MonoBehaviour b) @@ -175,40 +184,50 @@ void AddController(Type controllerType) }; } - - public static void OnGUI_DrawOnscreenTargetMarker( - ICinemachineTargetGroup group, Vector3 worldPoint, - Quaternion vcamRotation, Camera camera) + public static void OnGUI_DrawOnscreenTargetMarker(Vector3 worldPoint, Camera camera) { var c = camera.WorldToScreenPoint(worldPoint); c.y = Screen.height - c.y; + if (c.z > 0) + { + var oldColor = GUI.color; + var r = new Rect(c, Vector2.zero).Inflated(Vector2.one * CinemachineComposerPrefs.TargetSize.Value); + GUI.color = new Color(0, 0, 0, CinemachineComposerPrefs.OverlayOpacity.Value); + GUI.DrawTexture(r.Inflated(new Vector2(1, 1)), Texture2D.whiteTexture, ScaleMode.StretchToFill); + var color = CinemachineComposerPrefs.TargetColour.Value; + GUI.color = color; + GUI.DrawTexture(r, Texture2D.whiteTexture, ScaleMode.StretchToFill); + GUI.color = oldColor; + } + } + + public static void OnGUI_DrawOnscreenGroupSizeMarker( + Bounds groupBounds, Matrix4x4 cameraViewMatrix, Camera camera) + { + var c = groupBounds.center; c.z -= groupBounds.extents.z; groupBounds.center = c; + var e = groupBounds.extents; e.z = 0; groupBounds.extents = e; + + c = camera.WorldToScreenPoint(cameraViewMatrix.MultiplyPoint3x4(c)); if (c.z < 0) return; + e = camera.WorldToScreenPoint(cameraViewMatrix.MultiplyPoint3x4(groupBounds.center + e)); + var groupSize = new Vector2(Mathf.Abs(e.x - c.x), Mathf.Abs(e.y - c.y)); - var oldColor = GUI.color; - float radius = 0; - if (group != null) - { - var p2 = camera.WorldToScreenPoint( - worldPoint + vcamRotation * new Vector3(group.Sphere.radius, 0, 0)); - radius = Mathf.Abs(p2.x - c.x); - } - var r = new Rect(c, Vector2.zero).Inflated(Vector2.one * CinemachineComposerPrefs.TargetSize.Value); - GUI.color = new Color(0, 0, 0, CinemachineComposerPrefs.OverlayOpacity.Value); - GUI.DrawTexture(r.Inflated(new Vector2(1, 1)), Texture2D.whiteTexture, ScaleMode.StretchToFill); - var color = CinemachineComposerPrefs.TargetColour.Value; - GUI.color = color; - GUI.DrawTexture(r, Texture2D.whiteTexture, ScaleMode.StretchToFill); + var radius = Mathf.Max(groupSize.x, groupSize.y); if (radius > CinemachineComposerPrefs.TargetSize.Value) { - color.a = Mathf.Lerp(1f, CinemachineComposerPrefs.OverlayOpacity.Value, (radius - 10f) / 50f); + var oldColor = GUI.color; + var color = CinemachineComposerPrefs.TargetColour.Value; + color.a = Mathf.Lerp(1f, CinemachineComposerPrefs.OverlayOpacity.Value, (radius - 10f) / 100f); GUI.color = color; - GUI.DrawTexture(r.Inflated(new Vector2(radius, radius)), - GetTargetMarkerTex(), ScaleMode.StretchToFill); + c.y = camera.pixelHeight - c.y; + var r = new Rect(c, Vector2.zero).Inflated(groupSize); + GUI.DrawTexture(r, GetTargetMarkerTex(), ScaleMode.StretchToFill); + GUI.color = oldColor; } - GUI.color = oldColor; } + static Texture2D s_TargetMarkerTex = null; static Texture2D GetTargetMarkerTex() { @@ -249,22 +268,32 @@ public static void IMGUI_DrawMissingCmCameraHelpBox( { if (targets[i] is CinemachineComponentBase c) { - noCamera |= c.VirtualCamera == null || c.VirtualCamera is CinemachineCameraManagerBase; + var vcam = c.VirtualCamera; + noCamera |= vcam == null || vcam is CinemachineCameraManagerBase; + if (vcam != null) + vcam.UpdateTargetCache(); switch (requiredTargets) { case RequiredTargets.Tracking: noTarget |= c.FollowTarget == null; break; case RequiredTargets.LookAt: noTarget |= c.LookAtTarget == null; break; - case RequiredTargets.Group: noTarget |= c.FollowTargetAsGroup == null; break; + case RequiredTargets.Group: noTarget |= + (c.FollowTargetAsGroup == null || !c.FollowTargetAsGroup.IsValid) + && (c.LookAtTargetAsGroup == null || !c.LookAtTargetAsGroup.IsValid); break; } } else if (targets[i] is CinemachineExtension x) { - noCamera |= x.ComponentOwner == null; + var vcam = x.ComponentOwner; + noCamera |= vcam == null; + if (vcam != null) + vcam.UpdateTargetCache(); switch (requiredTargets) { - case RequiredTargets.Tracking: noTarget |= noCamera || x.ComponentOwner.Follow == null; break; - case RequiredTargets.LookAt: noTarget |= noCamera || x.ComponentOwner.LookAt == null; break; - case RequiredTargets.Group: noTarget |= noCamera || x.ComponentOwner.FollowTargetAsGroup == null; break; + case RequiredTargets.Tracking: noTarget |= noCamera || vcam.Follow == null; break; + case RequiredTargets.LookAt: noTarget |= noCamera || vcam.LookAt == null; break; + case RequiredTargets.Group: noTarget |= noCamera + || ((vcam.FollowTargetAsGroup == null || !vcam.FollowTargetAsGroup.IsValid) + && (vcam.LookAtTargetAsGroup == null || !vcam.LookAtTargetAsGroup.IsValid)); break; } } } diff --git a/com.unity.cinemachine/Runtime/Behaviours/CinemachineGroupFraming.cs b/com.unity.cinemachine/Runtime/Behaviours/CinemachineGroupFraming.cs index 0572f7533..e21c65907 100644 --- a/com.unity.cinemachine/Runtime/Behaviours/CinemachineGroupFraming.cs +++ b/com.unity.cinemachine/Runtime/Behaviours/CinemachineGroupFraming.cs @@ -43,12 +43,6 @@ public enum FramingModes + "rapidly adjusting the camera to keep the group in the frame. Larger numbers give a heavier " + "more slowly responding camera.")] public float Damping = 2f; - - /// - /// Offset from screen center at which to place the group center. X is left/right, Y is up/down. - /// - [Tooltip("Offset from screen center at which to place the group center. X is left/right, Y is up/down")] - public Vector2 FramingOffset = Vector2.zero; /// How to adjust the camera to get the desired framing size public enum SizeAdjustmentModes @@ -117,7 +111,6 @@ void Reset() LateralAdjustment = LateralAdjustmentModes.ChangePosition; FramingSize = 0.8f; Damping = 2; - FramingOffset = Vector2.zero; DollyRange = new Vector2(-100, 100); FovRange = new Vector2(1, 100); OrthoSizeRange = new Vector2(1, 1000); @@ -167,7 +160,7 @@ protected override void PostPipelineStageCallback( var group = vcam.LookAtTargetAsGroup; group ??= vcam.FollowTargetAsGroup; - if (group == null) + if (group == null || !group.IsValid) return; var extra = GetExtraState(vcam); @@ -204,10 +197,6 @@ void OrthoFraming( extra.FovAdjustment += vcam.DetachedFollowTargetDamp(deltaFov - extra.FovAdjustment, damping, deltaTime); lens.OrthographicSize += extra.FovAdjustment; state.Lens = lens; - - // Apply framing offset - state.PositionCorrection -= state.RawOrientation * new Vector3( - lens.OrthographicSize * lens.Aspect * FramingOffset.x, lens.OrthographicSize * FramingOffset.y, 0); } void PerspectiveFraming( @@ -260,20 +249,6 @@ void PerspectiveFraming( var deltaPos = Quaternion.Inverse(state.RawOrientation) * (camPos - state.RawPosition); extra.PosAdjustment += vcam.DetachedFollowTargetDamp(deltaPos - extra.PosAdjustment, damping, deltaTime); state.PositionCorrection += state.RawOrientation * extra.PosAdjustment; - - // Apply framing offset - if (moveCamera) - { - var h = Mathf.Tan(Mathf.Deg2Rad * lens.FieldOfView * 0.5f) * GroupBounds.center.z; - state.PositionCorrection -= state.RawOrientation * new Vector3( - h * lens.Aspect * FramingOffset.x, h * FramingOffset.y, 0); - } - else - { - state.OrientationCorrection = state.OrientationCorrection.ApplyCameraRotation(new Vector2( - lens.FieldOfView * lens.Aspect * FramingOffset.y * 0.5f, - lens.FieldOfView * FramingOffset.x * -0.5f), Quaternion.Inverse(state.GetFinalOrientation()) * state.ReferenceUp); - } } void AdjustSize( diff --git a/com.unity.cinemachine/Runtime/Behaviours/CinemachineTargetGroup.cs b/com.unity.cinemachine/Runtime/Behaviours/CinemachineTargetGroup.cs index 5ee17cbb0..327a9404c 100644 --- a/com.unity.cinemachine/Runtime/Behaviours/CinemachineTargetGroup.cs +++ b/com.unity.cinemachine/Runtime/Behaviours/CinemachineTargetGroup.cs @@ -11,6 +11,11 @@ namespace Unity.Cinemachine /// public interface ICinemachineTargetGroup { + /// + /// Returns true if object has not been deleted. + /// + bool IsValid { get; } + /// /// Get the MonoBehaviour's Transform /// @@ -193,6 +198,9 @@ public Target[] m_Targets /// public Transform Transform => transform; + /// + public bool IsValid => this != null; + /// The axis-aligned bounding box of the group, computed using the /// targets positions and radii public Bounds BoundingBox diff --git a/com.unity.cinemachine/Runtime/Core/CinemachineVirtualCameraBase.cs b/com.unity.cinemachine/Runtime/Core/CinemachineVirtualCameraBase.cs index a6f2452b1..28a840e16 100644 --- a/com.unity.cinemachine/Runtime/Core/CinemachineVirtualCameraBase.cs +++ b/com.unity.cinemachine/Runtime/Core/CinemachineVirtualCameraBase.cs @@ -725,7 +725,7 @@ static OnDomainReload() /// targets and update the target cache. This is needed for tracking /// when a target object changes. /// - protected void UpdateTargetCache() + public void UpdateTargetCache() { var target = ResolveFollow(Follow); FollowTargetChanged = target != m_CachedFollowTarget; diff --git a/com.unity.cinemachine/Runtime/Core/UnityVectorExtensions.cs b/com.unity.cinemachine/Runtime/Core/UnityVectorExtensions.cs index 5a44f248b..ce76316fd 100644 --- a/com.unity.cinemachine/Runtime/Core/UnityVectorExtensions.cs +++ b/com.unity.cinemachine/Runtime/Core/UnityVectorExtensions.cs @@ -398,7 +398,7 @@ public static class UnityRectExtensions { /// Inflate a rect /// - /// x and y are added/subtracted fto/from the edges of + /// x and y are added/subtracted to/from the edges of /// the rect, inflating it in all directions /// The inflated rect public static Rect Inflated(this Rect r, Vector2 delta) diff --git a/com.unity.cinemachine/Runtime/Deprecated/CinemachineFramingTransposer.cs b/com.unity.cinemachine/Runtime/Deprecated/CinemachineFramingTransposer.cs index e5c3843d8..69172bf12 100644 --- a/com.unity.cinemachine/Runtime/Deprecated/CinemachineFramingTransposer.cs +++ b/com.unity.cinemachine/Runtime/Deprecated/CinemachineFramingTransposer.cs @@ -439,7 +439,7 @@ public override void MutateCameraState(ref CameraState curState, float deltaTime // Compute group bounds and adjust follow target for group framing ICinemachineTargetGroup group = FollowTargetAsGroup; - bool isGroupFraming = group != null && m_GroupFramingMode != FramingMode.None && !group.IsEmpty; + bool isGroupFraming = group != null && group.IsValid && m_GroupFramingMode != FramingMode.None && !group.IsEmpty; if (isGroupFraming) followTargetPosition = ComputeGroupBounds(group, ref curState); diff --git a/com.unity.cinemachine/Runtime/Deprecated/CinemachineGroupComposer.cs b/com.unity.cinemachine/Runtime/Deprecated/CinemachineGroupComposer.cs index 5584865eb..012ccb63f 100644 --- a/com.unity.cinemachine/Runtime/Deprecated/CinemachineGroupComposer.cs +++ b/com.unity.cinemachine/Runtime/Deprecated/CinemachineGroupComposer.cs @@ -146,7 +146,7 @@ public override void MutateCameraState(ref CameraState curState, float deltaTime { // Can't do anything without a group to look at ICinemachineTargetGroup group = LookAtTargetAsGroup; - if (group == null) + if (group == null || !group.IsValid) { base.MutateCameraState(ref curState, deltaTime); return;