> For the complete documentation index, see [llms.txt](https://docs.coherence.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.coherence.io/2.3/manual/networking-state-changes/commands.md).

# Commands: invoking methods

Commands are methods that can be invoked through the network, from one CoherenceSync to another CoherenceSync. Functionally equivalent to RPCs, commands bind to **public methods** accessible on the **GameObject** hierarchy that **CoherenceSync** sits on.

This video explains how Commands work when invoked on entities:

{% embed url="<https://youtu.be/Ql2w10nJl80?t=300>" %}

You can expose public methods the same way you select fields for synchronization: through the [Configure window](/2.3/manual/networking-state-changes/configure-window.md) on your **CoherenceSync** component.

<figure><img src="/files/tvpwFaQCwj02pF5hPpVH" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/HMG8XPv1ldtIC3gWfPob" alt=""><figcaption><p>Configure window: Accessible from CoherenceSync Inspector</p></figcaption></figure>

By clicking on the method, you bind to it, defining a command. The grid icon on its right lets you configure the **routing mode**. Commands with a `Send to State Authority Only` mode can be sent only to the state authority of the target CoherenceSync, while ones with the `Send to All Instances` can be broadcasted to all Clients that see it. The routing is enforced by the Replication Server as a security measure, so that outdated or malicious Clients don't break the game.

<figure><img src="/files/MDkA1jdXZoFJnpH2hrZI" alt=""><figcaption><p>Routing mode for a command</p></figcaption></figure>

{% hint style="info" %}
Once commands are added or removed, you must [bake](/2.3/manual/baking-and-code-generation.md) the change&#x73;**.**
{% endhint %}

### Sending a command

To send a command, call the `SendCommand` method on the **target** `CoherenceSync`.

<pre class="language-csharp" data-overflow="wrap"><code class="lang-csharp">private void OnHit()
{
    var sync = GetComponent&#x3C;CoherenceSync>();
<strong>    sync.SendCommand(TakeDamage, MessageTarget.AuthorityOnly);
</strong>}

[Command]
public void TakeDamage()
{
    Debug.Log("Ouch!");
}
</code></pre>

{% hint style="info" %}
If your Networked Prefab has multiple components of the same type binding to the same method, refer to [sending commands to a specific instance](#sending-a-command-to-a-specific-instance).
{% endhint %}

### Command extensions

Aside from the `SendCommand` method, an extension method is generated for every command when baking. This feature is called **command extensions**.

Such methods take a `MessageTarget` as first argument, followed by the rest of arguments the original method defined. So for example, if you bind to `Foo.Bar()`, you will have a new method `Bar(MessageTarget)` that you can call to convert your method into a command. Here's an example of this approach in practice:

<pre class="language-csharp"><code class="lang-csharp">private void OnHit()
{
<strong>    this.TakeDamage(MessageTarget.AuthorityOnly);
</strong>}

[Command]
public void TakeDamage()
{
    Debug.Log("Ouch!");
}
</code></pre>

This approach is not only easier to write, but also easier to read, and additionally, the intent of who to send to (i.e., the target) is clear right away (in this case, self).

{% hint style="warning" %}
The `MessageTarget` specified when sending the command must be compatible with the **routing mode** set in the bindings, i.e. `Send to State Authority Only` will allow only for the `MessageTarget.StateAuthorityOnly` while `Send to Everyone, including yourself` allows any target.

Also, it is possible that the message never sends as in the case of a command with `MessageTarget.Other` sent from the authority with routing of `State Authority Only.`&#x20;
{% endhint %}

### Configuring command extensions

The settings window has a couple of defines that you can set if you want to change how to command extensions work, or completely disable the feature if you wish to avoid the extra generation.

<figure><img src="/files/G4F55uiKikccJJFayx9I" alt=""><figcaption></figcaption></figure>

Stubs are command extensions that do nothing and are generated alongside the real methods. They are there to avoid compilation errors when commands stop existing, so you have a chance to update your game logic without hitting a compilation deadlock. By default, when your code falls back to these stubs, you will be warned through an compiler obsolete message.

### Sending a command to a specific instance

Command extensions are always explicit about who is the target, so this section only applies to `SendCommand`.

If you have the same command bound more than once in the same Prefab hierarchy, you can target a specific Component when sending a message, via the `SendCommand(Component target)` or `SendCommand(Action action)` overloads. When using the overload that takes an action, it can infer the Component instance associated with it, so you can do `SendCommand(myPlayerRef.TakeDamage)`.

Additionally, if you want to target every component in the hierarchy, you can do so via `SendCommandToChildren`.

### Ordering of commands

By default commands don't have any order. In other words, commands might be received by other Clients in a completely different order than they were sent.

If the order of commands is crucial, use `SendOrderedCommand` instead of `SendCommand`. This guarantees that any given ordered command will be received by other Clients in the same order in which it was sent from the source Client, relative to other sent ordered commands by that Client.

{% hint style="info" %}
Note that ordered commands are not ordered relative to entity creation/destruction or binding updates. They are ordered only relative to other ordered commands.
{% endhint %}

Sending commands as ordered should be used only where necessary, since each ordered command slightly increases bandwidth and latency in case of bad network conditions.

### Receiving a command

We don't have to do anything special to receive the command. The system will simply call the corresponding method on the target network entity.

If the target is a locally simulated entity, `SendCommand` will recognize that and not send a network command, but instead simply call the method directly.

### Command Meta

Commands can carry metadata that provides additional context about when and by whom the command was sent. This is controlled by using `[Command(UseMeta = true)]`.

Command metadata includes:

* **Frame**: The frame number when the command was sent
* **Sender**: The ID of the client that sent the command

#### Enabling Command Meta

To enable metadata for a command, add the `UseMeta = true` parameter to the `[Command]` attribute:

```csharp
[Command(UseMeta = true)]
public void CommandWithMeta()
{
    // Access metadata here
}
```

#### Accessing Command Meta

There are two ways to access command metadata:

**Using CurrentCommandMeta (direct access):**

```csharp
[Command(UseMeta = true)]
public void CommandWithMeta()
{
    var meta = CoherenceSync.CurrentCommandMeta;
    Debug.Log($"Command sent at frame: {meta.Frame}");
    Debug.Log($"Sent by client: {meta.Sender}");
}
```

{% hint style="warning" %}
**Important**: Accessing `CurrentCommandMeta` can throw an exception if accessed outside of a command's context or if 'UseMeta' has not been set to true.
{% endhint %}

**Using TryGetCurrentCommandMeta (safe access):**

```csharp
[Command(UseMeta = true)]
public void CommandWithMetaAndData(string data, int value)
{
    if (CoherenceSync.TryGetCurrentCommandMeta(out var meta))
    {
        Debug.Log($"Command sent at frame: {meta.Frame}");
        Debug.Log($"Sent by client: {meta.Sender}");
        Debug.Log($"Data: {data}, Value: {value}");
    }
}
```

Both methods can be used for commands with or without parameters. The key difference is that `CurrentCommandMeta` provides direct access but can throw exceptions, while `TryGetCurrentCommandMeta` is the safer option that returns a boolean indicating success.

#### When to Use Command Meta

Command meta is useful when you need to:

* Track the timing of command execution for gameplay synchronization
* Identify which client sent a command for security or gameplay purposes
* Implement frame-based game logic that depends on command timing
* Debug network command flow

{% hint style="info" %}
**Performance Note**: Enabling metadata adds a small overhead to command transmission. Only enable it for commands where timing or sender information is actually needed.
{% endhint %}

### Sending a command to multiple CoherenceSyncs

Sometimes you want to inform a bunch of different CoherenceSyncs about a change. For example, an explosion impact on a few players. To do so, we have to go through the instances we want to notify and send commands to each of them.

```csharp
using Coherence;
using Coherence.Toolkit;
using UnityEngine;

public class MyCommands : MonoBehaviour
{
    public void MulticastCommand()
    {
        var self = GetComponent<CoherenceSync>();
        var listeners = FindObjectsByType<CoherenceSync>(); 
        
        foreach (var listener in listeners)
        {
            if (!listener || listener == self)
            {
                continue;
            }
            
            listener.SendCommand<MyCommands>(nameof(ReceiveCommand), 
                MessageTarget.StateAuthorityOnly);
        }
    }

    // bind to this method via the Bindings window
    public void ReceiveCommand()
    {
        Debug.Log("Received!");
    }
}
```

In this example, a command will get sent to each CoherenceSync under the state authority of this Client. To make it only affect CoherenceSyncs within certain criteria, you need to filter to which CoherenceSync you send the command to, on your own.

### Sending null values in command arguments

Some of the primitive types supported are nullable values, this includes:

* Byte\[]
* string
* Entity references: CoherenceSync, Transform, and GameObject

{% hint style="info" %}
Refer to the [supported types](/2.3/manual/networking-state-changes/supported-types.md) page.
{% endhint %}

In order to send one of these values as a null (or default) we need to use special syntax to ensure the right method signature is resolved.

```csharp
using Coherence;
using Coherence.Toolkit;
using UnityEngine;
using System;

public class MyCommand : MonoBehaviour
{
    private CoherenceSync sync;

    public void MyNullableCommand(string someString, Byte[] someArray)
    {
        if (!string.IsNullOrEmpty(someString)) //Could be null or string.Empty
        {
            // Do something with the string
        }

        if (someArray != null && someArray.Length > 0) //Could be null or Byte[0]
        {
            // Do something with the array
        }
    }

    public void SendNullableCommand()
    {
        sync.SendCommand<MyCommand>(nameof(MyNullableCommand),
            MessageTarget.All,
            (typeof(string), (string)null),
            (typeof(Byte[]), (Byte[])null));
    }
}
```

Null-value arguments need to be passed as a ValueTuple\<Type, object> so that their type can be correctly resolved. In the example above sending a null value for a string is written as:\
\
`(typeof(string), (string)null)`

and the null Byte\[] argument is written as:\
\
`(typeof(Byte[]), (Byte[])null)`

Mis-ordered arguments, type mis-match, or unresolvable types will result in errors logged and the command not being sent.

{% hint style="info" %}
When a null argument is deserialized on a client receiving the command, it is possible that the null value is converted into a non-null default value. For example, sending a null string in a command could result in clients receiving an empty string. As another example, a null Byte\[] argument could be deserialized into an empty Byte\[0] array. So, receiving code should be ready for either a null value or an equivalent default.
{% endhint %}

### Limitations

When a Client receives a command targeted at `StateAuthorityOnly` but it has already transferred an authority of that entity, the command is simply discarded.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.coherence.io/2.3/manual/networking-state-changes/commands.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
