Porting from client-hosted to DGS - Optimizing server builds
This is part four of the Porting from client-hosted to dedicated server-hosted series.
See the other pages in this series:
Unlike client builds, server builds have no need for visuals, sounds, inputs, or anything related to a user's device like mobile notifications. You can reduce the size of server builds and, as a result, save a lot of hardware resources by removing client-specific scripts and assets.
You can do this by stripping the unnecessary assets from the server build at build time; this way, the client-side assets aren’t included in memory when loading the executable. Server build stripping allows you to pack as many server instances as possible on your dedicated hosting, saving you money.
Server build stripping
In Unity Editor version 2021 and later, you can use the Dedicated Server build target option. The Dedicated Server build target automatically strips content the server doesn’t need at build time in addition to starting headless automatically. See the Unity Build Settings documentation.
You should see a reduction in memory and CPU usage with the Dedicated Server build (compared to a build that includes client-side assets).
Script stripping
Script stripping involves removing client-only scripts from a server build. You can strip scripts from a server build using the UNITY_SERVER scripting symbol. You can use the UNITY_SERVER option per script or per assembly to strip whole client-only assemblies.
For example, you might want to set all audio-specific code in an Audio assembly, then strip the Audio assembly from server build targets. This would ensure you have no audio code running on your server. Because Unity performs stripping operations at compile time, it’s easier to find compiler errors than runtime errors.
There are some indexing issues that arise when using Netcode for GameObjects (NGO) with asset stripping. See NGO and script stripping.
NGO and script stripping
Netcode for GameObjects (NGO) relies on NetworkBehaviour
’s index position on a GameObject to know to which NetworkBehaviour
it needs to route network messages. By stripping a script, you can unintentionally create holes in the GameObject’s list of components, interfering with NGO’s indexing. In general, you shouldn’t strip NetworkBehaviours
; in fact, NetworkBehaviours
should always be the same between the client and server. To avoid indexing issues with NGO, use script stripping with caution (and only strip as necessary).
Your server build can have a few NetworkBehaviours
scripts to allow callbacks like OnNetworkSpawn
. These callbacks should use the NetcodeHook
class (see Boss Room’s Utilities package).
Manual stripping
You can use third-party solutions, such as BuildStripper
and Headless Builder, to manually strip Prefab and GameObject assets one by one.
GameObjects stripping
It’s possible to create automation workflows that selectively strip GameObjects depending on the build target. Such automation might allow you to remove performance-heavy GameObjects and ensure the server is as lightweight as possible, resulting in reduced hosting costs.
Other stripping opportunities
You can also strip other client-specific data to improve the performance of your build. Some examples include:
Animations
Because server builds are headless, you might be able to exclude some animation-related code, such as character animation and bones that aren’t linked to gameplay, further reducing the resource requirements. Animations often increase the performance demands of a build; as a result, removing unnecessary animations server-side can improve performance a great deal.
Animation-only bones
It’s usually safe to do per-bone stripping on server builds, where you delete bones that aren’t linked to gameplay. For example, you might keep a character’s right arm for weapons, but you strip the left arm because it’s only used for animation.
Don’t remove bones if you have hitboxes or gameplay attached to those bones.
Rigidbody
physics
You can also improve server build performance by disabling server-side interpolation of Rigidbody
physics. For example, you might add a post-process step to your scene that disables server-side Rigidbody
interpolation.