Skip to content

fix: resolve chat message fade persisting after teleport#7691

Merged
biotech77 merged 6 commits intodevfrom
fix/7596-fading-chat
Mar 25, 2026
Merged

fix: resolve chat message fade persisting after teleport#7691
biotech77 merged 6 commits intodevfrom
fix/7596-fading-chat

Conversation

@biotech77
Copy link
Copy Markdown
Contributor

@biotech77 biotech77 commented Mar 20, 2026

Prevent messages fading out if we are not in default chat state

Closes #4272

Pull Request Description

Prevent messages fading out when we teleport

Explanation:

  1. Caller is EventBus - the async continuation from the MVC framework
  2. 39 DOTween tweens actively playing when Kill is called - DOTween is mid-iteration
  3. OnKill DEFERRED - correctly detected, field unchanged after Kill
  4. Frame 5438: deferred OnKill fires, nulls seq#4
  5. killed=False on seq#4 - proof it was never killed, ran full 13s fade

The sequence is still alive inside DOTween's internal update list, but we lost our reference to it (_fadeSequenceTween = null). Without the reference, StopChatEntriesFadeout() cannot call Kill() on it. Setting _fadeSequenceTween to null does NOT stop the tween it only removes our handle to it.

Fix:

  • Remove _fadeSequenceTween = null from OnKill/OnComplete callbacks - callbacks no longer touch the field, so a deferred callback from an old sequence can never corrupt the reference to a newer one
  • Null the field explicitly right after Kill() in Start/Stop methods - the caller manages the lifecycle, not the callback
  • Build the Sequence into a local variable first, then assign to - _fadeSequenceTween after construction - no window where the field holds a partially-built sequence

From logs:

OnMvcViewClosed → PopState frame=5437
  DOTween active tweens: 38
  caller: EventBus

STOP frame=5437: Kill(seq#3 = 2120662738)
  seq IsActive=True IsPlaying=True
  DOTween total playing: 39
  field after Kill: 2120662738
  result: OnKill DEFERRED — field UNCHANGED, callback will fire later

START frame=5437: created seq#4 = -1328791714
>> seq#3 OnKill frame=5438: field points to -1328791714 ← nulls seq#4!

STOP frame=5726: field: null — NOTHING TO KILL ← seq#4 orphaned
>> seq#4 OnComplete frame=6419 (killed=False) ← ran full fade, never killed

Raw and full logs attached
logs_raw.txt
logs_formatted.txt

What does this PR change?

Properly disposes tween sequence

Test Steps

  1. Go to friends panel and teleport to location of a friend
  2. Wait scene to load
  3. Observe if messages are not fading out

Quality Checklist

  • Changes have been tested locally
  • Documentation has been updated (if required)
  • Performance impact has been considered
  • For SDK features: Test scene is included

Code Review Reference

Please review our Code Review Standards before submitting.

@biotech77 biotech77 requested review from a team as code owners March 20, 2026 11:30
@github-actions github-actions Bot requested a review from DafGreco March 20, 2026 11:30
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 20, 2026

Copy link
Copy Markdown

@DafGreco DafGreco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️ PR reviewed and approved by QA on both platforms following instructions playing both happy and un-happy path

Regressions for this ticket had been performed in order to verify that the normal flow is working as expected:

  • [ ✔️] Backpack and wearables in world
  • [✔️ ] Emotes in world and in backpack
  • [✔️ ] Teleport with map/coordinates/Jump In
  • [✔️ ] Chat and multiplayer
  • [ ✔️] Skybox
  • [ ✔️] Settings

Evidence:

20260320-1332-21.2950686.mp4

@dalkia
Copy link
Copy Markdown
Collaborator

dalkia commented Mar 23, 2026

@claude review

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Mar 23, 2026

Claude finished @dalkia's task in 1m 4s —— View job


Claude Code Review

  • Gathering context and reading changed files
  • Analyzing diff and reviewing code
  • Posting review feedback

Review: ChatMessageFeedView.cs

The fix correctly addresses a well-documented DOTween deferred-kill race condition. The three changes work together as a coherent solution:

  1. Null field immediately after Kill() — prevents callbacks from finding a stale reference
  2. Remove null-assignment from OnComplete/OnKill callbacks — deferred callbacks can no longer corrupt the field with a newer sequence's reference
  3. Build sequence in a local variable, then assign — no window where _fadeSequenceTween holds a partially-constructed sequence

One observation (non-blocking, pre-existing)

Dispose() at line 44 does not kill _fadeSequenceTween. If the view is disposed while a fade is in progress, the orphaned DOTween sequence will continue to tick and attempt to mutate a destroyed chatEntriesCanvasGroup. This is a pre-existing issue not introduced by this PR, but worth noting for a follow-up.

public void Dispose()
{
    fadeoutCts.SafeCancelAndDispose();
    _fadeSequenceTween?.Kill();   // missing — pre-existing issue
    _fadeSequenceTween = null;

    if (chatScrollToBottomView != null)
        chatScrollToBottomView.OnClicked -= ChatScrollToBottomToBottomClicked;
}

The fix is minimal, well-reasoned, and QA-verified. No blocking issues found.


REVIEW_RESULT: PASS ✅

Copy link
Copy Markdown
Collaborator

@dalkia dalkia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving due to the urgency of the release, but I do suggest to analyze if it can be done differently, considering the following:

  • Removes code repetition
  • Doesnt rely OnKill and OnComplete. Doesnt look like its needed like these, since you are always killing and setting to 1 the chateEntriesCanvasGroup values
  • Doesnt require the extra seq (Im not sure its needed at all, I still dont understand the window part)
  • Doesnt require nullification of _fadeSequenceTween
        internal void StartChatEntriesFadeout()
        {
            StopChatEntriesFadeout()
            float waitSeconds = chatEntriesWaitBeforeFading / 1000f;

            _fadeSequenceTween = DOTween.Sequence()
                .AppendInterval(waitSeconds)
                .Append(chatEntriesCanvasGroup.DOFade(0.4f, chatEntriesFadeTime))
        }

        internal void StopChatEntriesFadeout()
        {
            _fadeSequenceTween?.Kill();
            chatEntriesCanvasGroup.DOKill();
            chatEntriesCanvasGroup.alpha = 1f;
        }

@biotech77 biotech77 enabled auto-merge (squash) March 23, 2026 14:36
@biotech77 biotech77 disabled auto-merge March 24, 2026 08:38
@DafGreco DafGreco self-requested a review March 25, 2026 08:34
Copy link
Copy Markdown

@DafGreco DafGreco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️ PR reviewed and approved by QA on both platforms following instructions playing both happy and un-happy path

Regressions for this ticket had been performed in order to verify that the normal flow is working as expected:

  • [✔️ ] Backpack and wearables in world
  • [✔️ ] Emotes in world and in backpack
  • [✔️ ] Teleport with map/coordinates/Jump In
  • [✔️ ] Chat and multiplayer
  • [✔️ ] Profile card
  • [✔️ ] Settings

Evidence:

Screen.Recording.2026-03-25.at.08.40.47.mp4

More evidence on the following thread

@biotech77 biotech77 merged commit e9d593e into dev Mar 25, 2026
11 of 13 checks passed
@biotech77 biotech77 deleted the fix/7596-fading-chat branch March 25, 2026 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[QA] Chat | Profile pictures and chat fade while input is focused

4 participants