# Custom Serializers

When creating a custom serializer there are a few important things to remember. When you follow the proper steps your custom serializer will be found and used by Fish-Networking. Your custom serializers can also override automatic serializers, but not included ones.

* [x] Your method must be static, and within a static class.
* [x] Writing method names must begin with *Write*.
* [x] Reading method names must begin with *Read*.
* [x] The first parameter must be *this Writer* for writers, and *this Reader* for readers.
* [x] Data must be read in the same order it is written.

Although *Vector2* is already supported, the example below uses a Vector2 for simplicity sake.

```csharp
// Write each axis of a Vector2.
public static void WriteVector2(this Writer writer, Vector2 value)
{
    writer.WriteSingle(value.x);
    writer.WriteSingle(value.y);
}

// Read and return a Vector2.
public static Vector2 ReadVector2(this Reader reader)
{
    return new Vector2()
    {
        x = reader.ReadSingle(),
        y = reader.ReadSingle()
    };
}
```

Custom serializers are more commonly used for conditional situations where what you write may change depending on the data values. Here is a more complex example where certain data is only written when it's needed.

```csharp
/* This is the type we are going to write.
* We will save data and populate default values
* by not writing energy/energy regeneration if
* the enemy does not have energy. */
public struct Enemy
{
    public bool HasEnergy;
    public float Health;
    public float Energy;
    public float EnergyRegeneration;
}

public static void WriteEnemy(this Writer writer, Enemy value)
{
    writer.WriteBoolean(value.HasEnergy);
    writer.WriteSingle(value.Health);
    
    // Only need to write energy and energy regeneration if HasEnergy is true.
    if (value.HasEnergy)
    {
        writer.WriteSingle(value.Energy);
        writer.WriteSingle(value.EnergyRenegeration);
    }
}

public static Enemy ReadEnemy(this Reader reader)
{
    Enemy e = new Enemy();
    e.HasEnergy = reader.ReadBoolean();
    e.Health = reader.ReadSingle();
    
    // If there is energy also read energy values.
    if (e.HasEnergy)
    {
        e.Energy = reader.ReadSingle();
        e.EnergyRenegeration = reader.ReadSingle();
    }

    return e;
}
```

Often when creating a custom serializer you want to use it across your entire project, and all assemblies. Without taking any action further your custom serializer would **only be used on the assembly it is written.** Presumably, that's probably not what you want.

But making a custom serializer work across all assemblies is very simple. Simply add the \[UseGlobalCustomSerializer] attribute of the type your custom serializer is for, and done!

Example:

```csharp
[UseGlobalCustomSerializer]
public struct Enemy
{
    public bool HasEnergy;
    public float Health;
    public float Energy;
    public float EnergyRegeneration;
}
```


---

# Agent Instructions: 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://fish-networking.gitbook.io/docs/guides/features/data-serialization/custom-serializers-guides.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.
