Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions com.unity.cinemachine/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Fixed error when both HDRP and URP rendering pipelines are added to a project.\
- Fixed outdated warning on RotationComposerComponent.
- Fixed GC Alloc in CinemachineInputAxisController.Update().
- Fixed ForceCameraPosition regression in CinemachineFollow/CinemachineOrbitalFollow/CinemachineTransposer/CinemachineOrbitalTransposer to allow looking away from targets.

### Changed
- Converted code using InstanceID references and API to EntityID.
Expand Down
26 changes: 12 additions & 14 deletions com.unity.cinemachine/Runtime/Core/TargetTracking.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,6 @@ struct Tracker
public Quaternion PreviousReferenceOrientation { get; private set; }

Vector3 m_PreviousOffset;
Vector3 m_PreviousTargetPositionDampingOffset;

Quaternion m_TargetOrientationOnAssign;
Transform m_PreviousTarget;
Expand Down Expand Up @@ -331,7 +330,6 @@ public void TrackTarget(

outTargetPosition = PreviousTargetPosition = currentPosition;
outTargetOrient = dampedRot;
m_PreviousTargetPositionDampingOffset = currentPosition - targetPosition;
}

Vector3 GetTargetPositionWithOffset(
Expand Down Expand Up @@ -405,20 +403,20 @@ public void OnForceCameraPosition(
BindingMode bindingMode, Vector3 targetOffset,
ref CameraState newState)
{
var state = component.VcamState; // old state
var prevOrient = GetReferenceOrientation(
component, bindingMode, targetOffset, newState.ReferenceUp, ref state);
var targetPos = GetTargetPositionWithOffset(component, bindingMode, targetOffset, prevOrient);
var oldState = component.VcamState;

var orient = GetReferenceOrientation(
component, bindingMode, targetOffset, newState.ReferenceUp, ref newState);
m_PreviousOffset = orient * (Quaternion.Inverse(prevOrient) * m_PreviousOffset);
PreviousReferenceOrientation = orient;
var oldOrient = GetReferenceOrientation(component, bindingMode, targetOffset, newState.ReferenceUp, ref oldState);
var newOrient = GetReferenceOrientation(component, bindingMode, targetOffset, newState.ReferenceUp, ref newState);

// Rotate the damping data also, to preserve position damping integrity
var deltaRot = newState.GetFinalOrientation() * Quaternion.Inverse(state.GetFinalOrientation());
m_PreviousTargetPositionDampingOffset = deltaRot * m_PreviousTargetPositionDampingOffset;
PreviousTargetPosition = targetPos + m_PreviousTargetPositionDampingOffset;
// Recompute the target position based on the camera state and target offset. This has the effect
// of snapping the camera to camera position since the camera posistion will be computed from the target and
// the target offset during the next frame.
var cameraOffset = Quaternion.Inverse(oldState.GetFinalOrientation()) * (PreviousTargetPosition - oldState.GetFinalPosition());
PreviousTargetPosition = newState.GetFinalOrientation() * cameraOffset + newState.GetFinalPosition();
PreviousReferenceOrientation = newOrient;

m_PreviousOffset = newOrient * (Quaternion.Inverse(oldOrient) * m_PreviousOffset);
var deltaRot = newState.GetFinalOrientation() * Quaternion.Inverse(oldState.GetFinalOrientation());
if (bindingMode == BindingMode.WorldSpace)
m_PreviousOffset = deltaRot * m_PreviousOffset;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class CinemachineRuntimeFixtureBase : CinemachineFixtureBase
protected CinemachineBrain m_Brain;
protected readonly FloatEqualityComparer m_FloatEqualityComparer = new(UnityVectorExtensions.Epsilon);
protected readonly Vector3EqualityComparer m_Vector3EqualityComparer = new(UnityVectorExtensions.Epsilon);
protected readonly QuaternionEqualityComparer m_QuaternionComparer = new QuaternionEqualityComparer(1e-5f);

[SetUp]
public override void SetUp()
Expand Down
46 changes: 46 additions & 0 deletions com.unity.cinemachine/Tests/Runtime/FollowForcePositionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
using Unity.Cinemachine;

namespace Unity.Cinemachine.Tests
{
[TestFixture]
public class FollowForcePositionTests : CinemachineRuntimeFixtureBase
{
CinemachineCamera m_Vcam;
GameObject m_FollowObject;

[SetUp]
public override void SetUp()
{
base.SetUp();

m_Vcam = CreateGameObject("CM Vcam", typeof(CinemachineCamera)).GetComponent<CinemachineCamera>();
m_FollowObject = CreateGameObject("Follow Object");
}

[UnityTest, Description("UUM-131870: ForceCameraPosition should allow looking away from the target.")]
public IEnumerator LookAwayFromTarget()
{
CinemachineCore.UniformDeltaTimeOverride = 0.0f; // we only test force position, not damping
var follow = m_Vcam.gameObject.AddComponent<CinemachineFollow>();
follow.FollowOffset = new Vector3(0, 0, -10);
m_Vcam.Follow = m_FollowObject.transform;

// Initial update to settle camera
m_FollowObject.transform.position = Vector3.zero;
yield return null;
Assume.That(m_Vcam.State.GetFinalPosition(), Is.EqualTo(follow.FollowOffset).Using(m_Vector3EqualityComparer));

// Move camera away from target
var forcedPos = new Vector3(0, 5, -5);
var forcedRot = Quaternion.identity;
m_Vcam.ForceCameraPosition(forcedPos, forcedRot);
yield return null;
Assert.That(m_Vcam.State.GetFinalPosition(), Is.EqualTo(forcedPos).Using(m_Vector3EqualityComparer));
Assert.That(m_Vcam.State.GetFinalOrientation(), Is.EqualTo(forcedRot).Using(m_QuaternionComparer));
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.