- Home /
Using uNet to convert from single player to multiplayer - Where to assign SyncVar, Client and Command?
// Blurb begins
For the last few days I've been working on a single-player version of what will eventually be a multiplayer game. The game is a sandbox RPG (ugh) like ARK, Rust, whatever. In the last few days I've completed the systems for player skills, health /other stats, equipped and non-equipped items, crafting, harvesting and picking up items from the game world.
With all but item placement, combat and actual survival elements implemented (excl. the whole host of models and a fully-furnished game world...) I decided to give multiplayer code a shot before things became too messy, so that I could continue to implement features in a multiplayer project rather than a single-player project. For now, I'm looking to make a "working prototype" - something that myself and a few friends could play on to demonstrate how the game is played. For this reason I've decided to use uNet, since I'm lazy af and didn't want to download a better networking solution at the time.
I got players and spawning set up with no issues (not very complicated since it was mostly drag and drop!), and the destructible game world (ie. trees falling over when harvested) registers across the server. All was going well.
// Blurb ends
// Problem
The issue that I have is that, once there's more than one person on a server (ie. someone other than the host) I get a NullReferenceException
stating that the PlayerStats script doesn't exist. Here's a rough overview of how things are set up at the moment:
Database GameObject
Item Database: contains
List
with all items used in the game by playersPerk Database: contains
List
with all perks that players have access toRecipe Database: contains List with all crafting recipes
Player GameObject
Actions (Script): contains a Raycast to find what GameObject is hit; does various things depending on the tag of the GameObject
Inventory (Script): contains
List
which stores all objects in the player's inventory, as well as the OnGUI() to draw the inventory on screen. There are functions such asAddItem()
,RemoveItem()
,EquipItem()
and so forth in here.PlayerStats (Script): contains
List
,List
,List
. All of these are created and added to by functions called InitialisePlayerSkill/Vital/Equipment in theStart()
method. Also on this script is the function for unequipping an item.Crafting (Script): contains the
OnGUI()
function for the crafting window, which links back around to the player's inventory script to Add /Remove items.
As I said, I get a NullReferenceException
when a second player joins the world:
"NullReferenceException: Object reference not set to an instance of an object PlayerStats.Update () (at Assets/Resources/Scripts/PlayerStats.cs:46)"
void Update() {
if(!isLocalPlayer)
{
// exit from update if this is not the local player
return;
}
if(Input.GetButtonDown("Character Pane"))
{
showCharPane = !showCharPane;
}
foreach(Vital v in playerVitals) // OFFENDING LINE (#46)
{
if(v.curValue <= v.maxValue && v.curValue >= 0)
{
v.curValue += v.vitalRegen * Time.fixedDeltaTime;
}
if(v.curValue > v.maxValue)
{
v.curValue = v.maxValue;
}
}
}
The offending line (Line 46) is highlighted. This suggests to me that playerVitals doesn't actually exist to this player (player 2), confirmed by another NullReferenceException
on line 29 (which simply changes the value at `playerVitals[0]'.
// Looking for a solution...
If I'm correct, this would be due to the new player immediately being out of sync with the server. At the moment, I'm (trying) to store the player's stats on the server. I all honesty, I have very little idea what I'm doing with regards to player variables...
Do I store all of the player's stats on the server or do I keep them on the client until they're needed somewhere else on the server (ie. damage detection or adding XP to a player's skill when they cut down a tree)? I know that the [SyncVar] tag can be added before a field's declaration at the start of a script, but what does this actually do? Does it store that instance of the script's version of the variable or does it make that variable a global value shared by all clients?
// More broadly...
As well as not really knowing when to use [SyncVar], I don't really know when to use [Client] and [Command] before my methods! How do I know, for certain, whether I need to give a method or a variable one of these tags?
Thanks in advance!
Your answer
Follow this Question
Related Questions
Unity 5 - submeshes don't work as before 1 Answer
Unity 5 Light Problem 1 Answer
Why don't shadows appear in my built .exe? Unity 5 4 Answers
Sound files not working [Unity 5.1] 0 Answers
Can't Play Animation 0 Answers