- Install FishNet
- Click "Add package from git URL..." in the Unity Package Manager (UPM) and paste in https://github.com/hudmarc/FFO-FishNet-Floating-Origin.git
- Add a
FishNetOffsetManager(located atPackages > Floating Offset for Unity > Runtime > Networking > FishNet > Management) to the GameObject holding your FishNetNetworkManager. This will allow you to also set your configuration. - Add an
OffsetViewto all your players and any GameObjects you spawn in with aNetworkTransformthat need to move long distances (for example, AIs that can chase the player) - Utility functions live on
OffsetUtils, if you want to teleport the player you also call that through theOffsetUtils. (note that Teleport in particular is only callable on the network server!)
Setup tutorial video coming soon.
Check out the Server Authoritative Client Side Prediction Demo Here
By default, Unity can handle ~20km by 20km game worlds without running into floating point precision limitations.
This package extends the possible world size to ~2.114e+35 light years. The known universe is only 4.651e+10 light years (as of writing this README)
This is currently the only open-source Unity package that can do this while maintaining full server authority. It is also compatible with client-side prediction, but you may need to adjust your CSP scripts.
At the time of writing, this package is the only open source origin-shifting/world rebasing solution that supports full server authority in a multiplayer environment. Other solutions generally require client-side authority and physics (by storing offsets client-side), but this package uses a fast server-side neighborhood clustering algorithm to ensure all players that can interact exist in the same scene on the server. If you want to learn more, the main Process loop in OffsetServer contains the bulk of the implementation.
Is this package fast enough for my game? I want to host my small friend group of 3000 people on one world on my server.
Assuming a 4ms frame budget and a midrange server (in other words, the same cost as the default Unity Physics loop) yes.
If all players are clustered in one spot (all players in the same scene, generally best case)
MultipleViewsSameClientStressTestCloseTogether (27.396s)
---
Stopped at 4800 players with simulated frametime 4ms.
Average: 1.89145833333333ms
Worst: 4.38333333333333ms @ 4800 players
Best: 0.0666666666666667ms @ 80 players
If players are all far from each other (1 scene/player, worst case)
MultipleViewsSameClientStressTestSpreadOut (17.476s)
---
Stopped at 3060 players with simulated frametime 4ms.
Average: 1.8942265795207ms
Worst: 4.03333333333333ms @ 3060 players
Best: 0.05ms @ 40 players
Note: These benchmarks were using mock classes, not Unity libraries, so YMMV. If you manage to reach this many players on an actual Unity game with this package, please let me know!
Tested on 6-Core Mobile Core i7 (I7-9750H) @ 4.5Ghz Turbo Boost
- Create an Offline Scene, this should have your FishNet
NetworkManager, add theOffsetManagerNetworkingcomponent and untick Unity Physics if you want to use TimeManager physics. - Add an OffsetTransform to your player, and tick 'isView'
- If you have static structures that can be duplicated, anchor them in real space using the
OffsetAnchor - If your game uses line renderers or particle effects and you want them to be offset correctly add the
EffectOffsetterto your manager object and assign it to theOffsetManager - To configure the Floating Offset backend, set your preferences to the
OffsetUniverse. It should be automatically created at the root of your project. If not, you can create your own underAssets/Create/Floating Offset/OffsetUniverse - To teleport views to specific real positions, use
universe.TeleportTo(OffsetTransform offsetTransform, Vector3d position)
You can think of an offset scene as a normal Unity scene with a particular offset from 0,0,0 represented in 64-bit doubles. The point of this package is to keep all players as close to the centers of their scenes as possible, and it does this using a variety of algorithms and datastructures.
These are implemented in the OffsetServer as collections, you can view the offset of a given scene in the Editor when you have an OffsetTransform or OffsetAnchor selected. If you need to see the offset of a scene in code you can do this with Vector3d GetSceneOffset(Scene scene) (currently this is located on OffsetServer but will be moved, update to follow soon)
Manages the offset server and configuration. See FishNetOffsetManager for the core multiplayer version of this class.
Implements the low level neighborhood clustering of this package. The core logic of this package could in the future be ported to Godot or another C# engine, and in the meantime this class is very testable.
The Offset Server manages the pooling of Offset Scenes and the transfer of Offset Transforms between all active Offset Scenes as well as keeping the scenes properly rebased. The Offset Server is not actually a Monobehaviour so it is instantiated by the OffsetManager as a plain C# object and its instance lives on the OffsetUniverse.
Add an OffsetView to all your players and any GameObjects you spawn in with a NetworkTransform that need to move long distances (for example, AIs that can chase the player)
Offset Anchors ensure that the object they are attached to are always at the exact position specified in the OffsetAnchor's target position. Great for things like cities or other POI's that need to exist at specific points in space. If you didn't use this you would notice that cities that exist very very far from the origin are not where you put them (for example, clipping into the terrain) because their native Unity position (which is a Vector3) is not precise enough to store their exact location.
Marks an object as ignored by the Offset system, when a scene is rebased this object will not be moved. Great for terrains that need to stay near the origin and use some custom system to render themselves. (for exmaple, offsetting the terrain by the scene offset, I'll port an example as soon as I can)
