Skip to content

Conversation

andybak
Copy link
Contributor

@andybak andybak commented May 16, 2025

Problem - some commands fire every frame and flood the network in multiplayer.

How to reproduce: Before joining a room, switch to advanced mode, add an image then switch back to beginner mode and create/join a room. Moving the widget will send the "move widget" RPC every single frame.

Cause: The current code assumes that adding a command to the undo stack is a sign that it should be sent over the network. However some command subclasses work as follows - each command is executed and added to the stack. The next command looks at the previous command and decides if it can merge with it. In the case of MoveWidgetCommand this is true until m_IsFinal is set to true (usually when the widget is released).

The original PhotonManager code has a switch/case that has a default fall-through for commands that aren't handled explicitly. I haven't removed this in this PR as I would need to figure out all possible commands that we currently want to handle and add a case statement for them all. However - I think this is probably a better approach as we shouldn't be broadcasting commands without carefully looking at their behaviour.

This PR does hopefully fix the specific MoveWidgetCommand case. Currently not tested but I'm posting it to start the discussion and get a couple of eyeballs on it.

@andybak andybak requested review from mikeskydev and sbanca May 16, 2025 08:15
@mikeage mikeage added the bugfix Something has been fixed label May 29, 2025
@andybak andybak requested a review from Copilot September 4, 2025 13:09
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes a performance issue where MoveWidgetCommand was being broadcast over the network every frame during widget movement in multiplayer mode, causing network flooding. The solution adds conditional broadcasting logic to only send the command when it's finalized.

  • Added a public IsFinal property to MoveWidgetCommand to expose the internal final state
  • Modified PhotonManager to only broadcast MoveWidgetCommand when IsFinal is true
  • Added clarifying comments to the command merging logic in SketchMemoryScript

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
Assets/Scripts/Commands/MoveWidgetCommand.cs Exposes the final state through a public IsFinal property
Assets/Scripts/Multiplayer/Photon/PhotonManager.cs Adds conditional logic to only broadcast MoveWidgetCommand when final
Assets/Scripts/SketchMemoryScript.cs Adds clarifying comments to existing command merging logic

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +439 to +444
case MoveWidgetCommand:
var cmd = command as MoveWidgetCommand;
if (cmd.IsFinal)
{
success &= CommandBase(command);
}
Copy link
Preview

Copilot AI Sep 4, 2025

Choose a reason for hiding this comment

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

When cmd.IsFinal is false, the method continues without setting success, but the return value of ProcessCommand depends on success. This could lead to incorrect return values when non-final MoveWidgetCommands are processed. Consider explicitly setting success = true in the else case or restructuring the logic to handle this scenario properly.

Suggested change
case MoveWidgetCommand:
var cmd = command as MoveWidgetCommand;
if (cmd.IsFinal)
{
success &= CommandBase(command);
}
}
else
{
success = true;
}

Copilot uses AI. Check for mistakes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugfix Something has been fixed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants