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

GTGD's Unity Multiplayer Tutorials

Discussion in 'Community Learning & Teaching' started by GTGD, Feb 7, 2012.

?

Please select each option you agree with (you can select multiple options)

Poll closed Dec 22, 2015.
  1. I like that the videos are covering a complete project.

    230 vote(s)
    88.1%
  2. I find the videos are detailed enough for me to understand and follow.

    197 vote(s)
    75.5%
  3. I find the video quality is clear enough.

    186 vote(s)
    71.3%
  4. I find the audio quality is clear enough.

    180 vote(s)
    69.0%
  5. The narrator doesn't send me to sleep.

    143 vote(s)
    54.8%
  6. In general the topics covered are interesting.

    170 vote(s)
    65.1%
  7. I find the website useful.

    130 vote(s)
    49.8%
  8. The Gamer To Game Developer logo looks good.

    119 vote(s)
    45.6%
  9. I would like to suggest topics that GTGD should cover in the future.

    103 vote(s)
    39.5%
Multiple votes are allowed.
  1. BloodyRayne89

    BloodyRayne89

    Joined:
    Oct 16, 2011
    Posts:
    31
    Hey GTGD i thought the terraintoolkit u gave me was for like in real time generation but this is just for like the editor :OO

    i want the terrain generator to be like minecraft and that would make my game(with ur tutorial :DDD)be n1ce
     
  2. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    A real time terrain generator :eek:. Well that's way, way, beyond my knowledge BloodRayne89. I'd recommend searching the forums because I remember reading posts of other Unity developers building Minecraft like terrains.

    It looks like you'll have an ambitious project on your hands so be patient and mentally prepare yourself to spend months and months studying and trying out new code. Break your project down into little pieces and work away bit by bit until you get to the end. It will take a lot of effort but anyone can achieve their goal if they are patient and persistent and don't flip to another project.

    Oh, and make sure you have a clear goal :)!
     
  3. BloodyRayne89

    BloodyRayne89

    Joined:
    Oct 16, 2011
    Posts:
    31
    Hmm ok GTGD, i am just a medium knowledge modeler so thats y i cant code lol
     
  4. bajeo

    bajeo

    Joined:
    Dec 5, 2011
    Posts:
    75
    Hey ive managed to get the Master Server working with several clients.

    Users can now host a game and clients can view all hosted games via the Master Server. Hosts can select levels and all clients load into that level.

    I managed to fix that bug i had... i couldnt quite workout where my error occurred. It kinda magically fixed itself when i retyped several sections in one go so guessing it was a tiny syntax error somewhere. I think my original problem was with the level loading rather than server setup as you change channels at this point so player communications was probably split.

    Ill be posting the code soon as i fix one final bug ive got... My camera always follows the first person in the scene (for all players). My camera system is completely different to yours since its 3rd person with occlusion testing etc.. Not sure if you will have the same bug if you take my code tho so id rather fix it first.
     
  5. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    That's so awesome bajeo! Please do post up the scripts once you're done and please comment it so that we can understand how it works. With your permission I'd like to make videos on what you've done and probably make it a part of series 2.
     
  6. bajeo

    bajeo

    Joined:
    Dec 5, 2011
    Posts:
    75
    Sure no problem! Happy to help.

    The scripts are pretty simple (you may even want to edit them slightly yourself) as i havent properly coded returning to the main menu.

    One or two changes are required to your MultiplayerScript (just to server creation section) and an additional LevelLoading script is needed (in javascript for some strange reason when i translated it into c# it has some weird behaviour) . Thats all so far. Think ive (in my head) just solved my camera problem so ill test it when i get home from work then start commenting.

    Total time to implement it into your project should be under 30mins + tweaking and bug fixes. (which i also have to do in future :p)
     
  7. BloodyRayne89

    BloodyRayne89

    Joined:
    Oct 16, 2011
    Posts:
    31
    Hey GTGD, if u have some spare time for the part 2 series can u make a cube terrain generator?

    I would be very happy for u if u do the tutorial and put u in credits for my game :)
     
  8. Lantos

    Lantos

    Joined:
    Feb 12, 2012
    Posts:
    10
    I love the series, and I plan to add a lot to the my game.

    I was wondering how much you will make make for the UI?

    would it be possible to make an action bar, drag and drop? since i plan to add lots of weapons, and other stuff.

    Keep up the good work.
     
  9. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    Thanks Lantos. We won't be doing much with the UI for series 1 but I am intending to look into a drag drop inventory system for series 2, though I don't know when I'll be releasing series 2 as I first have to finish all the series 1 videos and then I'll have to learn all that new code!

    There might be some tutorials out there that explain how to setup an inventory system. I'd suggest having a look at BergZerg arcades RPG tutorials as it looks like he has a number of videos about an inventory system, though I haven't had enough time to watch them so I don't know what they cover.
     
  10. bajeo

    bajeo

    Joined:
    Dec 5, 2011
    Posts:
    75
    Finally ironed out most of the bugs with the networking over the web players can join and see each other and the server controls which level is loaded (and can change levels at anytime). I am noticing some differences thought between the tutorials and what i have to write to make the code work (particularly with OnJoinServer style functions as the player joins the server before the level is loaded so it cant access player data). Working on getting people to exit the game cleanly as atm the server seems to take quite a while to recover when players leave and had it even crash once or twice (but think it was just my PC lol).

    Should hopefully have the code ready in a few days. Where abouts should i post it? Here or PM? There may be a bit of back and forth because of the code changes all over the place but the actual networking code is pretty straight forward.
     
  11. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    Thanks for keeping us updated on your progress bajeo. It's probably better to post the code up in the forums so that it's available to everyone and you could post it here or you could even create a new thread and post the link to that thread here. You could even post up the webplayer for download so that everyone can see and try out what you're working on. Thanks for sharing and I'll be really keen to study your code once I've finished producing series 1.

    On that note, I'm currently working away on Video 9 and in that video we'll implement the PlayerScore script so that the player can score when they destroy an enemy. We'll also write the ScoreTable script so that the player can see the scoreboard when they press Tab, and we'll get to experience a small sample of the power of lists in C# when we sort the players by their score. I'm currently aiming to get video 9 finished by Thursday the 22nd of March.
     
  12. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    I've just released Video 9 Our Scoring System!
     
  13. modulo

    modulo

    Joined:
    Sep 10, 2011
    Posts:
    31
    Thank you again for this tutorial
    I'm a beginner but I will try to integrate PHP and SQL to connect and register my player, position, etc.
     
  14. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    I’m working away on video 10 and it looks like it will be less than 2 hours which is good news! In video 10 we’ll allow teams to achieve a winning score and then have the game reload across the network. Videos 2 to 10 are the essential videos and from video 11 onwards we’ll be implementing the fun stuff. I'm aiming to publish video 10 by Wednesday the 28th of March.

    Btw, if you find these videos beneficial then please subscribe and thumbs up the videos on YouTube as doing so will really help me understand which videos are helping you out, plus it motivates me.
     
  15. gormee

    gormee

    Joined:
    Mar 20, 2012
    Posts:
    14
    Hi GTGD,

    Thanks for the informative tutorials, they're really excellent! Very much appreciated! I do however have a problem with the SpawinScript in video 5, I've sent your a message on YouTube as I didn't realize that you were on the forums here too. Anyway I'm going to post my problem here as well in the hope that anyone could help me see what my problem is.

    My problem stems from drawing the GUI window for team selection after the player connects to a server, I have tried to log the activity when the function onOnConnectedToServer() is called and it seems like its not calling the onGUI() function to draw the selection window. I have modified your script a bit to suit my needs as I have 4 classes that I would like to player to choose from, other than that I have followed your instructions step by step. Can anyone please take a look and give me a helping hand? Much appreciated!


    here is my code so far:


    public class SpawnScript : MonoBehaviour {


    //Variables

    //This variable is used to determine if the player needs to spawn into the game
    private bool justConnectedToServer = false;

    //Used to determine what class the player is
    public bool amIOnTheBuilderClass = false;
    public bool amIOnTheViewerClass = false;
    public bool amIOnTheJumperClass = false;
    public bool amIOnTheMoverClass = false;

    //Used to define the JoinTeamWindow
    private Rect joinClassRect;
    private string joinClassWindowTitle = "Choose your Player Class";
    private int joinClassWindowWidth = 660;
    private int joinClassWindowHeight = 200;
    private int joinClassLeftIndent;
    private int joinClassTopIndent;
    private int buttonHeight = 40;



    // Use this for initialization
    void Start ()
    {

    }

    // Update is called once per frame
    void Update ()
    {

    }


    void OnConnectedToServer ()
    {
    Debug.Log("Connected");
    justConnectedToServer = true;
    }

    void JoinClassWindow(int windowID)
    {

    //If the player clicks on the Builder Class then assign them as a builder
    //and spawn them into the game

    if(GUILayout.Button("Join Builder Class", GUILayout.Height(buttonHeight)))
    {
    amIOnTheBuilderClass = true;

    justConnectedToServer = false;
    }


    //If the player clicks on the Mover Class then assign them as a builder
    //and spawn them into the game

    if(GUILayout.Button("Join Mover Class", GUILayout.Height(buttonHeight)))
    {
    amIOnTheMoverClass = true;

    justConnectedToServer = false;
    }


    //If the player clicks on the Jumper Class then assign them as a builder
    //and spawn them into the game

    if(GUILayout.Button("Join Jumper Class", GUILayout.Height(buttonHeight)))
    {
    amIOnTheJumperClass = true;

    justConnectedToServer = false;
    }


    //If the player clicks on the Viewer Class then assign them as a builder
    //and spawn them into the game

    if(GUILayout.Button("Join Viewer Class", GUILayout.Height(buttonHeight)))
    {
    amIOnTheViewerClass = true;

    justConnectedToServer = false;
    }

    }



    void onGUI()
    {
    Debug.Log ("LoadGUI");
    //If the player has just connected to the server then draw the join class window

    if(justConnectedToServer == true)
    {
    Debug.Log ("Show Player Select");
    joinClassLeftIndent = Screen.width / 2 - joinClassWindowWidth / 2;

    joinClassTopIndent = Screen.height / 2 - joinClassWindowHeight / 2;

    joinClassRect = new Rect (joinClassLeftIndent, joinClassTopIndent,
    joinClassWindowWidth, joinClassWindowHeight);

    joinClassRect = GUILayout.Window(0, joinClassRect, JoinClassWindow, joinClassWindowTitle);
    }
    }

    }
     
    Last edited: Mar 26, 2012
  16. zOrigin

    zOrigin

    Joined:
    Jul 31, 2010
    Posts:
    21
    Change
    Code (csharp):
    1. void onGUI()
    to
    Code (csharp):
    1. void OnGUI()
     
    Last edited: Mar 26, 2012
  17. gormee

    gormee

    Joined:
    Mar 20, 2012
    Posts:
    14
    Thanks for the help!

    However despite changing the syntax the OnGUI() function only works if I play it in the Unity Editor. Should I build and run it, it doesn't work.:confused:


    UPDATE:
    I managed to get my builds working too. I used this helpful forum thread in case anyone has problems with their scripts working in the editor but not in their builds. My fix was the first listed one

    http://forum.unity3d.com/threads/40806-Script-not-working-in-build-ok-in-editor
     
    Last edited: Mar 26, 2012
  18. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    Thanks a heap zOrigin for helping gormee out and I'm glad that gormee solved the latter part of his problem!
     
  19. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    Uhhh by the way I've just checked my YouTube channel and I suddenly have at least 50 new subscribers in a single day. I've had a look at some of the new subscribers and they seem to be liking a video every few minutes???! Any ideas on what's going on? It feels so wrong that I've gone and changed my password out of paranoia.

    Edit:
    I've checked up and it looks like someone is subscribing to my channel with fake or hacked accounts. If anyone knows how to delete and block subscribers in the new YouTube layout it would be much appreciated.
     
    Last edited: Mar 26, 2012
  20. gormee

    gormee

    Joined:
    Mar 20, 2012
    Posts:
    14
    Okay I've got another problem with the multiplayer script.. It seems as though the function OnPlayerDisconnected() is not working for me. I've checked this time to see if its a capitalization problem but my code checks out. I added a debug log and it seems when I disconnect the function doesn't execute and this leaves my previously instantiated player objects in my level.

    Anyone got any suggestions? Here is my code and muchos gracias in advance!:
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. /// <summary>
    5. /// This script is attached to the MultiplayerManager
    6. /// it is the foundation for the Multiplayer system
    7. /// </summary>
    8.  
    9. public class MultiplayerScript : MonoBehaviour {
    10.    
    11.     //Variables
    12.     private string titleMessage = "Collaboration Game Prototype";
    13.     private string connectToIP = "127.0.0.1";
    14.     private int connectionPort = 26500;
    15.     private bool useNAT = false;
    16.     private string ipAddress;
    17.     private string port;
    18.     private int numberOfPlayers = 4;
    19.     public string playerName;
    20.     public string serverName;
    21.     public string serverNameForClient;
    22.     private bool iWantToSetupAServer = false;
    23.     private bool iWantToConnectToAServer = false;
    24.    
    25.    
    26.     //These variables are used to define the main window
    27.     private Rect connectionWindowRect;
    28.     private int connectionWindowWidth = 400;
    29.     private int connectionWindowHeight = 280;
    30.     private int buttonHeight = 60;
    31.     private int leftIndent;
    32.     private int topIndent;
    33.    
    34.    
    35.     //These variables are used to define the server shutdown window
    36.     private Rect serverDisWindowRect;
    37.     private int serverDisWindowWidth = 300;
    38.     private int serverDisWindowHeight = 150;
    39.     private int serverDisWindowLeftIndent = 10;
    40.     private int serverDisWindowTopIndent = 10;
    41.    
    42.    
    43.     //These variables are used to define the client disconnect window
    44.     private Rect clientDisWindowRect;
    45.     private int clientDisWindowWidth = 300;
    46.     private int clientDisWindowHeight = 170;
    47.     private bool showDisconnectWindow = false;
    48.    
    49.        
    50.        
    51.        
    52.     // Use this for initialization
    53.     void Start ()
    54.     {
    55.         //Load the last used server name from registry
    56.         //If the server name doesn't exist then use 'server'
    57.         serverName = PlayerPrefs.GetString("serverName");
    58.        
    59.         if(serverName == "")
    60.         {
    61.             serverName = "Server"; 
    62.         }
    63.        
    64.        
    65.         //Load last used player name from registry
    66.         //If the player name is blank then default is 'player'
    67.        
    68.         playerName = PlayerPrefs.GetString("playerName");
    69.        
    70.         if(playerName == "")
    71.         {
    72.             playerName = "Player";
    73.         }
    74.     }
    75.    
    76.     // Update is called once per frame
    77.     void Update ()
    78.     {
    79.         if(Input.GetKeyDown(KeyCode.Escape))
    80.         {
    81.             showDisconnectWindow = !showDisconnectWindow;  
    82.         }
    83.     }
    84.    
    85.    
    86.     void ConnectWindow(int windowID)
    87.     {
    88.         // Leave a gap from the header
    89.         GUILayout.Space(15);
    90.        
    91.         //When the player launches the game they have the option to create a server
    92.         //or join a server. The variables iWantToSetupAServer and iWantToConnectAServer
    93.         //start as false so the player is presented with the necessary choices
    94.        
    95.         if(iWantToSetupAServer == false  iWantToConnectToAServer == false)
    96.         {
    97.             if(GUILayout.Button("Setup a server", GUILayout.Height(buttonHeight)))
    98.             {
    99.                 iWantToSetupAServer = true;
    100.             }  
    101.            
    102.             GUILayout.Space(10);
    103.                
    104.             if(GUILayout.Button("Connect to a server", GUILayout.Height(buttonHeight)))
    105.             {
    106.                 iWantToConnectToAServer = true;
    107.             }
    108.            
    109.             GUILayout.Space(10);
    110.            
    111.             if(Application.isWebPlayer == false  Application.isEditor == false)
    112.             {
    113.                 if(GUILayout.Button("Exit Prototype", GUILayout.Height(buttonHeight)))
    114.                 {
    115.                     Application.Quit();
    116.                 }                      
    117.             }
    118.            
    119.         }
    120.        
    121.        
    122.         if(iWantToSetupAServer == true)
    123.         {
    124.            
    125.             //The user can type a name for their server in the text field
    126.            
    127.             GUILayout.Label("Enter a name for your server");
    128.            
    129.             serverName = GUILayout.TextField(serverName);
    130.            
    131.             GUILayout.Space (5);
    132.            
    133.             //The user can type in the port number for their server in the text field
    134.             //Default value is 26500 as defined in the variables
    135.            
    136.             GUILayout.Label("Server Port");
    137.            
    138.             connectionPort = int.Parse(GUILayout.TextField(connectionPort.ToString()));
    139.            
    140.             GUILayout.Space(10);
    141.            
    142.             if(GUILayout.Button("Start my own server", GUILayout.Height(30)))
    143.             {
    144.                
    145.                 //Create the server
    146.                
    147.                 Network.InitializeServer(numberOfPlayers, connectionPort, useNAT);
    148.                
    149.                 //Save the server name using PlayerPrefs
    150.                
    151.                 PlayerPrefs.SetString("serverName", serverName);
    152.                
    153.                 iWantToSetupAServer = false;
    154.             }
    155.            
    156.             if(GUILayout.Button("Go Back", GUILayout.Height(30)))
    157.             {
    158.                 iWantToSetupAServer = false;   
    159.             }
    160.         }
    161.        
    162.        
    163.         if(iWantToConnectToAServer == true)
    164.         {
    165.             //The user can type a name for their player in the text field
    166.            
    167.             GUILayout.Label("Enter your player name");
    168.            
    169.             playerName = GUILayout.TextField(playerName);
    170.            
    171.             GUILayout.Space(5);
    172.            
    173.            
    174.             //The user can type in their IP address for the server they wish to connect to
    175.            
    176.             GUILayout.Label("Type in Server IP Address");
    177.            
    178.             connectToIP = GUILayout.TextField(connectToIP);
    179.            
    180.             GUILayout.Space(5);
    181.            
    182.            
    183.             //The user can type a port number for the server they want to connect to
    184.            
    185.             GUILayout.Label ("Type in the server port");
    186.            
    187.             connectionPort = int.Parse(GUILayout.TextField(connectionPort.ToString()));
    188.            
    189.             GUILayout.Space(5);
    190.            
    191.            
    192.             //Player clicks on this button to establish a connection
    193.            
    194.             if(GUILayout.Button("Connect", GUILayout.Height(25)))
    195.             {
    196.                 //Ensures that the player has entered a name for themselves
    197.                
    198.                 if(playerName == "")
    199.                 {
    200.                     playerName = "Player"; 
    201.                 }
    202.                
    203.                 //If the player has entered a name then attempt to join the server
    204.                
    205.                 if(playerName != "")
    206.                 {
    207.                     //Connect to a server with the IP Address  port number previously entered  
    208.                    
    209.                     Network.Connect(connectToIP, connectionPort);
    210.                    
    211.                     PlayerPrefs.SetString("playerName", playerName);
    212.                 }
    213.             }
    214.            
    215.            
    216.             GUILayout.Space(5);
    217.            
    218.            
    219.             if(GUILayout.Button("Go Back", GUILayout.Height(25)))
    220.             {
    221.                 iWantToConnectToAServer = false;   
    222.             }
    223.         }
    224.        
    225.     }
    226.    
    227.    
    228.    
    229.     void ServerDisconnectWindow(int windowID)
    230.     {
    231.         GUILayout.Label("Server name: " + serverName);
    232.        
    233.         //Show the number of players connected
    234.        
    235.         GUILayout.Label("Number of Players connected: " + Network.connections.Length);
    236.        
    237.        
    238.         //Show the avg ping time for the network connections
    239.        
    240.         if(Network.connections.Length >=1)
    241.         {
    242.             GUILayout.Label("Ping: " + Network.GetAveragePing(Network.connections[0]));
    243.         }
    244.        
    245.        
    246.         //Shutdown the server if the user chooses to
    247.        
    248.         if(GUILayout.Button("Shutdown Server"))
    249.         {
    250.             Network.Disconnect();  
    251.         }
    252.     }
    253.    
    254.    
    255.    
    256.     void ClientDisconnectWindow (int windowID)
    257.     {
    258.        
    259.         //Show the player the server they're connected to and their avg ping
    260.        
    261.         GUILayout.Label("Connected to server: " + serverName);
    262.        
    263.         GUILayout.Label("Ping: " + Network.GetAveragePing(Network.connections[0]));
    264.        
    265.         GUILayout.Space(7);
    266.        
    267.        
    268.         //The player disconnects from the server when they press this button
    269.        
    270.         if(GUILayout.Button("Disconnect", GUILayout.Height(25)))
    271.         {
    272.            
    273.             Network.Disconnect();
    274.            
    275.         }
    276.        
    277.        
    278.         GUILayout.Space(5);
    279.        
    280.        
    281.         //This button allows the player to return to the game in webplayer fullscreen mode
    282.        
    283.         if(GUILayout.Button("Return To Game", GUILayout.Height(25)))
    284.         {
    285.             showDisconnectWindow = false;  
    286.         }
    287.        
    288.     }
    289.    
    290.    
    291.     void onDisconnectedFromServer()
    292.     {
    293.        
    294.         //If a player disconnects/loses network then level is restarted
    295.        
    296.         Application.LoadLevel(Application.loadedLevel);
    297.     }
    298.    
    299.    
    300.    
    301.     void OnPlayerDisconnected(NetworkPlayer networkPlayer)
    302.     {
    303.         //When the player leaves the server delete them across the network
    304.         //Along with their RPCs so no one else sees them
    305.        
    306.         Debug.Log("Clean up " + networkPlayer);
    307.        
    308.         Network.RemoveRPCs(networkPlayer);
    309.        
    310.         Network.DestroyPlayerObjects(networkPlayer);
    311.     }
    312.    
    313.    
    314.    
    315.     void OnPlayerConnected(NetworkPlayer networkPlayer)
    316.     {
    317.         networkView.RPC("TellPlayerServerName", networkPlayer, serverName);
    318.     }
    319.    
    320.    
    321.     void OnGUI()
    322.     {
    323.        
    324.         //If the player is disconnected then run the ConnectWindow function
    325.         if(Network.peerType == NetworkPeerType.Disconnected)
    326.         {
    327.            
    328.             //Determine the position of the window based on the width and
    329.             //height of the screen. The window will be placed in the middle of the screen
    330.             leftIndent = Screen.width / 2 - connectionWindowWidth / 2;
    331.            
    332.             topIndent = Screen.height / 2 - connectionWindowHeight / 2;
    333.            
    334.             connectionWindowRect = new Rect (leftIndent, topIndent, connectionWindowWidth, connectionWindowHeight);
    335.            
    336.             connectionWindowRect = GUILayout.Window(0, connectionWindowRect, ConnectWindow, titleMessage);
    337.                                                    
    338.         }
    339.        
    340.        
    341.         //If the game is running as a server then run the ServerDisconnectWindow function
    342.        
    343.         if(Network.peerType == NetworkPeerType.Server)
    344.         {
    345.             //Defining the Rect for the server disconnect window
    346.            
    347.             serverDisWindowRect = new Rect(serverDisWindowLeftIndent, serverDisWindowTopIndent,
    348.                                            serverDisWindowWidth, serverDisWindowHeight);
    349.            
    350.             serverDisWindowRect = GUILayout.Window(1, serverDisWindowRect, ServerDisconnectWindow,"");
    351.            
    352.            
    353.         }
    354.        
    355.        
    356.         //If the connection type is a client then show them a 'disconnect from server' window
    357.        
    358.         if(Network.peerType == NetworkPeerType.Client  showDisconnectWindow == true)
    359.         {
    360.             clientDisWindowRect = new Rect(Screen.width / 2 - clientDisWindowWidth / 2,
    361.                                            Screen.height / 2 - clientDisWindowHeight / 2,
    362.                                            clientDisWindowWidth, clientDisWindowHeight);
    363.            
    364.             clientDisWindowRect = GUILayout.Window(1, clientDisWindowRect, ClientDisconnectWindow, "");
    365.         }
    366.     }
    367.    
    368.    
    369.     //RPC used to tell connected clients the server name they are connected to
    370.    
    371.     [RPC]
    372.     void TellPlayerServerName(string servername)
    373.     {
    374.         serverName = servername;   
    375.     }
    376.    
    377.    
    378.    
    379. }
    380.  
     
  21. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    Hello gormee. I see onDisconnectedFromServer in your code. Try OnDisconnectedFromServer and let me know how that goes. Btw, the scripts are available for download from my website so you can check against that line by line if you haven't made too many modifications.

    OnPlayerDisconnected runs on the server and OnDisconnectedFromServer runs on the client. These are inbuilt Unity functions and I'd recommend having a look at the script reference to expand your understanding of them.
     
    Last edited: Mar 27, 2012
  22. gormee

    gormee

    Joined:
    Mar 20, 2012
    Posts:
    14
    Goodness me.. *face palm* it worked for me now.. I'm such a noob thanks again GTGD!!
     
  23. pspdude

    pspdude

    Joined:
    Dec 17, 2011
    Posts:
    43
    Loving these tutorials so far! Btw can I request somthing for the series? Like, when your done all the main videos?
     
  24. Kaida Games

    Kaida Games

    Joined:
    Feb 28, 2012
    Posts:
    6
    Somehow I don't think you could have picked a better name for this video series. Happy to be on board and great full for the time you have put into this.
     
  25. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    I've published video 10! In this video we’ll implement the ability for our teams to reach a winning score and then win the game. The server will then reload the level across the network.

    The most important videos (2 to 10) are now complete and with their scripts you have the foundation for a decent multiplayer system that you can build upon and improve for your own multiplayer projects. Videos 11 onwards will be the fun stuff and are not essential to the multiplayer system but they will expose you to different systems and pieces of code.

    In the coming days you might also see some changes to my website as I'm intending to have all the videos available for viewing from my website.
     
  26. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    Sure pspdude let me know what you're thinking. I don't guarantee that I can accomplish it though :).

    Welcome on board!

     
  27. pspdude

    pspdude

    Joined:
    Dec 17, 2011
    Posts:
    43
    Think you can do some basic AI? Or is that out of the question? :p
     
  28. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    I'm intending to work on basic AI but that won't be till Series 2 which by the looks of it may be a year away from now sorry!

    It might actually take me that long because I need to finish Series 1, learn and try out a whole heap of new code while developing the concept for Series 2 (I have a fair idea of what I want to do for Series 2 but I'll talk about that in some months from now) and then build the Series 2 prototype game before I can plan and produce the videos. It's a very involved process and I'm intending to make a video once I've completed Series 1 explaining how to develop a concept and then the systems that will take that concept closer to reality. It has a fair bit to do with Project Management.
     
  29. pspdude

    pspdude

    Joined:
    Dec 17, 2011
    Posts:
    43
    Ahh okay, thanks. Btw I've learned quite a lot from your videos :p
     
  30. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    Video 11 Fake Crouching is now out! In this video we'll implement crouching for our player and we'll get some exposure to scaling.

    Also this video is a lot shorter than most of the other videos which is a good thing!
     
  31. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    Just a short question:
    You don't use the built in way of syncing the player movement, instead you are using RPCs, what is the pro of doing your way vs the built in way of syncing?
     
  32. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    I'm not sure which is the pro way but I find using RPCs to be easier on my brain. State synchronization relies on data being constantly sent and your network views will have to be observing something I'm pretty sure. You might also have to make use of OnSerializeNetworkView which I've never bothered to do because it just seems like too much code.

    I also find that using RPCs gives me much cleaner movement. If you left the send rate at 15 then the motion of your players is very jerky across the network. With RPCs it is way smoother and the RPCs are only sent when a player is moving. If you increased the send rate then I believe you'll have a whole lot more data being sent needlessly, well that's my current understanding.

    Here are two links from Unity that I found quite important and you might have already seen them.

    http://unity3d.com/support/documentation/Components/net-UnityNetworkElements.html

    http://unity3d.com/support/documentation/ScriptReference/Network.OnSerializeNetworkView.html

    If you learn something different please do come back and tell me about it and by the way your planned project looks pretty interesting, and I think you're onto something exciting, so don't let it fizzle out!
     
  33. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    A YouTube viewer OneManArmy3D posted up that he was having trouble with video 9 because he's programming in JavaScript which does not support delegates.

    I've pasted here some logic that I've developed for sorting a list of numbers without using delegate, and it's in C#, but you should be able to replicate this in JavaScript.

    Just create a new C# script, name it CompareAndSortNumbers, paste in this code and then attach the script to an empty GameObject or Camera. When you run the game the log will show that the list has been sorted.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. /// <summary>
    7. /// This script can be attached to the main camera or any
    8. /// empty gameobject. When the code runs some predefined
    9. /// numbers are added to List1 and these are then compared
    10. /// and added in descending order into List2.
    11. /// </summary>
    12.  
    13. public class CompareAndSortNumbers : MonoBehaviour {
    14.    
    15.     //Variables Start___________________________________________
    16.    
    17.     private List<int> List1 = new List<int>();
    18.    
    19.     private List<int> List2 = new List<int>();
    20.    
    21.     private int counter;
    22.    
    23.     //Variables End_____________________________________________
    24.  
    25.     // Use this for initialization
    26.     void Start ()
    27.     {  
    28.         //I'll add some numbers to our List1.
    29.        
    30.         List1.Add(12);
    31.        
    32.         List1.Add(1);
    33.        
    34.         List1.Add(4);
    35.        
    36.         List1.Add(8);
    37.        
    38.         List1.Add(7);
    39.        
    40.        
    41.         //I want List2 to be the same size as List1 so I'll add
    42.         //entries into List2 until it is the same size.
    43.        
    44.         for(int i = 0; i < List1.Count; i++)
    45.         {
    46.             List2.Add(0);  
    47.         }
    48.        
    49.        
    50.         //Compare the elements within List 1 and copy them
    51.         //into List2 in descending order.
    52.        
    53.         for(int i = 0; i < List1.Count; i++)
    54.         {
    55.             for(int j = 0; j < List1.Count; j++)
    56.             {
    57.                 if(List1[i] < List1[j])
    58.                 {
    59.                     counter++; 
    60.                 }
    61.             }
    62.            
    63.             List2[counter] = List1[i];
    64.            
    65.             counter = 0;
    66.         }
    67.        
    68.        
    69.         //Now display each element in List2 and you'll see that they are
    70.         //in descending order.
    71.        
    72.         for(int i = 0; i < List2.Count; i++)
    73.         {
    74.             Debug.Log("List2 " + "Index " + i.ToString() + " = " + List2[i].ToString());   
    75.         }
    76.     }
    77. }
    78.  
    79.  
     
    Last edited: Apr 2, 2012
  34. OneManArmy3D

    OneManArmy3D

    Joined:
    Jun 2, 2011
    Posts:
    191
    Thanks again. Here will be in JavaScript:
    Code (csharp):
    1. class CompareAndSortNumbers extends MonoBehaviour {
    2.  
    3.     var List1 = new Array();
    4.     var List2 = new Array();
    5.     var counter : int;
    6.  
    7.     function Start () {  
    8.  
    9.         //I'll add some numbers to our List1.
    10.         List1.Add(12);
    11.         List1.Add(1);
    12.         List1.Add(4);
    13.         List1.Add(8);
    14.         List1.Add(7);
    15.  
    16.         //I want List2 to be the same size as List1 so I'll add
    17.         //entries into List2 until it is the same size.
    18.         for( var k : int= 0; k < List1.Count; k++){
    19.             List2.Add(0);  
    20.         }
    21.  
    22.         //Compare the elements within List 1 and copy them
    23.         //into List2 in descending order.
    24.         for( var i : int = 0; i < List1.Count; i++){
    25.             for( var j : int= 0; j < List1.Count; j++){
    26.                 if(List1[i] < List1[j]){
    27.                     counter++;  
    28.                 }
    29.             }
    30.            
    31.             List2[counter] = List1[i];
    32.             counter = 0;
    33.         }
    34.  
    35.         //Now display each element in List2 and you'll see that they are in descending order.
    36.         for( var u : int = 0; u < List2.Count; u++){
    37.             Debug.Log("List2 " + "Index " + u.ToString() + " = " + List2[u].ToString());    
    38.         }
    39.     }
    40. }
     
  35. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    One thing i thought about regarding updating the player position.
    If you move and rotate you will send both rotation and position twice every frame.
    If you instead checked if playerMoved or playerRotated you will only need to send one RPC and will save a lot of bandwidth.
     
  36. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    That's totally true and I do point that out in the upcoming video 12 as we'll be adding a little bit more code to the MovementUpdate script in that video, but at the end of the day I haven't made the script more efficient. Maybe some day I'll change it but for now I leave improving the code from this series to the learner and a lot depends on how they intend to use the code.

    Btw, I'm aiming to get Video 12 Blinking (teleportation) published by this Thursday and it is going to be a totally awesome video and the code is even more awesome!!!
     
  37. virror

    virror

    Joined:
    Feb 3, 2012
    Posts:
    2,963
    BTW, i love your tutorials, very helpful! : D
     
  38. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    Video 12 Blinking is now out!!!
     
  39. bajeo

    bajeo

    Joined:
    Dec 5, 2011
    Posts:
    75
    Just wanted to drop in an let you know how i was getting along with making the game run using the Unity Master Server.

    I got all of the gameplay working correctly then you released the 'restart match' video and it all got messed up again haha :D. Have fixed some of the issues that happened but am stuck with 1 final issue.
    Upon restarting the match all players can see and shoot each other (yay!) but only red players take damage. Ive re-watched your video several times and cant quite work out whats going wrong. I remember you mentioning at one point you added code to stop behaviour similar to this but cant find this bit of the video?

    Any ideas where the problem might be? If players disconnect and reconnect then the game runs correctly.
     
  40. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    It almost sounds like the RPCs for Red players are not being sent across the network because blue players can't take damage, since damage application happens on the attackers computer and that would have to be a red player in order for a blue player to get hurt. This hypothesis isn't true though if you can see that the red players position changes as you move them, as their movement is getting sent by RPCs across the network.

    Maybe the red players are not getting added back to the PlayerList in the PlayerDatabase script?
     
  41. bajeo

    bajeo

    Joined:
    Dec 5, 2011
    Posts:
    75
    All the players can see each other moving and when shooting you can see the projectiles being created, its just the damage.

    Thanks for the pointer ill checkout the PlayerDatabase script and see if anything is missing there and let you know.
     
  42. bajeo

    bajeo

    Joined:
    Dec 5, 2011
    Posts:
    75
    Hey think i worked it out. There is nothing wrong with the code i think i was spawning players too quickly because for the moment if once the game has restarted i wait about 5 - 10 seconds before selecting a team then the game plays as normal and all communications are sent correctly. I think its because i set the AssignHealth co-routine to a longer wait duration to allow the health buffering to catch up over the internet since its not LAN based. So i just need to not show the team selection menu until after that duration.

    If this turns out to be the only problem then i will organise the code and post it here, its really only affects a few files. The MultiplayerScript, ReloadLevelScript and a new one i had to make which handles the level loading and for some reason it would only work correctly in javascript
     
  43. richardh

    richardh

    Joined:
    Mar 7, 2012
    Posts:
    226
    Just started to follow your tutorials. I'm on number 3 now. VERY good. Informative, clear and unrushed. Great narrative and I'm learning a lot. Thank You.

    Will there be a series 2 by any chance?

    thanks again.
     
  44. ConnorLuke

    ConnorLuke

    Joined:
    Apr 7, 2012
    Posts:
    7
    Hey Guys Im on Video 10 Currently... But ive managed to come across a few things i may have missed out... if you have skype please post it on here so we may be in contact and you can help me out and maybe remote help me with some coding.

    Bugs/Missed Out:
    When Shooting My Player Gets Moved By The Bullets.
    Player Name Doesnt show above Players.

    Things Needed:
    Master Server
    Weapons

    Hope You can help me guys!

    -Connor
     
  45. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    I've just completed Video 13 where we’ll implement energy so that the player’s energy weapons and behavior are regulated by how much energy they have!
     
  46. technotdc

    technotdc

    Joined:
    Oct 21, 2011
    Posts:
    60
    Hi.........
    First, thanks a lot.... for this tutorials ..... One of the best I've ever seen .........
    Well ..... Now the problem I have .........
    I have completed the level change video,but not work well (as you see in the video), when a team has won, does not re-start the level correctly........



    Where do I can have my error???


    PD- 1 ----- I have unity 3.5
    PD- 2 ------ sorry my bad english


    Thanks
     
  47. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    Hello technotdc,

    Thanks for posting the video to describe the problem you're facing. Actually it looks like you're having multiple problems.

    First your level is not reloading and I suspect this is because the name of your scene is different from what I named the scene. In your ReloadLevelScript look for this line and supply it with the name of your scene rather than what I named my scene.

    Code (csharp):
    1. Application.LoadLevel("Series 1 Prototype");
    Second I notice that when you click a button to choose a team the options are not going away. I think this might be because in the SpawnScript you have not set matchRestart to false after making use of it. This is my code from the JoinTeamWindow function in the SpawnScript.

    Code (csharp):
    1. if(justConnectedToServer == true || matchRestart == true)
    2.         {
    3.             //If the player clicks on the Join Red Team button then
    4.             //assign them to the red team and spawn them into the game.
    5.            
    6.             if(GUILayout.Button("Join Red Team", GUILayout.Height(buttonHeight)))
    7.             {
    8.                 amIOnTheRedTeam = true;
    9.                
    10.                 justConnectedToServer = false;
    11.                
    12.                 matchRestart = false;
    13.                
    14.                 SpawnRedTeamPlayer();
    15.                
    16.                 firstSpawn = true;
    17.             }
    18.            
    19.            
    20.             //If the player clicks on the Join Blue Team button then
    21.             //assign them to the blue team and spawn them into the game.
    22.            
    23.             if(GUILayout.Button("Join Blue Team", GUILayout.Height(buttonHeight)))
    24.             {
    25.                 amIOnTheBlueTeam = true;
    26.                
    27.                 justConnectedToServer = false;
    28.                
    29.                 matchRestart = false;
    30.                
    31.                 SpawnBlueTeamPlayer();
    32.                
    33.                 firstSpawn = true;
    34.             }
    35.         }
    The third thing I've noticed is that when your cursor unlocks after you won the match you were still able to move around and I believe this is because you've forgotten to include the if(Screen.lockCursor == true) and if(Screen.lockCursor == false) checks in the Update function of Unity's FPSInputController script

    Code (csharp):
    1. private var motor : CharacterMotor;
    2.  
    3. // Use this for initialization
    4. function Awake () {
    5.  
    6.     if(networkView.isMine == true)
    7.     {
    8.         motor = GetComponent(CharacterMotor);
    9.     }
    10.    
    11.     else
    12.     {
    13.         enabled = false;
    14.     }
    15. }
    16.  
    17. // Update is called once per frame
    18. function Update () {
    19.  
    20.     if(Screen.lockCursor == true)
    21.     {
    22.         // Get the input vector from kayboard or analog stick
    23.         var directionVector = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
    24.        
    25.         if (directionVector != Vector3.zero) {
    26.             // Get the length of the directon vector and then normalize it
    27.             // Dividing by the length is cheaper than normalizing when we already have the length anyway
    28.             var directionLength = directionVector.magnitude;
    29.             directionVector = directionVector / directionLength;
    30.            
    31.             // Make sure the length is no bigger than 1
    32.             directionLength = Mathf.Min(1, directionLength);
    33.            
    34.             // Make the input vector more sensitive towards the extremes and less sensitive in the middle
    35.             // This makes it easier to control slow speeds when using analog sticks
    36.             directionLength = directionLength * directionLength;
    37.            
    38.             // Multiply the normalized direction vector by the modified length
    39.             directionVector = directionVector * directionLength;
    40.         }
    41.        
    42.         // Apply the direction to the CharacterMotor
    43.         motor.inputMoveDirection = transform.rotation * directionVector;
    44.         motor.inputJump = Input.GetButton("Jump");
    45.     }
    46.    
    47.    
    48.     if(Screen.lockCursor == false)
    49.     {
    50.         directionVector = new Vector3(0,0,0);
    51.        
    52.         motor.inputMoveDirection = transform.rotation * directionVector;
    53.     }
    54.    
    55. }
    56.  
    57. // Require a character controller to be attached to the same game object
    58. @script RequireComponent (CharacterMotor)
    59. @script AddComponentMenu ("Character/FPS Input Controller")
    Hope that helps.
     
  48. gormee

    gormee

    Joined:
    Mar 20, 2012
    Posts:
    14
    Hey GTGD,

    Very grateful for your helpful tutes, however I have a bit of a problem that I hope you would help me out with. I have taken some of your code and placed it in my game and I'm having problems with the RPC calls over a network. Basically I have a gravity gun that will help my player to pick up rigidbody objects, however the object movement does not translate over the network so other players can't see me moving the object.

    The gravity gun (mover class) will move 'projectiles' made by the builder class type of player. I have tried to adapt your code to suit my needs and this is what I have so far:

    The projectiles already have the Network View attached to them.

    My gravity gun code is in JS and I added an RPC function (at the bottom) that is modelled after what you wrote for your examples
    Code (csharp):
    1.  
    2. var catchRange = 30.0;
    3.     var holdDistance = 4.0;
    4.     var minForce = 10;
    5.     var maxForce = 10;
    6.     var forceChargePerSec = 30;
    7.     var layerMask : LayerMask = -1;
    8.      
    9.     enum GravityGunState { Free, Catch, Occupied, Charge, Release};
    10.     private var gravityGunState : GravityGunState = 0;
    11.     private var rigid : Rigidbody = null;
    12.     private var currentForce = minForce;
    13.  
    14.     function FixedUpdate () {
    15.         if(gravityGunState == GravityGunState.Free) {
    16.             if(Input.GetButton("Fire1")) {
    17.                 var hit : RaycastHit;
    18.                 if(Physics.Raycast(transform.position, transform.forward, hit, catchRange, layerMask)) {
    19.                     if(hit.rigidbody) {
    20.                         rigid = hit.rigidbody;
    21.                         //print("rigidPos: " + rigid.transform.position);
    22.  
    23.                         gravityGunState = GravityGunState.Catch;
    24.                        
    25.                         // for debuging, remove it
    26.                         //print("force: " + currentForce);
    27.                     }
    28.                 }
    29.             }
    30.         }
    31.         else if(gravityGunState == GravityGunState.Catch) {
    32.             rigid.MovePosition(transform.position + transform.forward * holdDistance);
    33.             //networkView.RPC("updatePos", RPCMode.All, rigid.transform.position, rigid.transform.rotation);
    34.             if(!Input.GetButton("Fire1"))
    35.                 gravityGunState = GravityGunState.Occupied;
    36.         }
    37.         else if(gravityGunState == GravityGunState.Occupied) {
    38.             rigid.MovePosition(transform.position + transform.forward * holdDistance);
    39.             //networkView.RPC("updatePos", RPCMode.All, rigid.transform.position, rigid.transform.rotation);
    40.             if(Input.GetButton("Fire1"))
    41.                 gravityGunState = GravityGunState.Charge;
    42.         }
    43.         else if(gravityGunState == GravityGunState.Charge) {
    44.             rigid.MovePosition(transform.position + transform.forward * holdDistance);
    45.             if(currentForce < maxForce) {
    46.                 currentForce += forceChargePerSec * Time.deltaTime;
    47.             }
    48.             else {
    49.                 currentForce = maxForce;
    50.             }
    51.             if(!Input.GetButton("Fire1"))
    52.                 gravityGunState = GravityGunState.Release;
    53.                
    54.             // for debuging, remove it
    55.             //print("force: " + currentForce);
    56.         }
    57.         else if(gravityGunState == GravityGunState.Release) {
    58.             rigid.AddForce(transform.forward * currentForce);
    59.             currentForce = minForce;
    60.             gravityGunState = GravityGunState.Free;
    61.             // for debuging, remove it
    62.             //print("");
    63.         }
    64.     }
    65.    
    66.     @RPC
    67.     function updatePos(pos:Vector3, rot:Quaternion){
    68.         if(rigid != null){
    69.             rigid.transform.position = pos;
    70.             rigid.transform.rotation = rot;
    71.         }
    72.     }
    73.  

    This is the code for the 'projectiles' that the gravity gun will have to move. I copied and pasted your movementupdate script to use on the projectiles so you can ignore the comments
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class ProjectileUpdate : MonoBehaviour
    5. {
    6.    
    7.     //Variables
    8.     private Vector3 lastPosition;
    9.     private Quaternion lastRotation;
    10.     private Transform myTransform;
    11.    
    12.    
    13.    
    14.  
    15.     // Use this for initialization
    16.     void Awake ()
    17.     {
    18.         if(networkView.isMine == true)
    19.         {
    20.             myTransform = transform;
    21.             Debug.Log("myPos: " + myTransform.position);
    22.             //Ensure that everyone sees the player at the correct location
    23.             //the moment they spawn
    24.            
    25.             networkView.RPC("updateMovement", RPCMode.OthersBuffered, myTransform.position, myTransform.rotation);
    26.            
    27.         }
    28.        
    29.         else
    30.         {
    31.             enabled = false;   
    32.         }
    33.     }
    34.    
    35.     // Update is called once per frame
    36.     void Update ()
    37.     {
    38.         //If the player has moved at all then fire an RPC to update across the network
    39.        
    40.         if(Vector3.Distance(myTransform.position, lastPosition) >=0.1)
    41.         {
    42.             //Capture the player's position before the RPC is fired
    43.             //This determines if the player has moved in the previous if statement
    44.             Debug.Log("updatePosNow");
    45.             lastPosition = myTransform.position;
    46.  
    47.             networkView.RPC("updateMovement", RPCMode.OthersBuffered, myTransform.position, myTransform.rotation);
    48.         }
    49.        
    50.         if(Quaternion.Angle(myTransform.rotation, lastRotation) >=1)
    51.         {  
    52.             //Capture the player's rotation before the RPC is fired
    53.             //This determins if the player has turned in the previous if statement
    54.            
    55.             lastRotation = myTransform.rotation;
    56.            
    57.             networkView.RPC("updateMovement", RPCMode.OthersBuffered, myTransform.position, myTransform.rotation);
    58.         }
    59.     }
    60.    
    61.    
    62.    
    63.    
    64.     [RPC]
    65.     void updateMovement (Vector3 newPosition, Quaternion newRotation)
    66.     {  
    67.         transform.position = newPosition;
    68.        
    69.         transform.rotation = newRotation;
    70.        
    71.         //Debug.Log("updatePos:" + newPosition);
    72.  
    73.     }
    74.    
    75.    
    76.    
    77.    
    78. }
    79.  
    Hope you're in a helpful mood, if nt thanks so much for the vids anyway, they're excellent and keep up the gd work!
     
    Last edited: Apr 10, 2012
  49. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    Hello gormee,

    I've had a brief read and this is what I understand, the projectiles are the objects picked up by the gravity gun, and at the moment you can pick them up in your game, but no one else across the network can see you picking up or moving that projectile. I'm guessing that the Gravity Gun script is attached to the player or a GameObject that is a child to the player.

    I believe that you won't see the update because if you notice in the ProjectileUpdate script it requires if(networkView.isMine == true) and I believe this is only going to be true if the projectile was Network.Instantiated with your player, but then other players will not be able to pick it up.

    I think the RPC in the Gravity Gun script has no effect because the other instances of this Gravity Gun script across the network on your player character across the network don't know what rigid is referring to. Only on your instance of the game does the script know what rigid is. In the RPC you would actually have to find the object and tell it what rigid is.

    Here are two rough solutions that I can think of:

    Possible solution 1
    Supply the RPC in the Gravity Gun script with the name of the projectile it has picked up. Please note that each projectile would need a unique name. In the RPC find this projectile GameObject by it's name and then update it's position and rotation with the pos and rot you supplied to the RPC, across the network. I've read from people more knowledgeable than me that GameObject.Find is apparently quite slow and expensive so it might not be such a good solution if you will be sending out this RPC a lot.

    Possible solution 2 and probably better than solution 1
    Make the Gravity Gun script access the ProjectileUpdate script and supply it with your player name when you pick it up.

    In the ProjectileUpdate script use a check just like in the HealthAndDamage script where only on your instance of the game is the RPC executed, which in this case would be updating the position of the projectile. Have your ProjectileUpdate script inform itself across the network who its current holder is (would be you) so that the movement update doesn't get fired off by other players who had supplied their name to that object in the past. This is just like how the HealthAndDamage script updates myAttacker across the network and it's important because when the player is destroyed only the last attacker gets the score. When you let go of the projectile, access the script again and remove your name so that you are no longer the holder and do this across the network so there is no way for the projectile to get moved by player's unintentionally. You could even say the holder is now the Server and include the check if(Network.IsServer) and let the server handle updating the movment of the projectile when no one is holding it. Since it has a rigidbody I guess an explosion that has force could cause it to move so you'd want it's position to be updated across the network by the server in such a situation.

    Let me know how you go and once you have it working, if you can, post a video or some screen shots here about your gravity gun as it would be really neat to see it in action.
     
  50. Ithkul

    Ithkul

    Joined:
    Apr 8, 2012
    Posts:
    22
    This is a great place to start if you are serious about game development, but have little to no experience. For the more experienced developers the phase might be a bit slow, but several concepts not seen on other development platforms are thoroughly covered by this series.

    I applaud your time and effort put into this GTGD. Thanks to generous individuals like yourself, this community evolves. Keep up the good work, my friend. :D
     
    Last edited: Apr 10, 2012