# \[Sync] and \[Command] Attributes

Aside from configuring your CoherenceSync bindings from within the *Configure* window, it's possible to use the `[Sync]` and `[Command]` C# attributes directly on your scripts. Your Prefabs will get updated to **require** such bindings.

## Sync Attribute

Mark **public** fields and properties to be synchronized over the network.

```csharp
[Sync]
public int health;
```

It's possible to migrate the variable automatically, if you decide to change its definition:

```csharp
[Sync("health")]
public float hp;
```

If a variable is never updated after it is first initialized, it can be flagged to only be synchronized when the GameObject is created. This will improve performance, as **coherence** won't need to continually sample its value for changes like it would normally do.

```csharp
[Sync(DefaultSyncMode = SyncMode.CreationOnly)]
public Color teamColor;
```

### SyncMode.Manual

For fine-grained control over when a variable is synchronized, you can use `SyncMode.Manual`. In this mode, the variable will only be sent over the network when you explicitly call `MarkForSyncing()` on the binding. This is useful for values that change infrequently or only in response to specific events.

{% hint style="info" %}
`SyncMode.Always` is already quite efficient, only performing a lightweight comparison when the binding is ready to sample. In most cases, the default automatic synchronization is sufficient. Consider using `SyncMode.Manual` only when profiling reveals that specific bindings are causing performance issues, or when you have domain knowledge that a value changes very infrequently.
{% endhint %}

```csharp
[Sync(DefaultSyncMode = SyncMode.Manual)]
public byte[] playerSettings;

private CoherenceSync coherenceSync;
private ValueBinding<byte[]> settingsBinding;

private void Awake()
{
    coherenceSync = GetComponent<CoherenceSync>();
    settingsBinding = coherenceSync.GetValueBinding<Player, byte[]>(nameof(playerSettings));
}

public void UpdateSettings(byte[] newSettings)
{
    playerSettings = newSettings;

    // Manually trigger synchronization when settings change
    settingsBinding.MarkForSyncing();
}
```

{% hint style="info" %}
When using `SyncMode.Manual`, it's recommended to disable interpolation on the binding as irregular updates can result in visual artifacts.
{% endhint %}

{% hint style="warning" %}
Be careful not to call `MarkForSyncing()` every frame, as this can result in a much higher sending rate than the default 20Hz sampling rate, leading to excessive bandwidth usage. Only mark bindings for syncing when the value actually changes in a meaningful way.
{% endhint %}

### Switching SyncMode at Runtime

You can change a binding's `SyncMode` at runtime to adapt to different gameplay scenarios. For example, you might want continuous synchronization during active gameplay but manual synchronization during idle periods.

```csharp
[Sync]
public Vector3 targetPosition;

private CoherenceSync coherenceSync;
private ValueBinding<Vector3> targetPositionBinding;

private void Awake()
{
    coherenceSync = GetComponent<CoherenceSync>();
    targetPositionBinding = coherenceSync.GetValueBinding<NetworkedObject, Vector3>(nameof(targetPosition));
}

public void EnableContinuousSync()
{
    // Switch to automatic continuous synchronization
    targetPositionBinding.SyncMode = SyncMode.Always;
}

public void EnableManualSync()
{
    // Switch to manual synchronization for fine-grained control
    targetPositionBinding.SyncMode = SyncMode.Manual;
}

public void UpdateTargetPosition(Vector3 newPosition)
{
    targetPosition = newPosition;

    // Only sync if in manual mode
    if (targetPositionBinding.SyncMode == SyncMode.Manual)
    {
        targetPositionBinding.MarkForSyncing();
    }
}
```

## Command Attribute

Mark **public** methods to be invoked over the network. Method return type must be `void`.

```csharp
[Command]
public void Heal(int amount)
{
    ...
}
```

It's possible to migrate the command automatically, if you decide to change the method signature:

```csharp
[Command("Heal", typeof(int))]
public void IncreaseHp(float hp)
{
    ...
}
```

### Command Meta

Commands can include metadata by setting `UseMeta = true`. This allows access to timing and sender information:

```csharp
[Command(UseMeta = true)]
public void CommandWithMeta()
{
    if (CoherenceSync.TryGetCurrentCommandMeta(out var meta))
    {
        // Access frame timing and sender information
        Debug.Log($"Frame: {meta.Frame}, Sender: {meta.Sender}");
    }
}
```

For more details on using command metadata, see [Command Meta](https://docs.coherence.io/manual/commands#command-meta).

{% hint style="warning" %}
Note that **marking** a command attribute only marks it as programmatically usable. It does not mean it will be automatically called over the network when executed.

You still need to follow the guidelines in the [Messaging with Commands](https://docs.coherence.io/manual/networking-state-changes/commands) article to make it work.
{% endhint %}
