Search Unity

Unity Multiplayer Custom serialization and SetDirtyBit

Discussion in 'Connected Games' started by glitchers, Jul 23, 2015.

  1. glitchers

    glitchers

    Joined:
    Apr 29, 2014
    Posts:
    52
    Hi,

    I've been trying to find some information about dirty bit in regards to custom serialization. As far as I can tell SetDirtyBit works only if you use SyncVars.

    Am I missing something or should I implement this myself?

    Thank you
     
  2. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
  3. glitchers

    glitchers

    Joined:
    Apr 29, 2014
    Posts:
    52
    I have read that page from the manual, I was looking for some clarification on it's implementation when not using SyncVars.

    From what I understand, every NetworkBehaviour has syncVarDirtyBits, but only if you use SyncVars it is written to automatically.

    Am I able to use it as my custom dirty bit mask or will it's value be overwritten automatically?
     
  4. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    SyncVar accessor properties write to the dirty mask, and it is set to zero after an update is sent. Those are the only built-in interactions.
     
    glitchers likes this.
  5. Mr-Slat

    Mr-Slat

    Joined:
    Jan 25, 2013
    Posts:
    2
    For anyone with this problem here go's a solution. It's kinda bad but it works (NOTE : Haven't tested the code but it should work. If you have any problems just comment and i'll fix it) :

    Code (CSharp):
    1.  
    2. public class Player : NetworkBehaviour
    3. {
    4.     public delegate void PlayerEventHandler(Player sender);
    5.  
    6.     public event PlayerEventHandler  OnCanBeDamagedChanged,
    7.                                                           OnCanBeHealedChanged,
    8.                                                           OnCanBeRevivedChanged;
    9.  
    10.     public bool canBeDamaged = true;
    11.     public bool canBeHealed = true;
    12.     public bool canBeRevived = true;
    13.  
    14.     public const uint BIT_CANBEDAMAGED = 1u,
    15.                                BIT_CANBEHEALED = 2u,
    16.                                BIT_CANBEREVIVED = 4u; //It has to power o 2 (i.e : 8, 16, 32, 64, 128 etc...)
    17.  
    18.     protected virtual void Start()
    19.     {
    20.         OnCanBeDamagedChanged += OnCanBeDamagedHasChanged;
    21.         OnCanBeHealedChanged += OnCanBeHealedHasChanged;
    22.         OnCanBeRevivedChanged += OnCanBeRevivedHasChanged;
    23.     }
    24.  
    25.     protected virtual void OnDestroy()
    26.     {
    27.         OnCanBeDamagedChanged -= OnCanBeDamagedHasChanged;
    28.         OnCanBeHealedChanged -= OnCanBeHealedHasChanged;
    29.         OnCanBeRevivedChanged -= OnCanBeRevivedHasChanged;
    30.     }
    31.  
    32.     //Press A to change canBeDamaged value
    33.     [ServerCallback]
    34.     protected virtual void Update()
    35.     {
    36.         if (Input.GetKeyDown(KeyCode.A))
    37.             CanBeDamaged = !canBeDamaged;
    38.     }
    39.  
    40.    public override bool OnSerialize(NetworkWriter writer, bool initialState)
    41.     {
    42.         bool e = base.OnSerialize(writer, initialState);
    43.         if (initialState)
    44.         {
    45.             writer.Write(canBeDamaged);
    46.             writer.Write(canBeHealed);
    47.             writer.Write(canBeRevived);
    48.  
    49.             return true;
    50.         }
    51.  
    52.         writer.Write(syncVarDirtyBits);
    53.  
    54.         bool wroteSyncVar = false;  
    55.  
    56.         if ((syncVarDirtyBits & BIT_CANBEDAMAGED) != 0u)
    57.         {
    58.             wroteSyncVar = true;
    59.             writer.Write(canBeDamaged);
    60.         }
    61.  
    62.         if ((syncVarDirtyBits & BIT_CANBEHEALED) != 0u)
    63.         {
    64.             wroteSyncVar = true;
    65.             writer.Write(canBeHealed);
    66.         }
    67.  
    68.         if ((syncVarDirtyBits & BIT_CANBEREVIVED) != 0u)
    69.         {
    70.             wroteSyncVar = true;
    71.             writer.Write(canBeRevived);
    72.         }
    73.  
    74.         return e || wroteSyncVar;
    75.     }
    76.  
    77.     public override void OnDeserialize(NetworkReader reader, bool initialState)
    78.     {
    79.         base.OnDeserialize(reader, initialState);
    80.  
    81.         if (initialState)
    82.         {
    83.              canBeDamaged = reader.ReadBoolean();
    84.              canBeHealed     = reader.ReadBoolean();
    85.              canBeRevived   = reader.ReadBoolean();
    86.  
    87.              return;
    88.         }
    89.  
    90.          uint _syncVarDirtyBits = reader.ReadUint32();
    91.  
    92.          if ((_syncVarDirtyBits & BIT_CANBEDAMAGED) != 0u)
    93.          {
    94.              canBeDamaged = reader.ReadBoolean();
    95.              if (OnCanBeDamagedChanged != null)
    96.                  OnCanBeDamagedChanged(this);
    97.          }
    98.  
    99.          if ((_syncVarDirtyBits & BIT_CANBEHEALED) != 0u)
    100.          {
    101.              canBeHealed = reader.ReadBoolean();
    102.              if (OnCanBeHealedChanged != null)
    103.                  OnCanBeHealedChanged(this);
    104.          }
    105.  
    106.          if ((_syncVarDirtyBits & BIT_CANBEREVIVED) != 0u)
    107.          {
    108.              canBeRevived = reader.ReadBoolean();
    109.              if (OnCanBeRevivedChanged != null)
    110.                  OnCanBeRevivedChanged(this);
    111.          }
    112.     }
    113.  
    114.     protected virtual void OnCanBeDamagedHasChanged()
    115.     {
    116.         //Code for logic when can be damaged
    117.         //changes
    118.         Debug.Log("Player : " + gameObject.name + ", can be damaged has been changed to " + canBeDamaged.ToString());
    119.     }
    120.  
    121.     protected virtual void OnCanBeHealedHasChanged()
    122.     {
    123.         //Code for logic when can be healed
    124.         //changes
    125.         Debug.Log("Player : " + gameObject.name + ", can be healedhas been changed to " + canBeHealed.ToString());
    126.     }
    127.  
    128.     protected virtual void OnCanBeRevivedHasChanged()
    129.     {
    130.         //Code for logic when can be revived
    131.         //changes
    132.         Debug.Log("Player : " + gameObject.name + ", can be revived has been changed to " + canBeRevived.ToString());
    133.     }
    134.  
    135.     //Use this implementation to make this NetworkBehaviour
    136.     //send a new update if canbeDamaged changes
    137.     //(NOTE : The "set" implementation should run on the Server)
    138.     public bool CanBeDamaged
    139.     {
    140.         get { return canBeDamaged; }
    141.  
    142.         set
    143.         {
    144.             if (canBeDamaged == value)
    145.                 return;
    146.  
    147.             canBeDamaged = value;
    148.  
    149.             if (isServer)
    150.                 SetDirtyBit(BIT_CANBEDAMAGED);
    151.  
    152.             if (OnCanBeDamagedChanged != null)
    153.                 OnCanBeDamagedChanged(this);
    154.         }
    155.     }
    156.     public bool CanBeHealed
    157.     {
    158.         get { return canBeHealed; }
    159.  
    160.         set
    161.         {
    162.             if (canBeHealed == value)
    163.                 return;
    164.  
    165.             canBeHealed = value;
    166.  
    167.             if (isServer)
    168.                 SetDirtyBit(BIT_CANBEHEALED);
    169.  
    170.             if (OnCanBeHealedChanged != null)
    171.                 OnCanBeHealedChanged(this);
    172.         }
    173.     }
    174.     public bool CanBeRevived
    175.     {
    176.         get { return canBeRevived; }
    177.  
    178.         set
    179.         {
    180.             if (canBeRevived == value)
    181.                 return;
    182.  
    183.             canBeRevived = value;
    184.  
    185.             if (isServer)
    186.                 SetDirtyBit(BIT_CANBEREVIVED);
    187.  
    188.             if (OnCanBeRevivedChanged != null)
    189.                 OnCanBeRevivedChanged(this);
    190.         }
    191.     }
    192. }
    When you set "CanBeDamaged", to a different value, then it will make the NetworkBehaviour send a new update, forcing it to serialize.

    if you want to listen player canBeDamaged from outside the Player class then use the event :

    something like :

    Code (CSharp):
    1.  
    2. public class Test : MonoBehaviour
    3. {
    4.     private Player player;
    5.  
    6.     private void Start()
    7.     {
    8.         player = GameObject.FindObjectOfType<Player>();
    9.  
    10.         if (player != null)
    11.         {
    12.             //Assigning Player OnCanBeDamagedChanged event
    13.             player.OnCanBeDamagedChanged += OnPlayerCanBeDamagedChanged;
    14.         }
    15.     }
    16.  
    17.     private void OnDestroy()
    18.     {
    19.         if (player != null)
    20.         {
    21.             player.OnCanBeDamagedChanged -= OnPlayerCanBeDamagedChanged;
    22.             player = null;
    23.         }
    24.     }
    25.  
    26.     private void OnPlayerCanBeDamagedChanged(Player sender)
    27.     {
    28.         //Code when player can be damaged changes.
    29.         Debug.Log("Player Can Be Damaged = " + sender.canBeDamaged.ToString());
    30.     }
    31. }
    32.  
    (NOTE : For OnSerialize to work properly you can't have any SyncVar fields. The Documentation explains it further :
    "...If a class has SyncVars, then an implementation of this function and OnDeserialize() are added automatically to the class. So a class that has SyncVars cannot also have custom serialization functions…" From : https://docs.unity3d.com/ScriptReference/Networking.NetworkBehaviour.OnSerialize.html )

    Hope this helps.
     
    Last edited: Nov 19, 2018