新增FishNet文档

This commit is contained in:
2026-09-20 15:53:11 +08:00
parent c403145db9
commit 179c282405
431 changed files with 15476 additions and 0 deletions
@@ -0,0 +1,135 @@
# Features
{% hint style="warning" %}
For a more exact feature comparison of various networking solutions please see this [comparison chart](https://docs.google.com/spreadsheets/d/1Bj5uLdnxZYlJykBg3Qd9BNOtvE8sp1ZQ4EgX1sI0RFA/).
{% endhint %}
Performance and reliability are very important to us, but so is including great features to make your experience easier, and better. The last thing we want to do is create limitations; we support all features Mirror does, and then some.
Below is a comparison of unique and enhanced features, with more to come.
## Features unique to Fish-Networking
> **Update Stability**
>
> Other solutions do not guarantee that their API will not change between releases, making it difficult and dangerous to update for fixes or features. Fish-Networking prides itself on its [No-Break Promise](../../../#no-break-promise), ensuring updates do not require alteration of user code, keeping you on-top with the best to offer.
> **Built-in Addressables Support**
>
> Unlike other networking solutions, Fish-Networking has addressables support included within core features. Addressable scenes are easily implemented with our network SceneManager, and addressable prefabs are supported as well.
> **Network Balancing**
>
> NetworkManagers are the center of your network environment. They contain other managers, and handle communications between the client and server. Fish-Networking allows an infinite number of NetworkManagers, allowing clients at once to connect to multiple different servers, to have each handle certain tasks or worlds. Various NetworkManagers may also be used to fit different game modes, transports, platforms, and a number of other tasks.
> **Local Remote Calls**
>
> Fish-Networking allows remote calls to run not only on their intended destination, but also on the caller as well. Typically, you would have to copy logic into multiple methods to accomplish such a task, but Fish-Networking allows it to be done in one method. This drastically reduces potential errors in code, lines of code, and improves ease of use.
> **Multi-purpose Remote Calls**
>
> Target and Observers remote calls can be used interchangeable, in the same method. This allows you to use a single method to send data to one client or multiple clients. Like _**Local Remote Calls**_, this creates a more reliable code-base and improves the user experience.
> **Buffered Remote Calls**
>
> Often the last value of a remote call must be sent to newly joined clients. Fish-Networking is one of few solutions that offer this ability.
> **Client-side Prediction**
>
> Client-side prediction primarily focuses on ensuring players in your game cannot cheat a variety of movement types. This feature is an absolute must for any competitive game.
>
> Fish-Networking is the only free solution to provide built-in client-side prediction with only a few lines of code. Also, included are a variety of components for desynchronization smoothing, and rigidbody prediction.
> **Lag Compensation (pro feature)**
>
> Another very important feature for precision-based gaming is lag compensation. This is the act of rolling back colliders in time to where a client had seen them; this ensures accurate hit registration. This technique is applicable to several genre types but is most commonly seen in shooter games.
> **Automatic Code Stripping (pro feature)**
>
> Code stripping helps protect your game server by removing sensitive logic that the player should not be aware of.
> **Network Level of Detail (pro feature)**
>
> Optimize your game's networking footprint with the intelligent LOD system. This feature scales the frequency of data synchronization based on an object's distance from the player. By throttling updates for distant entities while maintaining high-fidelity precision for nearby interactions, you can significantly reduce server bandwidth and improve client-side CPU performance without sacrificing gameplay quality.
> **Large Packet Handling**
>
> In some scenarios you may need to send large amounts of data either to the client or server. Tests show Fish-Networking was able to effectively send anywhere from a few, to a few hundred megabytes over the network. Other solutions such as Mirror and even Fusion throw errors on the same job.
> **Reliable Order of Operations**
>
> Race conditions are possibly the worst kind of problems to solve, and it's especially frustrating when those race conditions are caused by someone else's software. Competitors such as Mirror have shown to have a variety of race conditions, such as networked objects referencing one-another before they actually exist.
>
> Fish-Networking ensures references cannot go missing, and that the reliability of operations and callbacks are consistent in all scenarios.
> **Child Network Components**
>
> Child Network Components allow for easier design and better code organization by using components such as Network Objects or Network Behaviours on child objects. Mirror for example requires all networked components to be placed on the root object, which could quickly clutter your work flow.
> **Custom SyncTypes**
>
> Custom SyncTypes allow you to create logic on how something may be updated over the network. For example: SyncVars, SyncList, SyncDictionaries are all custom SyncTypes included within Fish-Networking. If you would prefer a more hands-on/tailored experience you may create your own Custom SyncType using the exposed framework.
> **Dual Projects**
>
> Fish-Networking has limited support for dual projects. We recommend using a single project and utilize server defines along with our **automatic code stripping** feature.
> **Single, Additive, Stacked Scene Management**
>
> Scene management is essential for offline and online games. While other solutions such as Mirror, Fusion, and Netcode are limited to basic single scene management out of the box, Fish-Networking provides built-in logic to control seperation of clients through single, additive, and even stacked scenes. This is a powerful tool for world streaming, dungeon instances, lobbys and more.
> **Automatic Prefab Detection**
>
> Networking solutions such as Mirror require you to specify and organize networked object prefabs. This is a time consuming task which often requires dragging every prefab into a collection, or looking up prefabs by string before you may spawn them over the network. Fish-Networking strongly believes in ease-of-use, and part of that is having your networked prefabs automatically detected by our framework. Changes made to networked objects are automatically known and configured by Fish-Networking without requiring additional steps form the user.
> **Built-in, or Custom Object Pool**
>
> Included is the ability to automatically reset and pool network objects. Objects can be set to pool at runtime, or be pre-configured on the NetworkObject. Pooled objects automatically have their network values reset, including all SyncTypes on the object.
>
> Fish-Networking comes with a basic object pool but fully supports any object pool of your choice.
> **Zero Hotpath Allocations**
>
> Allocations can massively affect both server and client performance. While Mirror and Netcode allocate garbage regularly, Fish-Networking does not, ensuring better scalability and all-around performance.
> **Offline Networked Objects**
>
> In some instances an object may need to only exist locally, rather than over the network, and sometimes both. Fish-Networking allows users to default objects to being local only so that the objects network functionality is unused. In addition, these objects are intelligently synchronized over the network when the user shows such intent.
## Features which do more in Fish-Networking
> **Serializables**
>
> Fish-Networking supports more object types to be serialized than any other free solution. Dictionaries, scriptable objects, nullables and more can be automatically serialized in Fish-Networking. Solutions which have existed longer, such as Mirror, still require manual serialization of many types which Fish-Networking handles automatically.
> **Area of Interest System**
>
> Area of interest, often called AOI, controls which clients receive what information. AOI not only can prevent cheating by disallowing information clients get, but also drastically improve bandwidth and performance of the server by not sending unnecessary information to clients. Both Fish-Networking and Mirror support AOI, however in Mirror you may only use one AOI system at a time. For example, you can separate clients by scenes in Mirror, but you cannot also separate them by distance at the same time. In result if you have a larger world players will see each other at all times. Fish-Networking not only streamlines setting up the AOI system but allows multiple conditions to run at once, which would resolve the just mentioned Mirror problem. Fish-Networking's AOI system can also be easily customized with your own logic.
> **Reliable and Unreliable Remote Calls**
>
> Several networking solutions support reliable and unreliable remote calls, but Fish-Networking simplifies the process for users. In Mirror if you wish to have a remote call which can send both reliable and unreliable you must duplicate your logic into multiple methods, one for reliable and one for unreliable. Fish-Networking again saves on lines of code and risk of error by allowing a single remote call method to run both reliably and unreliably. You can change the reliability effortlessly at runtime as well.
> **SyncType Flexibility**
>
> [SyncTypes](../../../guides/features/network-communication/synchronizing/) are another very common feature found in just about every high level library. However, very few solutions offer flexibility on how SyncTypes can be configured. Mirror for example can only send SyncTypes reliably, cannot adjust the interval per SyncType, has limited callbacks, and cannot control who receives the values of each SyncType. Fish-Networking on the other hand may send reliable or unreliable with eventual consistency. SyncType intervals can be different for each SyncType. Callbacks can occur on both the server and client. Each SyncType can be specified to go to only the owner, or all clients.
> **Tick Based**
>
> Tick based timings allow accurate simulation for client-side prediction, smooth transform replication, and a lot more. Fish-Networking has a strong and efficient tick based core to provide a smoother experience for both the developer and their players. Older networking solutions such as Mirror are not tick based, which results in sloppy simulations as well the inability to create a proper client-side prediction system.
> **Broadcasts and Messages**
>
> Fish-Networking supports broadcasts, interchangeably called messages. Broadcasts and messages are data which can be sent over the network without requiring a networked object receiver. These are useful for objects which you don't want networked but would still like to be able to communicate with, such as a door in your scene. Fish-Networking enhances this communication type by allowing multiple objects to utilize the same message. For example, in Fish-Networking all your scene doors could listen to the same message for updates; Mirror on the other hand only one door could listen to updates while you would have to create additional broadcast or message types for every single added door.
> **Original**
>
> Mirror, Netcode, and several other networking solutions are based off from previous works, some which are deprecated. Fish-Networking is made original from the ground up, with no prior solution's limitations to bog it down.
> **Anti-Singleton Design**
>
> Most networking solutions, even newer ones such as Netcode, use a singleton design pattern. Fish-Networking does not utilize singleton classes for it's managers, but still provides an easy way to access networking data from anywhere.
> **XML Documentation**
>
> An often unconsidered part of any project are the XML comments for it's API. Netcode, Mirror, and even Unity's official API have several parts which are not fully commented internally nor through the XML. Fish-Networking provides complete XML coverage with well thought-out descriptions to make developing easier without constantly have to jump through the source code or visit external sources.
@@ -0,0 +1,31 @@
# Performance
Prior to Fish-Networking we developed assets for other solutions, such as Mirror Networking. These assets have proven to perform 4 times faster, and use little as 13% the bandwidth of Mirror's internal components. Unfortunately, third party assets can only go so far. This is strongly in part why Fish-Networking was made.
Fish-Networking has been designed with performance and bandwidth in mind. Features are regularly benchmarked for client and server performance, as well bandwidth consumption; these metrics are important while deploying. Better performance allows your project to run on cheaper hardware, and enables a higher concurrent user count. By using less bandwidth Fish-Networking reduces your server bills.
## Bandwidth <a href="#server-and-host" id="server-and-host"></a>
**Networked Objects (moving)**
In most games moving objects will contribute the majority of used bandwidth. Fish-Networking's bandwidth consumption competes aggressively against modern paid solutions, and does better than any other free solution.
**Remote Procedure Calls**
Remote procedure calls, shortened to RPCs, are commonly placed second in bandwidth consumption. RPCs are used to communicate between the server and client. Fish-Networking uses only two bytes per RPC, while other free solutions use a minimum of 23 bytes.
## CPU <a href="#server-and-host" id="server-and-host"></a>
Another very important aspect is how well the networking solution scales. A better scaling solution ensures it will run on less expensive hardware, and get you closer to your MMO goals.
#### Network Object Count (idle)
It's not uncommon for frameworks to lose performance as more networked objects are spawned. Fish-Networking retains nearly 100% of it's performance regardless of how many objects are spawned.
#### Concurrent Users
Fish-Networking retains a large amount of performance with hundreds of users updating every tick. Other networking solutions have shown to slow down drastically as more concurrent users join the server.
**Client Experience**
With more objects, users, or activity even clients can be affected by a poorly designed networking solution. Fish-Networking has scored roughly 70% more frames per second on clients than other free solutions, such as Mirror.
@@ -0,0 +1,238 @@
---
description: >-
Everything looks good on paper but dedicated benchmarks can show you what to
really expect.
---
# Benchmark Setup
## **Setup**
* New scene with Camera and directional light.
* 1 object per player connection.
* Object moves and rotates randomly.
* Object has a client authoritative NetworkTransform with 100ms send rate.
* Object sends two ServerRPCs a second.
* Server sends an ObserverRPC for every ServerRPC it receives.
* Every client is it's own executable.
* Server tick rate is set to 10 (every 100ms).
## Gathering results
Performance results are determined by setting a server at it's highest possible frame rate and comparing frame time as more variables or clients are introduced.
Bandwidth results are discovered by using tools which come with the operating system, and averaging bandwidth per second.
## Scripts
These are the scripts created specifically to benchmark and ensure test are performed equally.
**MovingAverage.cs**
```csharp
using FishNet.Documenting;
using System;
using UnityEngine;
namespace FishNet.Managing.Timing
{
[APIExclude]
public class MovingAverage
{
#region Public.
/// <summary>
/// Average from samples favoring the most recent sample.
/// </summary>
public float Average { get; private set; }
#endregion
/// <summary>
/// Next index to write a sample to.
/// </summary>
private int _writeIndex;
/// <summary>
/// Collected samples.
/// </summary>
private float[] _samples;
/// <summary>
/// Number of samples written. Will be at most samples size.
/// </summary>
private int _writtenSamples;
/// <summary>
/// Samples accumulated over queue.
/// </summary>
private float _sampleAccumulator;
public MovingAverage(int sampleSize)
{
if (sampleSize < 0)
{
sampleSize = 0;
}
else if (sampleSize < 2)
{
if (NetworkManager.StaticCanLog(Logging.LoggingType.Warning))
Debug.LogWarning("Using a sampleSize of less than 2 will always return the most recent value as Average.");
}
_samples = new float[sampleSize];
}
/// <summary>
/// Computes a new windowed average each time a new sample arrives
/// </summary>
/// <param name="newSample"></param>
public void ComputeAverage(float newSample)
{
if (_samples.Length <= 1)
{
Average = newSample;
return;
}
_sampleAccumulator += newSample;
_samples[_writeIndex] = newSample;
// Increase writeIndex.
_writeIndex++;
_writtenSamples = Math.Max(_writtenSamples, _writeIndex);
if (_writeIndex >= _samples.Length)
_writeIndex = 0;
Average = _sampleAccumulator / _writtenSamples;
/* If samples are full then drop off
* the oldest sample. This will always be
* the one just after written. The entry isn't
* actually removed from the array but will
* be overwritten next sample. */
if (_writtenSamples >= _samples.Length)
_sampleAccumulator -= _samples[_writeIndex];
}
}
}
```
**DisplayPerformance.cs**
```csharp
using UnityEngine;
using FishNet;
using FishNet.Managing.Timing;
public class DisplayPerformance : MonoBehaviour
{
public int TargetFrameRate = 60;
private float _nextDisplayTime = 0f;
private MovingAverage _average = new MovingAverage(3);
private uint _frames = 0;
private void Update()
{
#if UNITY_SERVER
Application.targetFrameRate = TargetFrameRate;
_frames++;
if (Time.time < _nextDisplayTime)
return;
_average.ComputeAverage(_frames);
_frames = 0;
// Update display twice a second.
_nextDisplayTime = Time.time + 1f;
double avgFrameRate = _average.Average;
// Performance lost.
double lost = avgFrameRate / (double)TargetFrameRate;
lost = (1d - lost);
// Replace this with the equivelent of your networking solution.
int clientCount = InstanceFinder.ServerManager.Clients.Count;
Debug.Log($"Average {lost.ToString("0.###")} performance lost with {clientCount} clients.");
#elif UNITY_EDITOR
// Max out editor frames to test client side scalability.
Application.targetFrameRate = 9999;
#else
/* Limit client frame rate to 15
* so your computer doesn't catch fire when opening
* hundreds of clients. */
Application.targetFrameRate = 15;
#endif
}
}
```
**SimulatePlayer.cs**
```csharp
using FishNet.Object;
using UnityEngine;
public class SimulatePlayer : NetworkBehaviour
{
private float _nextMoveUpdate = 0f;
private float _nextRpc = 0f;
private Vector3 _posGoal;
private Quaternion _rotGoal;
private void Update()
{
if (!base.IsOwner)
return;
transform.position = Vector3.MoveTowards(transform.position, _posGoal, Time.deltaTime * 3f);
transform.rotation = Quaternion.RotateTowards(transform.rotation, _rotGoal, Time.deltaTime * 20f);
if (Time.time > _nextRpc)
{
_nextRpc = Time.time + 0.5f;
ServerRpc();
}
if (Time.time > _nextMoveUpdate)
{
bool rotate = (Random.Range(0f, 1f) <= 0.5f);
bool x = (Random.Range(0f, 1f) <= 0.5f);
bool y = (Random.Range(0f, 1f) <= 0.5f);
bool z = (Random.Range(0f, 1f) <= 0.5f);
if (!x && !y && !z)
x = true;
transform.position = _posGoal;
transform.rotation = _rotGoal;
float xPos = (x) ? Random.Range(-30f, 30f) : transform.position.x;
float yPos = (y) ? Random.Range(-30f, 30f) : transform.position.y;
float zPos = (z) ? Random.Range(-30f, 30f) : transform.position.z;
_nextMoveUpdate = Time.time + 2f;
_posGoal = new Vector3(xPos, yPos, zPos);
if (rotate)
_rotGoal = Quaternion.Euler(Random.Range(-80f, 80f),
Random.Range(-80f, 80f),
Random.Range(-80f, 80f)
);
}
}
[ServerRpc]
private void ServerRpc()
{
ObserversRpc();
}
[ObserversRpc]
private void ObserversRpc()
{
}
}
```
@@ -0,0 +1,66 @@
# Fish-Networking Vs Mirror
{% hint style="danger" %}
These benchmarks are very old. Server outbound bandwidth metrics have changed.
As of the date 2023/08/26 Mirror is believed to be approximately 5% more efficient in bandwidth, and Fish-Networking about 90-95% more efficient in bandwidth.
Example:
if Mirror previously sent 100mB/s they are now expected to send 95mB/s.
If Fish-Networking previously sent 100mB/s it would now send 5mB/s
{% endhint %}
## Versions
* Fish-Networking v1.4.3
* Mirror Networking v66.0.3
## Results
**Hardware**
* Windows Server 2019
* AMD EPYC 7402P 24-Core (1 SLICE/CORE USED!)
* 2.00 GB RAM
**100 CCU Scaling**
* FishNet Server lost 1.5% of it's performance.
* FishNet Client ran at 1350 FPS.
* Mirror Server lost 29.5% of it's performance.
* Mirror Client ran at 791 FPS.
**200 CCU Scaling**
* FishNet Server lost 7.4% of it's performance.
* Mirror Server lost 83.2% of it's performance.
* Clients were untested.
**100 CCU Bandwidth**
* FishNet Server per second sent 7.3mB (adjusted 0.55mB) and received 1.1mB.
* Mirror Server per second sent 31.8mB (adjusted 30.2mB) and received 3.2mB.
**200 CCU Bandwidth**
* FishNet Server per second sent 29.9mB (adjusted 2.24mB) and received 2.2mB.
* Mirror Server per second sent 94.3mb (adjusted 89.6mB) and received 4.8mB.
**Spawned Network Objects (idle)**
| Objects | Fish-Networking | Mirror |
| :-----: | :-------------: | :----: |
| 0 | 1.5ms | 1.5ms |
| 500 | 1.5ms | 1.9ms |
| 1000 | 1.5ms | 2.2ms |
| 2000 | 1.5ms | 2.9ms |
| 4000 | 1.5ms | 4.2ms |
**Results**
* Client FPS: FishNet clients achieved 70% more FPS than Mirror.
* Bandwidth: FishNet used 67-78% less bandwidth than Mirror.
* Server Performance(200 CCU): FishNet retained 92.6% server performance, while Mirror retained only 16.8% performance.
* Server Performance(4000 idle objects): FishNet retained 100% server performance, while Mirror retained only 36% performance.
@@ -0,0 +1,7 @@
---
description: Fish-Networking's compatibility with recent Unity versions
---
# Unity Compatibility
<table><thead><tr><th>Unity Version</th><th valign="top">FishNet Support</th></tr></thead><tbody><tr><td>Unity 6 LTS</td><td valign="top"><mark style="color:green;">All features work, fully supported.</mark></td></tr><tr><td>Unity 2023.2+</td><td valign="top"><mark style="color:green;">All features work, fully supported.</mark></td></tr><tr><td>Unity 2022.3+</td><td valign="top"><mark style="color:green;">All features work, fully supported.</mark></td></tr><tr><td>Unity 2021.3+</td><td valign="top"><mark style="color:green;">All features work, fully supported.</mark></td></tr><tr><td>Unity 2020 and earlier</td><td valign="top"><mark style="color:orange;">Not supported.</mark></td></tr></tbody></table>