Will the logic inside a synced property run on the owner or the caller?

Suppose I have the following synced property:

[Sync] public int Health {
        get {
            int health = SaveFile.GetHealth();
            return num;
        }
    }

Will the logic inside the property (in this case SaveFile.GetHealth()) run on the device that calls the property? or on the device that owns the script’s gameobject? I would like to understand better how coherence treats properties.

1 Like

Hi @codya !

Yes, coherence will call this getter in both clients that own the entity and clients that don’t.

When the client owns the entity, coherence will query the Health value to send it over the network, and for that we have to call the getter.

In clients that don’t own the entity, we still have to call it for interpolation purposes (if the property is using interpolation).

In the case of setters, it will be called in clients that don’t own the entity, to write the new value when it is updated over the network,

Hope that helps!

1 Like

I never want to call the getter logic in any device other than the owner. I want the other devices to only “see” the return value of the getter. I guess I only need to disable interpolation for this property, right? However, in that case, how are other clients able to get the property without running the getter logic?

By the way, I realized that the code above will not work unless I add a setter too.

Hard to tell what to advice here without having more context.

In the piece of code you shared, you’re fetching a int health value from SaveFile.GetHealth, but then you’re returning num.

Why is it necessary to call SaveFile.GetHealth here?

A getter is generally a place where you query a fields value, not a place where you perform any business logic since that might lead to bugs down the line due to unexpected behaviour.

Unfortunately coherence needs access to the fields you want to sync, i’m afraid thats something you will not be able to work around.

Apologies for not giving you proper context. This is the true code:

int _wantedPrice;
  [Sync] public int WantedPrice {
      get {
          _wantedPrice = SaveSystem.GetWantedPrice(); // Gets the player's wanted price from their save file
          return _wantedPrice;
      } set {
          _wantedPrice = value;
      }
  }

Each player has a Wanted Price (bounty) stored in their save file. The Police AI (which exists in the simulator) will try to check the “Wanted Price” property in order to decide whether to try to capture the player or leave them alone. As expected, I would not want the logic SaveSystem.GetWantedPrice() to run on the simulator, it should only run on the player’s device that has the save file.
My question is that: in my code, how do I make sure that SaveSystem.GetWantedPrice() will only run on the device that owns the object?
Please let me know if you need more context.

Personally I’d remove the GetWantedPrice call from this getter and use something like an observer to update the value.

Rough pseudocode:

int _wantedPrice;
  [Sync] public int WantedPrice {
      get => _wantedPrice;
      set => _wantedPrice = value;
  }

void Awake()
{
      // We listen for wanted price changes if we are the authority of the object
      if (_coherenceSync.HasStateAuthority){
              SaveFile.OnWantedPriceChanged += OnWantedPriceChanged;
              // Initialize the value
              _wantedPrice = SaveSystem.GetWantedPrice();
      }
}

void OnWantedPriceChanged(int newPrice)
{
       _wantedPrice = newPrice;
}
1 Like

Got it, thanks!

1 Like