Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Unity 5 UNET Multiplayer Tutorials - Making a basic survival co-op

Discussion in 'Community Learning & Teaching' started by GTGD, May 13, 2015.

  1. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    For those of you having trouble with the Join Game button in video 20 just change the SetupMenuSceneButtons () method into a coroutine. When a level is loaded you sometimes need to just put in a bit of fudgy delay before you run code that accesses components.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.Networking;
    4. using UnityEngine.UI;
    5.  
    6. public class NetworkManager_Custom : NetworkManager {
    7.  
    8.     public void StartupHost()
    9.     {
    10.         SetPort();
    11.         NetworkManager.singleton.StartHost();
    12.     }
    13.  
    14.     public void JoinGame()
    15.     {
    16.         SetIPAddress();
    17.         SetPort();
    18.         NetworkManager.singleton.StartClient();
    19.     }
    20.  
    21.     void SetIPAddress()
    22.     {
    23.         string ipAddress =  GameObject.Find("InputFieldIPAddress").transform.FindChild("Text").GetComponent<Text>().text;
    24.         NetworkManager.singleton.networkAddress = ipAddress;
    25.     }
    26.  
    27.     void SetPort()
    28.     {
    29.         NetworkManager.singleton.networkPort = 7777;
    30.     }
    31.  
    32.     void OnLevelWasLoaded (int level)
    33.     {
    34.         if(level == 0)
    35.         {
    36.             StartCoroutine(SetupMenuSceneButtons());
    37.             //SetupMenuSceneButtons();
    38.         }
    39.  
    40.         else
    41.         {
    42.             SetupOtherSceneButtons();
    43.         }
    44.     }
    45.  
    46.     IEnumerator SetupMenuSceneButtons ()
    47.     {
    48.         yield return new WaitForSeconds(0.2f);
    49.         GameObject.Find("ButtonStartHost").GetComponent<Button>().onClick.RemoveAllListeners();
    50.         GameObject.Find("ButtonStartHost").GetComponent<Button>().onClick.AddListener(StartupHost);
    51.      
    52.         GameObject.Find("ButtonJoinGame").GetComponent<Button>().onClick.RemoveAllListeners();
    53.         GameObject.Find("ButtonJoinGame").GetComponent<Button>().onClick.AddListener(JoinGame);
    54.     }
    55.  
    56.     void SetupOtherSceneButtons ()
    57.     {
    58.         GameObject.Find("ButtonDisconnect").GetComponent<Button>().onClick.RemoveAllListeners();
    59.         GameObject.Find("ButtonDisconnect").GetComponent<Button>().onClick.AddListener(NetworkManager.singleton.StopHost); //Unity method
    60.     }
    61.  
    62. }
    63.  
     
    Last edited: Oct 9, 2015
    AzatKhafizov likes this.
  2. Akthree

    Akthree

    Joined:
    Apr 30, 2015
    Posts:
    2
    First i want to say Thank You for this awesome Tutorial.
    I think i figured out an easy way of reducing the data-load of the Zombie_MotionSync without loosing performance.
    I packed it all in a coroutine and by an amount of 50 Zombies chasing around i messured and reduced it from 3600 to 50 approx Total Calls.
    (I think i need to say that i have added a wander function so the Zombies are totally moving)

    Here is the changed code:
    Code (CSharp):
    1. void Start () {
    2.  
    3.         myTransform = transform;
    4.         StartCoroutine(UpdateMotion());
    5.  
    6.     }
    7.  
    8.     // Update is called once per frame
    9.     /*
    10.     void Update()
    11.     {
    12.         TransmitMotion();
    13.         LerpMotion();
    14.     }
    15.     */
    16.  
    17.     IEnumerator UpdateMotion () {
    18.  
    19.         yield return new WaitForSeconds(0.2f);
    20.         TransmitMotion();
    21.         LerpMotion();
    22.  
    23.     }
     
  3. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    That's cool! Nice thinking there. So that means the sync is now really meant for new players joining the scene. After the initial position and rotation sync the client takes care of the motion of it's zombies from there. Am I correct? It must be really stable with the match maker now.

    Edit: Nah I think this still won't help you with the problem of ensuring that new players joining the scene have updated positions for all the zombies.
     
    Last edited: Oct 10, 2015
  4. Akthree

    Akthree

    Joined:
    Apr 30, 2015
    Posts:
    2
    Thank you for asking that ... i found that it really was behaving like you mentioned BUT this leads to no sync of the zombies at all after the inital start and therefore no movement. since they are only moved on the server... i need to think this more through but i will keep you updated
     
  5. Xazerek

    Xazerek

    Joined:
    Nov 3, 2014
    Posts:
    134
    Hello! Thank you for your great tutorial! I have one problem now. All clients have this same stats what host. I thought [SyncVar] will fix that problem, but it's not. Can you please tell me how can i sync variables between players?
    Thanks in advance. Btw. Will u make tutorial for how to make chat?
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using UnityEngine.Networking;
    5.  
    6. public class PlayerStatsNetworking : NetworkBehaviour {
    7.  
    8.         [SyncVar] public float health;
    9.         [SyncVar] public float maxHealth;
    10.         [SyncVar] public float level;
    11.         [SyncVar] public float gold;
    12.         [SyncVar] public float fighting;
    13.         [SyncVar] public float magicFighting;
    14.         [SyncVar] public float shielding;
    15.         [SyncVar] public float magicResist;
    16.         [SyncVar] public float walkSpeedMultilpier;
    17.    
    18.  
    19.     void Start () {
    20.         StartCoroutine (onCoroutine());
    21.         StartCoroutine (healthCoroutine());
    22.     }
    23.    
    24.         IEnumerator onCoroutine()
    25.         {
    26.         while(true)
    27.          {
    28.             walkSpeedMultilpier = PlayerPrefs.GetFloat("walkSpeedMultilpier");
    29.             fighting = PlayerPrefs.GetFloat("fighting");
    30.             shielding = PlayerPrefs.GetFloat("shielding");
    31.             magicResist = PlayerPrefs.GetFloat("magicResist");  
    32.             magicFighting = PlayerPrefs.GetFloat("magicFighting");
    33.            
    34.             yield return new WaitForSeconds(2f);
    35.         }
    36.         }
    37.        
    38.         IEnumerator healthCoroutine()
    39.         {
    40.         while(true)
    41.          {
    42.             health = PlayerPrefs.GetFloat("health");
    43.             maxHealth = PlayerPrefs.GetFloat("maxHealth");
    44.            
    45.             yield return new WaitForSeconds(0.5f);
    46.         }
    47.         }
    48.        
    49. }
     
  6. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    Remember that SyncVar is from server to clients. Clients don't talk to clients. If your game logic is running on the client then you use a command from the player client to set the variable on the server. The server will then sync it to all the clients. For stat setting though it would probably be much better to only have the server set stats and let it sync across the network using the SyncVar.
     
  7. Xazerek

    Xazerek

    Joined:
    Nov 3, 2014
    Posts:
    134
    @GTGD Could u please make small example?
     
  8. Xazerek

    Xazerek

    Joined:
    Nov 3, 2014
    Posts:
    134
    And i have one more question. Why if one player make button active, all players see that button?
    Script for make button visible:
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class Vendor1Trigger : MonoBehaviour {
    6.  
    7.     public GameObject bankButton;
    8.  
    9. void OnTriggerEnter(Collider other) {
    10.     if(other.tag == "Player") {
    11.         bankButton.SetActive(true);
    12.     }
    13. }
    14.  
    15. void OnTriggerExit(Collider other) {
    16.     if(other.tag == "Player") {
    17.         bankButton.SetActive(false);
    18.     }
    19. }
    20.  
    21. }
    22.  
    This script is attached to my vendor game object.
     
  9. awplays49

    awplays49

    Joined:
    Nov 9, 2014
    Posts:
    36
    Hey good videos! Although I have this code but clients aren't syncing to the server. Do you know what went wrong?

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Networking;
    3. using System.Collections;
    4.  
    5. [NetworkSettings (channel = 0, sendInterval =  0.033f)]
    6. public class NetworkTransformSync : NetworkBehaviour {
    7.  
    8.     public bool syncPosition;
    9.     public bool syncRotationY;
    10.     [SyncVar]
    11.     private Vector3 syncPos;
    12.     [SyncVar]
    13.     private float syncRotY;
    14.     public float lerpRate;
    15.  
    16.     void FixedUpdate () {
    17.         TransmitSync ();
    18.         LerpTransform ();
    19.     }
    20.  
    21.     void LerpTransform () {
    22.         if (!isLocalPlayer)
    23.         {
    24.             transform.position = Vector3.Lerp (transform.position, syncPos, lerpRate * Time.deltaTime);
    25.             transform.rotation = Quaternion.Lerp (transform.rotation, Quaternion.Euler (0, syncRotY,  0), lerpRate * Time.deltaTime);
    26.         }
    27.     }
    28.  
    29.     [Command]
    30.     void CmdSyncTransform () {
    31.         if (syncPosition)
    32.         {
    33.             syncPos = transform.position;
    34.         }
    35.         if (syncRotationY)
    36.         {
    37.             syncRotY = transform.rotation.y;
    38.         }
    39.     }
    40.  
    41.     [ClientCallback]
    42.     void TransmitSync () {
    43.         if (isLocalPlayer)
    44.         {
    45.             CmdSyncTransform ();
    46.         }
    47.     }
    48. }
    49.  
     
  10. bioert

    bioert

    Joined:
    Nov 9, 2014
    Posts:
    8
    Thanks for the excellent tutorials!

    Got a question regarding the method you use for naming GameObjects. You often use a Set Unique name function and use a Manager Script that have a reference number, in the zombie case, you set the name using a counter.

    What about other GameObjects in the world?, Do you manage that by creating Manager lists to keep record of each individual name?

    I'm following the tutorials but adding saving, loading, crafting, building and re spawning features to it.
    Having for example Trees that can receive damage and provide items turn to be complicated just for the GameObject Name (must be unique).

    I use 3D brush tool from Mesh Maker (https://www.assetstore.unity3d.com/en/#!/content/11625) to place my trees and environment gameobjects in scene. Mesh Maker author was very kind to add a Random GameObject name feature to temporarily address this problem I'm having.

    I haven't got to the part of saving the environment state, but I guess I would need some kind of GameObject Manager that keep track of each GameObject name, transform and when new GameObjects spawn, set Unique ID.
     
  11. IanSmellis

    IanSmellis

    Joined:
    Nov 2, 2014
    Posts:
    26
    Since the new version of Unity, the FPS camera will not move up or down once I add the networking stuff in Part 1 and Part 2. Any ideas? I know I am not the only one having this problem.

    Thank You
     
  12. bioert

    bioert

    Joined:
    Nov 9, 2014
    Posts:
    8
    Try maybe using "islocalplayer" function inside the OnTrigger functions. Your code only react to players entering a trigger zone and in Multiplayer each Player Object have the tag "Player", so when another player enter your vendor trigger zone It will activate the Button for everyone because you have a object with tag "Player" activating it.
     
  13. PaybackTony

    PaybackTony

    Joined:
    Mar 11, 2012
    Posts:
    5
    I wanted to ping this thread and add a little something I noticed in 5.2.x trying the first parts (interpolation) of this tut. I can't speak for 5.1, but in 5.2 don't forget (as I think it is mentioned in one vid) to disable the Network Transform script on the player prefab. If you don't, both the rotation and position interpolation will be very jumpy as both the pre-built interpolation in the default NetworkTransform.cs unity script and the ones from this tut will be updating position. The interpolation in this tut is much smoother than the default, so I recommend implementing it.

    It's simple to disable, just uncheck it (if it exists) when the player prefab is selected in the scene (you may have to drop it in first). You can also (the right way) click the cog and remove the scrip from the prefab all together. I always recommend doing your own stuff in transform and player state sync, as you can optimize based on game type.
     
  14. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    By the way everyone, I have a new tutorial series rolling out, Gamer To Game Developer Series 3 that focuses on single player first person shooter mechanics. Here's a video of it in action, and the Unity forum thread with links to all the videos.

     
    BackwoodsGaming and IanSmellis like this.
  15. faneric

    faneric

    Joined:
    May 15, 2013
    Posts:
    10
    Many thanks to you, this really helps me a lot!
     
  16. Mumrikaren

    Mumrikaren

    Joined:
    Oct 29, 2015
    Posts:
    3
    Hey do you know what the problem i have in episode 7 Unique Identity is.
    When i start the game the player names are Player 2 and Player 3 instead of Player 1 and Player 2.
    I don't think there is anything wrong with the code but if you could just point me in the right direction.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Networking;
    3.  
    4. public class PlayerID : NetworkBehaviour {
    5.  
    6.     [SyncVar] private string playerUniqueIdentity;
    7.  
    8.     private NetworkInstanceId playerNetID;
    9.  
    10.     void Update()
    11.     {
    12.         if(transform.name == "" || transform.name == "Player(Clone)")
    13.         {
    14.             SetIdentity();
    15.         }
    16.     }
    17.  
    18.     public override void OnStartLocalPlayer()
    19.     {
    20.         GetNetIdentity();
    21.         SetIdentity();
    22.     }
    23.  
    24.     [Client]
    25.     void GetNetIdentity()
    26.     {
    27.         playerNetID = GetComponent<NetworkIdentity>().netId;
    28.         CmdTellServerMyIdentity(MakeUniqueIdentity());
    29.     }
    30.  
    31.     void SetIdentity()
    32.     {
    33.         if(!isLocalPlayer)
    34.         {
    35.             transform.name = playerUniqueIdentity;
    36.         }
    37.         else
    38.         {
    39.             transform.name = MakeUniqueIdentity();
    40.         }
    41.     }
    42.  
    43.     string MakeUniqueIdentity()
    44.     {
    45.         string uniqueIdentity = "Player " + playerNetID.ToString();
    46.         return uniqueIdentity;
    47.     }
    48.  
    49.     [Command]
    50.     void CmdTellServerMyIdentity(string _identity)
    51.     {
    52.         playerUniqueIdentity = _identity;
    53.     }
    54. }
     
  17. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    Hello, There's nothing wrong with your code. It's just however the network ID numbers are being generated in the background. My objective here is to just have a simple way of ensuring that each networked player GameObject has a unique name for referencing purposes. I would actually make another script for actually capturing the player name and syncing that across the network, and then I'd display that name above the player's head.
     
    IanSmellis likes this.
  18. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    You're welcome!
     
  19. ronbonomo

    ronbonomo

    Joined:
    Oct 15, 2015
    Posts:
    32
    This code gives me nothing but errors. could you help me figure out why
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class AreaExplosion : MonoBehaviour {
    5.     private Collider[] hitColliders;
    6.     public float blastRadius;
    7.     public float explosionPower;
    8.     public float destroyTime;
    9.  
    10.     void OnCollisionEnter(Collision col)
    11.     {
    12.         ExplosionWork(col.contacts [0].point);
    13.         Destroy (GameObject);
    14.     }
    15.  
    16.     void ExplosionWork(Vector3 explosionPoint){
    17.         hitColliders = Physics.OverlapSphere(explosionPoint, blastRadius);
    18.         foreach (Collider hitCol in hitColliders)
    19.             if (hitCol.GetComponent<Rigidbody> () != null)
    20.                 hitCol.GetComponent<Rigidbody> ().isKinematic = false;
    21.         hitCol.GetComponent<Rigidbody> ().AddExplosionForce(explosionPower, explosionPoint, blastRadius, 1, ForceMode.Impulse);
    22.     }
    23.    
    24. }
    and on the initiate script it teels me TransFormPoint has not been used and get errors all in that one as well. mine is just like yours, can't figure out why i get errors and you don't. I am not to worried about the shooting one though, I have another method, but like having options, which is why I liked yours and trying to get it to work. But really interested in the explosion one. Great area one. Outstanding really

    Sorry, I'm an idiot, I fixed that. Just messes up when I try to add in the if enemy part, but will figure that out. If you could help me with your shooting though, that would be awesome. Only part sending error is the TransformPoint has not been used. Can't get a grasp on that one. Thanks, and looking forward to the other tutorials. Then I will put them all together and show you what you taught me. Already made my own character models and planned out game play scenes ;)
     
    Last edited: Nov 9, 2015
  20. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    The foreach loop isn't written properly. You need to enclose the instructions within it with {}. Please see the scripting tutorial from Unity on loops.
     
    IanSmellis likes this.
  21. ronbonomo

    ronbonomo

    Joined:
    Oct 15, 2015
    Posts:
    32
    Yes, I saw I missed that. And fixed the TransfomPoint issue as well. Stupid mistake withe the {} on first issue. I need to learn I can't go at it 24/7. Get to wore down and do stupid mistakes. Same problem I had when I taught myself dark basic years ago and made a 2d mmo game, self hosted from computers I built for servers. I am just one guy trying to do it all, so I push myself beyond what I should. I stumbled on Unity last month and been hitting it hard to learn so I can remake my 2d game to better 3d version. Lessons that I watch of yours help sooo much and I really appreciate you. I like Mike gieg as well but I have learned more from your videos than anyone. Thanks alot man, and thanks for your reply
     
    IanSmellis likes this.
  22. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    That's a really impressive feat that you built your own 2d mmo and setup your own servers back in the day! I think once you get used to using Unity and it's API you'll just be blazing ahead.
     
  23. ronbonomo

    ronbonomo

    Joined:
    Oct 15, 2015
    Posts:
    32
    It wasn't easy, lol. Yes Unity is a really awesome tool. I was Thinking of using Azure for hosting this time, instead of building a server/client and building servers. But haven't made up my mind on that. More focused with learning everything right now and will come back to that topic. I plan on giving you made cred when I get rolling with game play. And then go pro on unity. Your videos have made this process pretty painless. I watch all your videos on youtube over and over and over, make sure I have a grasp before I start working on the topic and apply it in few different ways so I can truly understand what is going on. I tip my hat to you
     
  24. ronbonomo

    ronbonomo

    Joined:
    Oct 15, 2015
    Posts:
    32
    Like last night/ this morning I made a trigger system in a maze that allowed to go through a wall, but if you don't notice you can you will be attacked by spawned monsters and cannons shoot grenades at you, so better find that wall lol. And I changed the explosion script so it looks for tags and layers, so different effect between buildings to effect and players/enemies, which for players/enemies it turns off inKinematic, applies dmg then turn is kinematic back on, so they don't go through the terrain when they hit the ground, but looks cool when hit
     
    Last edited: Nov 10, 2015
  25. Deleted User

    Deleted User

    Guest

    Hello Gamertogamedeveloper,

    First I want to thank you for making detailed tutorial about uNet. It made me learn much about the new Unity networking system. And so I'm trying to make a sort of derby game where players can drive around on a platform, knock other players off the platform and score points. Currently the players can move around smoothly. But here's the problem: when 2 players collide into each other it all gets very jittery and the collision itself doesnt look realistic and players don't move around as smoothly as before. So I tried to make the server handle this collision more smoothly and realisticly by setting the rigidbody's for the other clients to kinematic and when a collision occurs makes the other rigidbody non-kinematic for a brief second so the collision can be excecuted. But this only seems to work only as the other player is moving and Im collide with him from behind. So Im a little bit clueless now him to proceed and make it really work. :/

    Anyway here is the code I'm using right now:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.Networking;
    4.  
    5. [NetworkSettings(channel = 0, sendInterval = 0.03f)]
    6. public class PlayerNetworkBehaviour : NetworkBehaviour
    7. {
    8.     [SerializeField]Camera Camera;
    9.     [SerializeField]AudioListener audiolistener;
    10.     [SerializeField]private Carscript carscript;
    11.     private Rigidbody m_rigidBody;
    12.     private Transform PlayerTransform;
    13.     [SerializeField]private Vector3 CollisionDirection;
    14.     [SerializeField]private bool isColliding = false;
    15.  
    16.     // Use this for initialization
    17.     [Client]
    18.     void Start ()
    19.     {
    20.         PlayerTransform = transform;
    21.         m_rigidBody = GetComponent<Rigidbody>();
    22.         carscript = GetComponent<Carscript>();
    23.         //speed = carscript.currentSpeed;
    24.         if(isLocalPlayer)
    25.         {
    26.             GameObject.Find("Scenecamera").SetActive(false);
    27.             carscript.enabled = true;
    28.             Camera.enabled = true;
    29.             audiolistener.enabled = true;
    30.         }
    31.         if (!isLocalPlayer && !isColliding)
    32.         {
    33.             m_rigidBody.isKinematic = true;
    34.         }
    35.         else if(!isLocalPlayer && isColliding)
    36.         {
    37.             m_rigidBody.isKinematic = false;
    38.         }
    39.     }
    40.  
    41.     [Client]
    42.     void OnCollisionEnter(Collision col)
    43.     {
    44.         if(col.transform.tag == "Player" && !isLocalPlayer)
    45.         {
    46.             string uIdentity = col.transform.name;
    47.             Vector3 Myposition = transform.position;
    48.             //float Realspeed = speed * 10f;
    49.             CmdTellServerAboutCollision(uIdentity,Myposition);
    50.         }
    51.     }
    52.  
    53.     [Command]
    54.     void CmdTellServerAboutCollision(string uniqueID,Vector3 mypos)
    55.     {
    56.         GameObject Go = GameObject.Find (uniqueID);
    57.         Go.GetComponent<PlayerNetworkBehaviour> ().isColliding = true;
    58.         Vector3 colpos = Go.transform.position;
    59.         CollisionDirection = (mypos - colpos);
    60.         Go.GetComponent<Rigidbody> ().AddRelativeForce (CollisionDirection.normalized * 100f, ForceMode.Impulse);
    61.         Go.GetComponent<PlayerNetworkBehaviour> ().isColliding = false;
    62.     }
    63. }
    Like I said, I hope you or any other person who knows how to deal with this can push me into the right direction.

    Edit:
    Got it working! I just had to make an other function which applies the forces locally on the player.
     
    Last edited by a moderator: Nov 17, 2015
  26. larmst

    larmst

    Joined:
    Oct 1, 2014
    Posts:
    12
    When hosting a game I have multiple clients join, the position sync looks very smooth between client and server, but the movement between client and client is very choppy. Is there a bug fix or something I may have missed in the tutorials that would cause the historic interpolation to fail for the client -> server -> client sync?

    For example, I host a game as a server, client 1 joins and the movement between client 1 and server is good. Client 2 joins and the movement between client 2 and server is good. The movement is very poor between client 1 and client 2.

    Hopefully this makes sense, and any help is appreciated!
    Cheers
     
  27. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,173
  28. Velo222

    Velo222

    Joined:
    Apr 29, 2012
    Posts:
    1,437
    The "Network Animator" component does not seem to be working in Unity 5.2.x. Can anyone confirm this?

    I'm using 5.2.1p2 right now, and the host client animations play just fine, but any other client does not even play the animations at all.
     
  29. John-Void

    John-Void

    Joined:
    Dec 13, 2014
    Posts:
    3
    I am having trouble with recreating game as host. I was adding more buttons to UI and when I create game as host - everything is cool, then I leave the game and go to an offline scene - I am getting errors regarding multiple network managers, and for some reason network manager does not apply onclick function to a starthost button

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.Networking;
    4. using UnityEngine.UI;
    5.  
    6. public class NetworkManager_Custom : NetworkManager {
    7.  
    8.     private GameObject DiscButton;
    9.  
    10.     public void StartupHost()
    11.     {
    12.         SetPort();
    13.         NetworkManager.singleton.StartHost();
    14.     }
    15.  
    16.     public void JoinGame()
    17.     {
    18.         SetIPAddress();
    19.         SetPort();
    20.         NetworkManager.singleton.StartClient();
    21.     }
    22.  
    23.     void SetIPAddress()
    24.     {
    25.         string ipAddress = GameObject.Find("InputFieldIPAddress").transform.FindChild("Text").GetComponent<Text>().text;
    26.         NetworkManager.singleton.networkAddress = ipAddress;
    27.     }
    28.  
    29.     void SetPort()
    30.     {
    31.         NetworkManager.singleton.networkPort = 7777;
    32.     }
    33.  
    34.     void OnLevelWasLoaded (int level)
    35.     {
    36.         if(level == 1)
    37.         {
    38.             StartCoroutine(SetupMenuSceneButtons());
    39.         }
    40.  
    41.         if(level == 2)
    42.         {
    43.             StartCoroutine(SetupOtherSceneButtons());
    44.         }
    45.     }
    46.  
    47.     IEnumerator SetupMenuSceneButtons()
    48.     {
    49.         yield return new WaitForSeconds(0.3f);
    50.  
    51.         GameObject.Find("/UI/StartGame/StartHost").GetComponent<Button>().onClick.RemoveAllListeners();
    52.         GameObject.Find("/UI/StartGame/StartHost/").GetComponent<Button>().onClick.AddListener(StartupHost);
    53.    
    54.         GameObject.Find("/UI/StartGame/StartClient").GetComponent<Button>().onClick.RemoveAllListeners();
    55.         GameObject.Find("/UI/StartGame/StartClient/").GetComponent<Button>().onClick.AddListener(JoinGame);
    56.     }
    57.  
    58.     IEnumerator SetupOtherSceneButtons()
    59.     {
    60.         yield return new WaitForSeconds(0.3f);
    61.    
    62.         DiscButton = GameObject.Find("GameManager").GetComponent<GameManager_References>().DiscButton;
    63.         DiscButton.GetComponent<Button>().onClick.AddListener(NetworkManager.singleton.StopHost);
    64.     }
    65.  
    66. }

    [Update]
    Aight, so I simply made another game manager, but in the menu scene and made a reference to start and join buttons and everything seems to be working in the editor.
    I can switch back and forward between game and menu scenes, but for some unknown reason when I actually build the game - buttons stop working. here is the updated version of the script

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using UnityEngine.Networking;
    5. using UnityEngine.UI;
    6.  
    7. public class NetworkManager_Custom : NetworkManager {
    8.  
    9.     private GameObject DiscButton;
    10.     private GameObject rtuyu;
    11.  
    12.     public void StartupHost()
    13.     {
    14.         SetPort();
    15.         NetworkManager.singleton.StartHost();
    16.     }
    17.  
    18.     public void JoinGame()
    19.     {
    20.         SetIPAddress();
    21.         SetPort();
    22.         NetworkManager.singleton.StartClient();
    23.     }
    24.  
    25.     void SetIPAddress()
    26.     {
    27.         string ipAddress = GameObject.Find("InputFieldIPAddress").transform.FindChild("Text").GetComponent<Text>().text;
    28.         NetworkManager.singleton.networkAddress = ipAddress;
    29.     }
    30.  
    31.     void SetPort()
    32.     {
    33.         NetworkManager.singleton.networkPort = 7777;
    34.     }
    35.  
    36.     void OnLevelWasLoaded (int level)
    37.     {
    38.         if(level == 1)
    39.         {
    40.             //SetupMenuSceneButtons();
    41.             StartCoroutine(SetupMenuSceneButtons());
    42.         }
    43.  
    44.         if(level == 2)
    45.         {
    46.             //SetupOtherSceneButtons();
    47.             StartCoroutine(SetupOtherSceneButtons());
    48.         }
    49.     }
    50.  
    51.     IEnumerator SetupMenuSceneButtons()
    52.     {
    53.         yield return new WaitForSeconds(0.3f);
    54.      
    55.         rtuyu = GameObject.Find("MenuScripts").GetComponent<QuitApplication>().stratganne;
    56.         rtuyu.GetComponent<Button>().onClick.RemoveAllListeners();
    57.         rtuyu.GetComponent<Button>().onClick.AddListener(StartupHost);
    58.  
    59.     }
    60.  
    61.     //void SetupOtherSceneButtons()
    62.     IEnumerator SetupOtherSceneButtons()
    63.     {
    64.         yield return new WaitForSeconds(0.3f);
    65.      
    66.         DiscButton = GameObject.Find("GameManager").GetComponent<GameManager_References>().DiscButton;
    67.         DiscButton.GetComponent<Button>().onClick.RemoveAllListeners();
    68.         DiscButton.GetComponent<Button>().onClick.AddListener(NetworkManager.singleton.StopHost);
    69.     }
    70.  
    71. }
    72.  

    Ok, got it to work now!
    just add NetworkServer.Reset(); to a StartupHost() function!
    hope that helps anyone
     
    Last edited: Nov 29, 2015
  30. Eiseno

    Eiseno

    Joined:
    Nov 1, 2015
    Posts:
    86
    Why dont use network transform ? for better performance should i make custom script (sync pos-rot) or use unity network transform script ?
     
  31. Dimilicious

    Dimilicious

    Joined:
    Oct 19, 2015
    Posts:
    14
    Great series! Hope you will continue making UNET tutorials.
    I have a question to PlayerSyncRotation script. It doesn't really work on my computer properly. The player in the camera view is just jiggling around...no smooth rotation. The only one thing that helps is increasing the lerpRate considerably. In my case to minimum 150 instead of 20. What i'm doing wrong? The PlayerSyncRotation script is identical to your script.
    Maybe somebody of you guys have an idea?
     
    Last edited: Dec 2, 2015
  32. Vadyy

    Vadyy

    Joined:
    Jan 26, 2014
    Posts:
    2
    Hey, can anyone help me? I'm getting these errors while trying to host.

    "cannot open socket on ip {*} and port {7777} check please your network,most probably port has been already occupied"
    "startserver listen failed"

    I portforwarded 7777, I don't have another instance of the game open while hosting.
     
  33. vanpro

    vanpro

    Joined:
    Jan 3, 2016
    Posts:
    8
    The ui button's function seems not working again in 5.3. I barely can host or join game in my surface pro 3.

    [Update]
    As said above, just add NetworkServer.Reset(); to the StartupHost() function and it works like a charm now!
     
    Last edited: Jan 3, 2016
    abhishek_hingorani likes this.
  34. connorsrm

    connorsrm

    Joined:
    Jan 13, 2016
    Posts:
    5
    Greetings!

    Thank you very much for making this tutorial, it provided a great utility to dive into the unity networking system. I've been hitting a strange snag, however, when I try to step through the tutorials again as a refresher.

    For some reason the minute I add a network identity to my FPSCharacter during the first video, I lose all Mouse Y detection. My camera will rotate left and right but will no longer look up and down.

    Has anyone else hit this issue?

    Thanks
     
  35. arnesso

    arnesso

    Joined:
    Mar 3, 2015
    Posts:
    96
    Hi,

    Thank you for your videos, I would ask about a single player game ( UFPS) can be "converted" to multiplayer with this UNET , If someone did similiar could he give a tips how ?
    I would like if players will be able to connect each other via Hamachi (LAN) to connect one player anotherone player's game.
    Thank you
    cheers
     
  36. belive_in

    belive_in

    Joined:
    Aug 18, 2015
    Posts:
    5
    HI,Did you have to solve this question? I met the same question
     
  37. pKallv

    pKallv

    Joined:
    Mar 2, 2014
    Posts:
    1,173
  38. kilik128

    kilik128

    Joined:
    Jul 15, 2013
    Posts:
    909
    Any idea about android it's possible to create serverweb from it
     
  39. tobiushirogeri

    tobiushirogeri

    Joined:
    Feb 16, 2014
    Posts:
    1
    Awesome tutorial series, thanks !
    I'm trying to merge it with a 3rd person view camera but can't quite figure out how to get it working :
    When the host starts the game, everything is fine, but as soon as anoter player logs in, his camera is moved to the new player prefab. Only when the other player quits the server, his camera will come back to him.
    (I've got the camera attached to the player prefab)
    I've been reading around and trying some stuff but have been block on this for days..
    Anyone faced a same issue ?
     
  40. Heatmanofurioso

    Heatmanofurioso

    Joined:
    Mar 3, 2016
    Posts:
    8
    Hi. Great videos! Really have helped me out with my skills and have been giving me alot of insight into building working Multiplayer projects.
    One question, might be in a more advanced video"haven't advanced alot yet".
    I have made a loading/spash screen. But i would like to add information to it. It currently shows a percentage bar with the loading progress. But i wanted it so show information like, loading sounds, assets, textures, etc.
    Any idea how i pick up this information to show on the text?
     
  41. Nosfera

    Nosfera

    Joined:
    Sep 26, 2014
    Posts:
    12
    I'm working on my final college project, it is a fps multiplayer and I made a very simple weapon system that works perfectly locally. However when trying to convert to multiplayer I can't fix some issues. The first one and most basic in my opinion is I can't switch weapon in all clients. I've tried to use RpcClient and Commant but still no results. Basically, I have a class in the weapon that holds its attribute, including the projectile. From another class (WeaponManager), I set the activeWeapon parameters, including the active projectile (member variable) to be instantiated on the server via [Command]. The thing is, by not using [Command] on "RpcChangeWeapon" method, the instantiated bullet on server is always the same (it not changes), but on client it works fine. Otherwise, If I use [Command] on "RpcChangeWeapon", the instantiated bullet works fine on the server, but in the client the player do not change his weapon :(.

    I would love to get some help, so I can continue my final project :/ Thank you.

    public class WeaponManager : NetworkBehaviour {

    //Script References
    UIManager m_UIManager;
    BaseWeapon m_baseWeapon;
    ShootNetworkManager m_shootNetworkManager;

    //Public variables
    public GameObject m_activeWeapon;
    public GameObject m_primaryWeapon;
    public GameObject m_secondaryWeapon;

    public GameObject m_activeBullet;
    public Transform m_spawnBullet;


    //Private variables
    int m_weaponIndex = 0;
    float m_cooldown;

    //just testing
    public float F***ingfirerate = 1f;


    void Awake()
    {
    m_shootNetworkManager = GetComponent<ShootNetworkManager> ();
    m_baseWeapon = GetComponentInChildren<BaseWeapon> ();
    }


    void Start()
    {
    m_UIManager = GameObject.Find ("PlayerUI").GetComponent<UIManager>();
    SetActiveWeapon(m_primaryWeapon);
    }

    void Update()
    {
    if (!isLocalPlayer)
    return;

    if (!m_activeWeapon.GetComponent<BaseWeapon> ().m_isRecharging) {
    if (Input.GetKeyDown (KeyCode.Tab)) {
    RpcChangeWeapon ();
    }
    }

    m_cooldown -= Time.deltaTime;

    if (Input.GetButton ("Fire1") && m_cooldown <= 0f && !m_baseWeapon.m_isRecharging)
    CheckBullets();

    if (Input.GetKeyDown (KeyCode.R) && !m_baseWeapon.m_isRecharging)
    StartCoroutine(Recharge ());

    }

    void CheckBullets()
    {

    if (m_baseWeapon.m_loadedBullets > 0) {
    CmdFire ();
    m_cooldown = m_baseWeapon.m_fireRate;
    m_baseWeapon.m_loadedBullets--;
    } else {
    StartCoroutine(Recharge ());
    }
    }


    [Command]
    void CmdFire()
    {

    // create the bullet object from the bullet prefab
    var bullet = (GameObject)Instantiate(
    m_activeBullet,
    m_spawnBullet.position,
    m_spawnBullet.rotation);

    // make the bullet move away in front of the player
    bullet.GetComponent<Rigidbody>().AddRelativeForce(Vector3.forward * 400f);

    NetworkServer.Spawn (bullet);

    // make bullet disappear after 2 seconds
    Destroy(bullet, 2.0f);
    }

    IEnumerator Recharge()
    {
    if (m_baseWeapon.m_remainingBullets > 0) {
    m_baseWeapon.m_isRecharging = true;

    yield return new WaitForSeconds (m_baseWeapon.m_rechargebleTime);

    m_baseWeapon.m_isRecharging = false;
    int bulletsNeed = m_baseWeapon.m_maxBulletsPerCartridge - m_baseWeapon.m_loadedBullets;

    for (int i = 0; i < bulletsNeed; i++) {

    m_baseWeapon.m_remainingBullets--;
    m_baseWeapon.m_loadedBullets++;

    if (m_baseWeapon.m_remainingBullets <= 0) {
    m_baseWeapon.m_remainingBullets = 0;
    break;
    }
    }
    }
    }

    void SetActiveWeapon(GameObject weapon)
    {
    m_activeWeapon = weapon;
    m_baseWeapon = m_activeWeapon.GetComponent<BaseWeapon> ();
    m_activeBullet = m_baseWeapon.m_projectile;
    m_spawnBullet = m_baseWeapon.m_projectileSpawn;
    }

    [ClientRpc]
    void RpcChangeWeapon()
    {

    m_weaponIndex++;

    switch (m_weaponIndex) {
    case 0:
    SetActiveWeapon (m_primaryWeapon);
    m_primaryWeapon.SetActive (true);
    m_secondaryWeapon.SetActive (false);
    break;
    case 1:
    SetActiveWeapon (m_secondaryWeapon);
    m_secondaryWeapon.SetActive (true);
    m_primaryWeapon.SetActive (false);
    break;
    }

    m_UIManager.SetWeaponUI(m_activeWeapon.GetComponent<BaseWeapon>());

    if (m_weaponIndex >= 1)
    m_weaponIndex = -1;

    }

    }
     
  42. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    Commands tell the server to run a method. The command is sent from a local player. The command method only runs on the server.
    Client RPCs tell the client to run a method. The RPC is sent from the server to clients. The ClientRPC method only runs on clients.
    The SyncVar attribute can be used to synchronise simple types (such as float, int, string,etc.) from the server to the clients and you can use a hook to automatically carry out a method on clients when that variable is updated on the client.

    You have to to design your system to make use of the above.
     
  43. Nosfera

    Nosfera

    Joined:
    Sep 26, 2014
    Posts:
    12

    I know that :/
    I just can't figure it out how to do that. Is there any example that changes weapon in runtime you can show me?
    I would appreciate.
     
  44. Comolokko

    Comolokko

    Joined:
    Jul 24, 2014
    Posts:
    28
    @GTGD Thank you so much for this awsome tutorials!
     
  45. vanpro

    vanpro

    Joined:
    Jan 3, 2016
    Posts:
    8
    Currently I'm testing my client in different pc using Hamachi, the client player moved in the server pc perfectly, but my player in host pc does not move in client pc at all. Any clue for this? It worked ok in the same pc with client and host. I've finished the part 20 : UI and custom net manager tutorial btw.

    [EDIT] I put the sync data inside a structure, can SyncVars sync complex data type across different machine boundary?
     
    Last edited: May 1, 2016
  46. VeidoAugalu

    VeidoAugalu

    Joined:
    Apr 27, 2016
    Posts:
    1
    Hey, awesome tutorial, love it so far, but has anyone got a zip of all the videos together I could download? I plan on watching it at school and the Internet there is terrible, thanks.
     
  47. justcallmeb

    justcallmeb

    Joined:
    Jul 14, 2016
    Posts:
    4
    Excuse me, can UNET work with different networks, not LAN ?
     
  48. ChrisSch

    ChrisSch

    Joined:
    Feb 15, 2013
    Posts:
    763
    Yes UNET works both for online and LAN.
     
  49. moh05

    moh05

    Joined:
    Nov 26, 2015
    Posts:
    65
    Hello there,

    I didnt go to the tutorial yet. Wanted to ask if it suits for a simple 2 player card game. Thank you
     
  50. ahmadian

    ahmadian

    Joined:
    Nov 24, 2015
    Posts:
    44
    just use save from net to download them from youtube ;D