Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How to intentionally drop or flush the message queue when receiving "no free events for message"?

Discussion in 'Multiplayer' started by asperatology, Feb 5, 2016.

  1. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    Whenever I do something to call on a Command or something, I would get large amounts of "no free events for message" warnings in the Console.

    I know there are ways I can do to reduce this happening often by:
    • Increasing the value in the "config.fragmentsize".
    • Increasing the value in the "config.MaxSentMessageQueueSize"
    • Decreasing the speed of how fast I'm sending out messages.
    But point taken, it doesn't answer this question:

    How do you flush / clear away / drop the message queue waiting to be sent, so it doesn't clutter the Console tab view and stop repeating to send the "blocked or affected" messages to the server?

    It would be nice to know about this.

    In my game, I used an object pool that sends a message to the server saying the client has ordered a list of player units to "produce" resource. This object pool sorts and filters the waiting list, and puts the "handled" units to the end of the list, kind of like an ever-sorting priority queue. And by design, the game handles them so fast, which is what I wanted, that these messages would appear if they are handled too quick. But this happens rarely. And when it does happen, it slows down the Unity editor, which I use to debug/test the game, and fills up the Console view tab constantly.

    It fills it up even when it's marked to collapse the messages, and would keeping sending useless queued messages non-stop. By useless, I mean when you double click on the messages, nothing would respond and point Visual Studio to some arbitrary line of codes that makes it happen, or would show codes with many type safe checks already placed.

    Maybe I should change it back to "Unreliable" in the Network Manager... but then it could have a different and annoying quirk, such as outputting many "Send Error..." error messages.
     
    Last edited: Feb 5, 2016
  2. Whippets

    Whippets

    Joined:
    Feb 28, 2013
    Posts:
    1,775
    How many messages are you sending or receiving per second to receive this error, and how big are these messages?
     
  3. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    I'm not sure where to look up the size of these messages. I only know it is possible to change those values, but I don't know where to do so.

    The sending and receiving per second is very dependent on players. When playtesting, some players would slowly trudge along (not a lot of messages), while others would mass spam actions (you know what happens next).
     
  4. Whippets

    Whippets

    Joined:
    Feb 28, 2013
    Posts:
    1,775
    there should be no spamming. Messages should be sent on a tick of 5 or 10 times a second. any more than that and you are going to suffer with blockages. What are you spamming? character movement?
     
  5. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    A simple Command function that sets a SyncVar variable to either null or some GameObject. And that is it.

    I only know the standard way of using Commands is to send simple things, and let the client handle the heavy working.

    EDIT:

    Wait, if I call on CmdSetTargetEnemy(), it would cause problems?

    Code (CSharp):
    1.         [Command]
    2.         public void CmdSetTargetEnemy(GameObject obj, GameObject enemy, GameObject attackee) {
    3.             RpcSetTargetEnemy(obj, enemy, attackee);
    4.         }
    5.  
    6.         [ClientRpc]
    7.         public void RpcSetTargetEnemy(GameObject attacker, GameObject enemyInLineOfSight, GameObject victimInAttackRange) {
    8.             if (attacker != null && (enemyInLineOfSight != null || victimInAttackRange != null)) {
    9.                 GameUnit unit = attacker.GetComponent<GameUnit>();
    10.                 if (unit != null) {
    11.                     if (victimInAttackRange != null && attacker.Equals(enemyInLineOfSight) && attacker.Equals(victimInAttackRange)) {
    12.                         unit.targetEnemy = null;
    13.                     }
    14.                     else {
    15.                         if (victimInAttackRange != null) {
    16.                             unit.targetEnemy = victimInAttackRange.GetComponent<GameUnit>();
    17.                             MoveToTarget(attacker);
    18.                         }
    19.                         else if (enemyInLineOfSight != null) {
    20.                             unit.targetEnemy = enemyInLineOfSight.GetComponent<GameUnit>();
    21.                             MoveToTarget(attacker);
    22.                         }
    23.                         else {
    24.                             unit.targetEnemy = null;
    25.                         }
    26.                     }
    27.                 }
    28.             }
    29.         }
     
  6. Whippets

    Whippets

    Joined:
    Feb 28, 2013
    Posts:
    1,775
    Well you'd only need to call that upon a target change. That's not spamming, and probably not called very often. It certainly shouldn't cause any errors like the one you are getting. Movement is going to be your worst enemy, not changing target.
     
  7. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    This is why I'm looking into finding ways to flush the message queue, because it doesn't make sense at all. I couldn't see why it's happening though.
     
  8. Whippets

    Whippets

    Joined:
    Feb 28, 2013
    Posts:
    1,775
    If you're really not sending many messages per second, flag it up as a bug
     
  9. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    I still need to create a test project for that before submitting it. At the moment, I can't tell if it's because of player actions that's causing it, or it's the Unity engine doing it. Also, I can't be sure what's causing it, so investigation is still undergoing.
     
  10. Ashkan_gc

    Ashkan_gc

    Joined:
    Aug 12, 2009
    Posts:
    1,117
    There is a method with the word Flush in NetworkConnection and maybe NetworkServer and NetworkClient as well but you should not use it unless uNet is delaying sending messages and you want to send them faster,

    You should find out which messages are being sent too much and cause this.

    I had the problem and stopped sending movement commands every frame and made it 20 times a second and it fixed it.
     
  11. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    Still investigating. I'm actually at a loss as to where I can find a lead.

    It was the Command function given above. That's it.

    I only give movement command updates only when the player clicks on the playing field, as in it could be more than 5 seconds before a movement command is ordered.
     
  12. Ashkan_gc

    Ashkan_gc

    Joined:
    Aug 12, 2009
    Posts:
    1,117
    Maybe try sending it over a FragmentedReliable channel instead of default reliable channel, maybe a batch of them becomes so big and causes this.