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
3 changes: 3 additions & 0 deletions com.unity.cinemachine/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [3.1.7-pre.1] - 2026-02-24

### Bugfixes
- Fixed stack frame snapshot not resetting when CameraBlendStack completed blend.

### Changed
- Added support for fast enter play mode.

Expand Down
17 changes: 13 additions & 4 deletions com.unity.cinemachine/Runtime/Core/CameraBlendStack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,8 @@ public ICinemachineCamera GetSnapshotIfAppropriate(ICinemachineCamera cam, float
{
if (cam == null || (cam.State.BlendHint & CameraState.BlendHints.FreezeWhenBlendingOut) == 0)
{
// No snapshot required - reset it
m_Snapshot.TakeSnapshot(null);
m_SnapshotSource = null;
m_SnapshotBlendWeight = 0;
// No snapshot required - clear it
ClearSnapshot();
return cam;
}
// A snapshot is needed
Expand All @@ -101,6 +99,13 @@ public ICinemachineCamera GetSnapshotIfAppropriate(ICinemachineCamera cam, float
// Use the most recent snapshot
return m_Snapshot;
}

public void ClearSnapshot()
{
m_Snapshot.TakeSnapshot(null);
m_SnapshotSource = null;
m_SnapshotBlendWeight = 0;
}
}

// Current game state is always frame 0, overrides are subsequent frames
Expand Down Expand Up @@ -213,6 +218,7 @@ public void ResetRootFrame()
frame.Blend.CamB = null;
frame.Source.ClearBlend();
frame.Source.CamB = null;
frame.ClearSnapshot();
}
}

Expand Down Expand Up @@ -329,7 +335,10 @@ public void UpdateRootFrame(

// Advance the working blend
if (AdvanceBlend(frame.Blend, deltaTime))
{
frame.Source.ClearBlend();
frame.ClearSnapshot();
}
frame.UpdateCameraState(up, deltaTime);

// local function
Expand Down
43 changes: 43 additions & 0 deletions com.unity.cinemachine/Tests/Runtime/CamerasBlendingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,5 +210,48 @@ public IEnumerator SetActiveBlend()
yield return UpdateCinemachine();
Assert.That(m_Brain.ActiveBlend == null);
}

[UnityTest]
[Description("Regression test for UUM-131151 tests that blend snapshots are reset correctly when blending is interrupted")]
public IEnumerator BlendClearsSnapshotWhenBlendingIsInterrupted()
{
// We test cancelling a blend, changing the source camera position and then restarting the blend
// The camera must be in FreezeWhenBlendingOut mode
// We expect the blend to start from the new position

((CinemachineCamera)m_Source).BlendHint |= CinemachineCore.BlendHints.FreezeWhenBlendingOut;

yield return UpdateCinemachine();
Assume.That(ReferenceEquals(m_Brain.ActiveVirtualCamera, m_Source));
Assume.That(m_Brain.transform.position, Is.EqualTo(m_Source.transform.position));

// Start blend to target
m_Target.enabled = true;
yield return UpdateCinemachine();
Assume.That(m_Brain.IsBlending, Is.True);

yield return UpdateCinemachine();

// Cancel, blend back to source
m_Target.enabled = false;
yield return UpdateCinemachine();
Assume.That(m_Brain.IsBlending, Is.True);

while (m_Brain.IsBlending)
yield return UpdateCinemachine();

Assume.That(ReferenceEquals(m_Brain.ActiveVirtualCamera, m_Source));
Assume.That(m_Brain.transform.position, Is.EqualTo(m_Source.transform.position));

var newPos = new Vector3(0, 5, 0);
m_Source.transform.position = newPos;

// Restart blend to target
m_Target.enabled = true;
yield return UpdateCinemachine();

// Make sure we started from 0, 5, 0 and not 10, 0, 0
Assert.That(m_Brain.transform.position.y, Is.GreaterThan(4.0f));
}
}
}