To see uSurvival in action, simply open the included scene from uSurvival/Scenes, press Play in the Editor and select Server & Play. Run around a bit, pick up some weapons and drag them to your Hotbar at the bottom of the screen to try them. Kill some Zombies, climb the ladder, etc.
Once you got a feeling for it, now it’s time to get some basic project overview and learn some new stuff. Recommended first steps:
Right now, the recommended Unity version is Unity 2018.3.6. You should not use an older version because Unity is not downwards compatible.
You can use newer versions at your own risk. uSurvival is a big project that uses a lot of different Unity features, so whenever Unity introduces a new bug, we feel the effect very significantly. In theory, any newer Unity version should work fine if (and only if) Unity didn’t introduce new bugs. That being said, it’s common knowledge that Unity always introduces new bugs to new versions.
During the past few years working on uMMORPG, the process was to download Unity, encounter bugs, report them, upgrade Unity to the newer version where the bugs were fixed, only to encounter new bugs, and so on. It was a never ending cycle of upgrading headaches, with only the occasional stable version in between.
During GDC 2018, Unity announced the LTS release cycle. LTS stands for long term support. Unity LTS versions are supported for 2 years and will only receive bug fixes, without introducing any new features (and hence new bugs).
Words can hardly express how significant LTS versions are for a multiplayer game. You should absolutely use LTS at all times, otherwise your players will suffer from bugs and all hell will break loose.
The Player prefab(s) can be found in the Prefabs/Entities/Players folder:
Players have a whole lot of components attached to them, generally one per feature.
You can modify a whole lot without writing any code, simply browse through the components in the Inspector to get a feel for it.
You can of course add your own components to player prefabs too.
The PlayerMovement and NetworkTransformRubberbanding components are the only two components that are client authoritative. The reason is very simple too: evaluating every movement request on the server first would cause too much of a delay to feel smooth on the client.
Players are moved with Unity’s CharacterController.
If you ever played games like Counter Strike or Quake then you will greatly appreciate the CharacterController movement. It’s not 100% physically correct, but it sure feels really, really great.
The player model is easy to modify. All we have to do is swap out the 3D model and assign a couple of components, so that uSurvival knows where the hand/head/etc. are. Let’s do it step by step with the Space Robot from Unity.
IMPORTANT: the Space Robot model was created by a professional 3D artist, and everything worked perfectly. Some poorly created models will have strange bone structures or weird shoulder rotations, which often cause the arms to end up in weird positions while holding a weapon. If this happens, the easiest solution is to ask your artist to fix the rig. Send your artist the space robot for comparison. Another option is to modify the ShouldersLookAt component’s rotation offsets until it fits, but that’s a very tedious process.
The Zombie(s) can be found in Prefabs/Entities/Zombies:
You can modify it to your needs, just like the Player prefab, so please check out the part on modifying players.
You can also take a look at this video that was created by a community member.
There is no complicated spawning system for zombies. Simply drag them into the scenes and position them wherever you want them to live.
Zombies have a simple AI and they need to be able to navigate around obstacles, for example to follow a player into a building. This is very difficult to do, but thanks to Unity’s Navigation feature, all we have to do is set the Zombie’s NavMeshAgent.destination property.
So in other words, Zombies are NavMeshAgents on Unity’s Navmesh. Make sure to rebake the Navmesh whenever you modify the game world.
Zombies are driven by the Zombie component, which contains a Finite State Machine. The behaviour is 100% code, so you’ll have to modify the Zombie script if you want to change it.
If you want to modify your Player’s spawn position, simply move the Respawn point in the Scene / Hierarchy:
If you want multiple respawn points, simply duplicate one and move it somewhere else. Mirror has different ways to select the Respawn point, you can modify that in the NetworkManager:
uSurvival uses a small and simple scene to display all of the features. You can of course add any 3D models or environment assets that you like, as well as Terrains. Simply make sure that:
We already added the most basic items types, so you can simply duplicate existing items to make similar ones:
You can also create new Items by right clicking in the Project area to select Create->uSurvival Item:
As you can see, there are already different item usage mechanisms. Food like a banana will be consumed to increase health/hydration/nutrition. Other items like the Beretta do none of that, but shoot bullets instead. Every Survival game will need all kinds of different item usage mechanisms, which is why we implemented Scriptable Items.
Please take look at the Scripts/ScriptableItem.cs file and the Scripts/ScriptableItems folder with the currently implemented Scriptable Item types. In most cases, you will want to inherit from UsableItem.cs. All you have to do is overwrite the .Use() function (and a few others depending on your needs) to add any item mechanism that you want. You could have an item that kills every Zombie on the server in .Use(), you could have a tent that is built into the game world, the possibilities are endless.
To create a new Scriptable Item type, simply create a new Script, inherit from ScriptableItem (or UsableItem if it’s supposed to be usable) and then add your logic / properties as needed. Make sure to add a menu entry like this:
So that you can create an item of that type via right click.
We just talked about ScriptableItem.cs, which is the true ‘Item’ class in uSurvival. But there is also Item.cs - what the hell?
uSurvival uses Mirror’s SyncListStructs for the inventory and the equipment. Those SyncListStructs only work with structs, so we can’t put ScriptableItem types in there. And that’s a good thing, here is why:
Note that all ‘dynamic’ Item properties like current Ammo are also in Item.cs - since two Items of the same ScriptableItem type might as well have different amounts of ammo in their magazine.
There is also the ItemSlot struct, which is just Item + amount. No magic here.
The Inventory and Equipment SyncListStructs work with ItemSlots.
A slot contains a valid .item if the .amount > 0. If .amount == 0 then the .item is invalid and should not be accessed.
Another Item class - what the hell?
uSurvival needs Item Drops in the game world, like a Banana that lies on a kitchen table in an old farm house. We can’t just drag ScriptableItems or Item/ItemSlot structs into the game world, they have no 3D representation whatsoever.
Hence why we also need an ItemDrop component. There is no magic here either. Those are just 3D models with an ItemDrop component which refers to the ScriptableItem that is rewarded to the Player after picking it up.
By the way, ItemDrops are NetworkIdentities with NetworkProximityCheckers so that everyone on the server sees them when close enough.
Oh come on.. enough with the Item classes now!
Okay, last one. If the player uses an Axe, we should see an Axe model in the player’s hands. That’s why we need Item Models. They are really just 3D models this time, nothing complicated.
Note: we can’t reuse ItemDrops here. They are 3D models too, but ItemDrops are NetworkIdentities with ProximityCheckers, and ItemModels are literally just that, models. Mirror doesn’t allow NetworkIdentities to be children of other NetworkIdentities, hence why we need Item Models too.
Let’s say you want to add an apple to your game. Here is the step by step guide:
Now press Play, walk to your Apple, pick it up and find it in your inventory.
For tools / guns that the player can hold in his hand, you will also have to create the ItemModel (as usual, duplicate an existing one and modify it), and then assign the Scriptable Item’s modelPrefab field too.
Each ScriptableItem has a durability option:
An item’s durability is decreased:
You can modify each scriptable item’s OnUse function to also reduce durability on use if you want to.
ScriptableItem’s max. Durability can also be set to 0 to completely ignore durability for that item.
The item’s color will also change if the durability is either low or if the item is completely broken:
uSurvival comes with a StructureItem type that can be used to build things. The palette in the Demo Scene can be used to play around with the build system:
Structures snap to a grid, kind of like Minecraft where blocks can only be placed next to other blocks (and not one-third of a way to it).
By default, the palette uses a Grid Resolution of 2, so it can be placed at 0, 0.5, 1, 1.5, etc. In other words, the grid is ‘half a palette’:
The grid can also be modified. For example, Grid Resolution = 1 means that they can only be placed at 0, 1, 2, 3, etc.:
Different grid resolutions may need position offsets in the AvailableRotations property. For example, here are the offsets and rotations for a resolution of 1:
Play around with those values while building palettes to see what they do!.
Note: you can cycle through the available rotations with the R key ingame.
There are two types of equipment: static and animated (aka skinned mesh) equipment.
We don’t have to worry about static equipment at all, simply create whatever model that you like and uSurvival will show it in the player’s right hand.
Animated equipment (skinned meshes) are moved into the Player object, and then their attached Animator follows the main animator’s state. Artists will have to export the skinned meshes rigged and animated in order for that to work.
uSurvival already supports skinned mesh equipment, the code was copied from my other uMMORPG asset. uSurvival skinned mesh examples will follow soon.
Crafting recipes can be found in the Resources/Recipes folder:
Recipes are very simple. They have a list with ingredients and a result item:
You can craft them ingame by dragging the ingredients into the crafting slots, afterwards the item that can be crafted will appear:
This system also allows for real recipe items. For example, the banana drink could also require a secret scroll that players need to find in order to craft it. The scroll can simply be added as one of the ingredients.
Players and Zombies can have different Damage Areas, so that hits on the head (or other body parts) cause more damage than hits on the body.
To add a Damage Area, simply add a (Trigger)Collider to the Head/Arm/etc. and then also add a DamageArea component to it:
uSurvival comes with a built in networked interaction system:
Here is how to add another interactable object, like a campfire that can be lit:
Mirror can only handle one scene at a time, and there isn’t really any need to have multiple scenes in a Survival game.
You should simply modify the existing scene to your needs.
uSurvival has one abstract Energy type which can be inherited from to by all kinds of energies like Health, Nutrition and Hydration.
Energies can recover once per second. They can recover positively and negatively.
Energies can underflow and overflow into other Energies. For example, if Nutrition recovers by -1 per second (aka you get hungry), then it will reach 0 eventually. Once that happened, it can continue to reduce (for example) health by -1 once per second until Nutrition was filled up again (until the player ate something).
In other words, a player can die after not eating for a while, etc.
You can also add more energies like Oxygen. Simply inherit from Energy, add the component to the Player and then modify UIHud to display it on the screen.
uSurvival uses SQLITE for the database. SQLITE is like MySQL, but all stored in a single file. There’s no need for a database server or any setup at all, uSurvival automatically creates the Database.sqlite file when the server is started.
SQLITE and MySQL are very similar, so you could modify the Database.cs script to work with MYSQL if needed.
Note that SQLITE is more than capable though. Read the SQLITE Wikipedia entry to understand why.
The database can be found in the project folder, it has the name Database.sqlite.
The database structure is very simple, it contains a few tables for characters and accounts. They can be modified with just about any SQLite browser and we listed several good options in the comments of the Database script (e.g. SqliteBrowser).
Characters can be moved to a different account by simply modifying their ‘account’ property in the database.
A character can be deleted by setting the ‘deleted’ property to 1 and can be restored by setting it to 0 again. This is very useful in case someone accidentally deleted their character.
uSurvival uses Unity’s new UI system. Please read through the UI manual first:
Modifying the UI is very easy. Just modify it in the Scene in 2D view.
Most of the UI elements have UI components attached to them. There is no magic here, they usually just find the local player and display his stats in a UI element.
Feel free to modify all the UI to your needs.
uSurvival’s NetworkManager has a Server List:
The default entry is for a local server on your own computer, so you can test multiplayer easily. If you want to host uSurvival on the internet, you can add another entry here with some name and the server’s IP. Players can then select it in the Login screen:
Mirror puts the server and the client into one project by default, so any build can run as client or server as necessary. There is no special build process needed.
It’s obviously a bad idea to host the server on a mobile device or in WebGL of course, it should be a standalone platform like Windows/Mac/Linux with some decent hardware.
The recommended server platform is Linux. Unity can create a headless build of your game there, so that no rendering happens at all. This is great for performance.
Linux is the recommended Server system. If you have no idea how to get started hosting a Mirror game on a Linux system or where and which one to even rent, then please go through my UNET Server hosting tutorial for a step by step guide and then continue reading here.
If you already know your way around the Terminal, then use the following commands:
Upload Headless build to home directory:
scp /path/to/headless.zip firstname.lastname@example.org:~/headless.zip
Login via ssh:
Install 32 bit support (just in case), sqlite, unzip:
sudo dpkg --add-architecture i386
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386
sudo apt-get install libsqlite3-0:i386
sudo apt-get install unzip
Unzip the headless build:
Run the server with Log messages shown in the terminal:
./uSurvival.x86_64 -logfile /dev/stdout
The whole point of Mirror was to have all the server and client source code in one project. This seems counter-intuitive at first, but that’s the part that saves us years of work. Where we previously needed 50.000 lines of code or more, we only need 5000 lines now because the server and the client share 90% of it.
The 10% of the code that are only for the server are mostly commands. Reverse engineering the client could make this code visible to interested eyes, and some developers are concerned about that.
The first thing to keep in mind is that this does not matter as long as the server validates all the input correctly. Seeing the source code of a command doesn’t make hacking that much easier, since for most commands it’s pretty obvious what the code would do anyway. For example, the Linux operating system is very secure, even though it’s code is fully open source.
Furthermore it’s usually a good idea for game developers to spend all of their efforts on the gameplay to make the best game possible, without worrying about DRM or code obfuscation too much. That being said, if you still want to hide some of the server’s code from clients, you could wrap your [Command]s like this:
And then #define SERVER in your code before building your server.
uSurvival’s components offer several events that can be hooked into, for example:
You can use those events to add custom functionality without touching the core code. Simply press the + Button, drag in the prefab and select which public function to call in your component (e.g. for OnClientReceivedDamage, show another damage effect on the client).
You can add your own events easily by using Unity’s UnityEvent type:
And then calling .Invoke() for it.
We added a lot of events that can be used by your own components/addons. If you need more, let us know!
There are a lot more features and improvements planned for uSurvival. If you want to update your local version to the latest version, you should keep a few things in mind:
We did several community tests to proof that uSurvival can handle large amounts of players. Keep reading to learn about the CCU (concurrent users) goal, the server setup and the results.
Games like Fortnite and DayZ managed to make millions of dollars with a 100 CCU limit, so 100 seems like a reasonable goal.
Networking games use areas of interest so that not all 100 players send their state to all 100 other players, as this would result in 100 x 100 = 10,000 broadcasts per state change, which is an insane amount of packets being sent around, DayZ for sure can’t handle that, and we aren’t sure about Fortnite either. Instead, people are usually surrounded by less than 5 players, often times they are even completely alone, resulting in way less broadcasts per state change.
We did a worst case test because we really want to see how much the server can handle if it comes down to it.
In other words, multiply our CCU result with 2x-5x and you can estimate the real case CCU.
Date: August 27, 2018
Players (CCU): 122
Result: Success! 0 errors. 0 loss. 0 disconnects. 0 hickups.
Screenshots: (right click and open images in new Tab for details)
121 Players ingame:
We rented the PX92 dedicated server from Hetzner for 105€/month with the following specs:
Xeon W-2145 8 Cores x 3.7 GHz
128 GB DDR3
240 GB SSD, 6GB/s
Ubuntu 16.04 LTS
Many survival games run on $400+/month servers. We will test on one of those next time.
The Software Stack
High Level Networking
Low Level Networking
We always test CCU with our community, so that there are witnesses for the test results.
If you don’t believe the test results, feel free to come by our Discord server and ask any of the participants:
vis2k, KarlGG, Ryougi Shiki, Isaac, Davil, Holman, Cioa, Icon, Radioactive Bullfrog, Faiyth, ...
We also ran a Websocket Test a while ago, just to be sure.
Limitations: NetworkTransport doesn’t provide debug/statistics with WebSockets enabled, so we couldn’t measure bandwidth / pending packets, etc.
Result: Test succeeded. 25 CCU ran perfectly smooth.
Proof: (right click and open images in new Tab for details)
Notes: we contacted the NetworkTransport developer to hopefully get Websocket debugging in the future. All the -1 values in the screenshot above were not available in WebSockets. Will redo test when available and when we have more processing power in the community.