Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Player's controls or camera are the wrong way around?

Discussion in 'Multiplayer' started by Sargon_of_Akkad, Feb 1, 2011.

  1. Sargon_of_Akkad

    Sargon_of_Akkad

    Joined:
    Jan 16, 2011
    Posts:
    147
    Greetings all, I've managed to get a simple test game going, where on the connection of a player to my 'game' it instantiates a cube for them to drive around using basic WASD controls, followed by a camera. It works fine before a second player connects to the game.

    However, when the second player connects, they are instantiated as they should be but the player's controls appear to have been swapped around. The camera and box for player one are controlled by player two's keyboard, and vice-versa. I cannot see for the life of me why this is happening. Any help please, I've spent hours on this now! :(
     
  2. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,086
    Are you using Network.Instantiate, or allocating your own viewId's? Are you enabling/disabling relevant control scripts with networkView.IsMine?
     
  3. Sargon_of_Akkad

    Sargon_of_Akkad

    Joined:
    Jan 16, 2011
    Posts:
    147
    Code (csharp):
    1. var Player : Transform;
    2.  
    3. // This function will be called when network is loaded
    4. function OnNetworkLoadedLevel ()
    5. {  
    6. // Instantiate object to the network in the position of Spawn
    7. Network.Instantiate(Player, transform.position, transform.rotation, 0);
    8. }
    This is my instantiate script. The Player transform is a prefab consisting of a cube with the movement controls attached with a camera childed to it, using if(networkView.isMine) statement to encompass any of the keyboard inputs, which means that the players only control one cube, however, its the wrong darned one.
     
  4. JRavey

    JRavey

    Joined:
    May 12, 2009
    Posts:
    2,377
    Why not share the control code with us?
     
  5. Sargon_of_Akkad

    Sargon_of_Akkad

    Joined:
    Jan 16, 2011
    Posts:
    147
    My apologies, I didn't think to because it's pretty basic.

    Code (csharp):
    1. var moveSpeed:float = 10;
    2. var jumpPower:float = 350;
    3.  
    4. function FixedUpdate ()
    5. {
    6. if (networkView.isMine)
    7. {
    8. if(Input.GetButton("forward"))
    9. {
    10. transform.position += transform.forward * moveSpeed * Time.deltaTime;
    11. }
    12.  
    13. if(Input.GetButton("backward"))
    14. {
    15. transform.position += -transform.forward * moveSpeed * Time.deltaTime;
    16. }
    17.  
    18. if(Input.GetButton("left"))
    19. {
    20. transform.position += -transform.right * moveSpeed * Time.deltaTime;
    21. }
    22.  
    23. if(Input.GetButton("right"))
    24. {
    25. transform.position += transform.right * moveSpeed * Time.deltaTime;
    26. }
    27.  
    28. }
    29. }
     
  6. JRavey

    JRavey

    Joined:
    May 12, 2009
    Posts:
    2,377
    You're right, that is pretty basic, but we can eliminate it now.

    The networkView is attached and is associated with the transform of the object, I'm assuming.

    Do you have anything in the player's scripts related to Awake or Start which might be changing something?
     
  7. Sargon_of_Akkad

    Sargon_of_Akkad

    Joined:
    Jan 16, 2011
    Posts:
    147
    I tried to keep the movement as simple as possible for the time being to make sure it wasn't something there that was causing the problems.

    Here is the GUI script that enables you to connect from one computer to another:

    Code (csharp):
    1. // IP Address of the server
    2. var remoteIP = "127.0.0.1";
    3. // Port of the server (to connect)
    4. var remotePort = 25000;
    5. // Port of the server (to listen)
    6. var listenPort = 25000;
    7. // For enabling/disabling NAT usage
    8. var useNAT = false;
    9. // Variables to show your IP and Port
    10. var yourIP = "";
    11. var yourPort = "";
    12.  
    13. function OnGUI ()
    14. {
    15. // Checking if you are connected to the server or not
    16. if (Network.peerType == NetworkPeerType.Disconnected)
    17. {
    18. // If not connected
    19.  
    20. if (GUI.Button (new Rect(10,10,100,30),"Connect"))
    21. {
    22. Network.useNat = useNAT;
    23. // Connecting to the server
    24. Network.Connect(remoteIP, remotePort);
    25. }
    26. if (GUI.Button (new Rect(10,50,100,30),"Start Server"))
    27. {
    28. Network.useNat = useNAT;
    29. // Creating server
    30. Network.InitializeServer(32, listenPort);
    31.  
    32. // Notify our objects that the level and the network is ready
    33. for (var go : GameObject in FindObjectsOfType(GameObject))
    34. {
    35. // About OnNetworkLoadedLevel later
    36. go.SendMessage("OnNetworkLoadedLevel", SendMessageOptions.DontRequireReceiver);
    37. }
    38. }
    39.  
    40. // Fields to insert ip address and port
    41. remoteIP = GUI.TextField(new Rect(120,10,100,20),remoteIP);
    42. remotePort = parseInt(GUI.TextField(new Rect(230,10,40,20),remotePort.ToString()));
    43. }
    44. else
    45. {
    46. // If connected
    47.  
    48. // Getting your ip address and port
    49. ipaddress = Network.player.ipAddress;
    50. port = Network.player.port.ToString();
    51.  
    52. GUI.Label(new Rect(140,20,250,40),"IP Adress: "+ipaddress+":"+port);
    53.  
    54. if (GUI.Button (new Rect(10,10,100,50),"Disconnect"))
    55. {
    56. // Disconnect from the server
    57. Network.Disconnect(200);
    58. }
    59. }
    60. }
    61.  
    62. function OnConnectedToServer()
    63. {
    64. // Notify our objects that the level and the network are ready
    65. for (var go : GameObject in FindObjectsOfType(GameObject))
    66. go.SendMessage("OnNetworkLoadedLevel", SendMessageOptions.DontRequireReceiver);
    67. }
     
  8. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,086
    I would try moving the OnNetworkLoadedLevel for loop that is directly under Network.InitializeServer in OnGUI() to OnServerInitialized(), similarly to how you're doing it with OnConnectedToServer()
     
  9. JRavey

    JRavey

    Joined:
    May 12, 2009
    Posts:
    2,377
    I find it interesting that when a player connects, it tells every GameObject to run OnNetworkLevelLoaded. This is a bit different than how I do it, which is entirely manual (without Network.Instantiate). Wouldn't that tell every GameObject in the scene to run OnNetworkLevelLoaded and thusly call Network.Instantiate again building another player? How many GameObjects are actually in this scene when the 2nd player connects?
     
  10. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,086
    By looping through all objects and calling OnNetworkLevelLoaded in OnServerInitialized() and OnConnectedToServer(), it should only loop through all the objects once for each player (the host included), and thus, only spawn one player prefab for each player, I think.
     
  11. Sargon_of_Akkad

    Sargon_of_Akkad

    Joined:
    Jan 16, 2011
    Posts:
    147
    Do you mean replace the OnNetworkLoadedLevel function with OnServerInitialized, but keeping the existing code for it? Won't I need to change other references to OnNetworkLoadedLevel with OnServerInitialized?

    Thanks for the help guys, I really appreciate it.
     
  12. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,086
    Nooo, I meant:

    Take this:

    Code (csharp):
    1. if (GUI.Button (new Rect(10,50,100,30),"Start Server"))
    2. {
    3.     Network.useNat = useNAT;
    4.     // Creating server
    5.     Network.InitializeServer(32, listenPort);
    6.  
    7.     // Notify our objects that the level and the network is ready
    8.     for (var go : GameObject in FindObjectsOfType(GameObject))
    9.     {
    10.         // About OnNetworkLoadedLevel later
    11.         go.SendMessage("OnNetworkLoadedLevel", SendMessageOptions.DontRequireReceiver);
    12.     }
    13. }
    Replace with this (remove the OnNetworkLoadedLevel loop):
    Code (csharp):
    1.  
    2. if (GUI.Button (new Rect(10,50,100,30),"Start Server"))
    3. {
    4.     Network.useNat = useNAT;
    5.     // Creating server
    6.     Network.InitializeServer(32, listenPort);
    7. }
    Add this at the bottom:

    Code (csharp):
    1. function OnServerInitialized()
    2. {
    3.     // Notify our objects that the level and the network are ready
    4.     for (var go : GameObject in FindObjectsOfType(GameObject))
    5.         go.SendMessage("OnNetworkLoadedLevel", SendMessageOptions.DontRequireReceiver);
    6. }
    7.  
     
  13. Sargon_of_Akkad

    Sargon_of_Akkad

    Joined:
    Jan 16, 2011
    Posts:
    147
    Thanks for that, I gave it a try and while the cubes and their cameras' control beautifully, they are still using each other's keyboard! I am baffled, how is it that nobody else has had an issue like this?

    Is there a normal step to take when setting this up that I have missed?

    I used this multiplayer tutorial to get to this stage: http://www.scribd.com/doc/44574681/Multi-Player-Tutorial, however it didn't include controls for the cubes or the networkView.isMine information, I had to figure out that on my own.
     
  14. Sargon_of_Akkad

    Sargon_of_Akkad

    Joined:
    Jan 16, 2011
    Posts:
    147
    I assume it would be easier to just change the assignment of the cameras around, any idea how to do that?
     
  15. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,086
    Ohhh, I didn't even think of that. I bet if you checked the NetworkView.owner, the right players are actually controlling the object they are supposed to, you just assigned the cameras wrong.

    How exactly are you doing it? I always do something like this, I think its pretty common practice:

    1) Have ONE camera in the scene by default, with no networkview, attach whatever camera script your using to it, but do not set a target in the script, leave it null.
    2) Write a new script to be attached to your player prefabs that get instantiated, called PlayerNetworkInit:

    Code (csharp):
    1. OnNetworkInstantiate(info : NetworkMessageInfo){
    2.     if(networkView.IsMine){
    3.         Camera.main.GetComponent(MyCameraScript).target = transform;
    4.     }
    5. }
    Its good to have a PlayerNetworkInit script, because you can enable/disable all scripts on the instantiated prefab that you need to depending on whether or not this is the current player's owned prefab, or a remote prefab of another player in on the network. Then you don't have to pepper all your scripts with networkView.IsMine.

    For example, instead of doing what you're doing in your control script with the networkView.Ismine, you could do this in PlayerNetworkInit:
    Code (csharp):
    1.  
    2. OnNetworkInstantiate(info : NetworkMessageInfo){
    3.     if(networkView.IsMine){
    4.         Camera.main.GetComponent(MyCameraScript).target = transform;
    5.         GetComponent(MyControlScript).enabled = true;
    6.     }
    7.     else{
    8.         //this prefab is not owned by me, so I shouldn't be able to control it
    9.         GetComponent(MyControlScript).enabled = false;
    10.     }
    11. }
     
  16. Sargon_of_Akkad

    Sargon_of_Akkad

    Joined:
    Jan 16, 2011
    Posts:
    147
    That all makes sense to me except I have no idea what MyCameraScript and MyControlScript is supposed to be. I have no scripts on the camera except for the network GUI script (called ConnectionGUI.js) which displays the connect/host buttons, and on the player prefab I have the basic movement one only (TankMove.js).

    If I put these scripts as named above in where MyCameraScript and MyControlScript are, I get an error: "MissingFieldException: Field 'ConnectionGUI.target' not found.", and the camera does not move from its starting position.

    I must sound incredibly remedial asking such basic questions, but honestly I'm not, I've managed to figure out most of what I need on my own! :D

    Thanks again!
     
  17. JRavey

    JRavey

    Joined:
    May 12, 2009
    Posts:
    2,377
    If the player already has a camera, make sure remote players' cameras are not being drawn. This is probably a side note.
     
  18. Sargon_of_Akkad

    Sargon_of_Akkad

    Joined:
    Jan 16, 2011
    Posts:
    147
    I've removed all other cameras from the scene other than the main camera, which is not attached to anything.
     
  19. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,086
    There's no reason to have your ConnectionGUI script on your camera. I would create an empty gameobject and name it "NetworkManager" or something and put it on there.

    Then put a camera control script on your camera, like one of the ones provided with the standard assets, for testing purposes. I would suggest SmoothFollow.js, for example. That one should have a target variable.

    Then in PlayerNetworkInit, instead of MyCameraScript put SmoothFollow there (I just made up names for argument's sake in the original code I gave you).
     
    Last edited: Feb 1, 2011
  20. JRavey

    JRavey

    Joined:
    May 12, 2009
    Posts:
    2,377
    Sargon, if you want, you can just zip up the Assets folder and post it/mail it and I will take a look.
     
  21. Sargon_of_Akkad

    Sargon_of_Akkad

    Joined:
    Jan 16, 2011
    Posts:
    147
    By jove, I think I've got it! You are an absolute star for helping me out with that, honestly, I couldn't have done it without you, it works like a dream. I saw someone on roughly page 8 had the same question but nobody had helped him out, so hopefully this thread will help other noobs like myself in future! Thanks again!
     
  22. PrimeDerektive

    PrimeDerektive

    Joined:
    Dec 13, 2009
    Posts:
    3,086
    No problem dude, glad to help.
     
  23. Psyco

    Psyco

    Joined:
    Oct 5, 2012
    Posts:
    5
    having the same problem but i have a master server set up with a lobby system.

    network init looks like

    function OnNetworkInstantiate (msg : NetworkMessageInfo) {
    // This is our own player
    if (networkView.isMine)
    {
    //camera.main.enabled=false;


    localPlayer=true;
    networkView.RPC("setName", RPCMode.Others, thisName);

    Destroy(GameObject.Find("LevelCamera"));
    thisName=PlayerPrefs.GetString("playerName");

    //var gun : Machinegun = transform.Find("NyanFighter/Weapon").GetComponent("Machinegun") as Machinegun;
    //gun.localPlayer=true;
    var tmp1 : PlayerControls = GetComponent(PlayerControls) as PlayerControls;
    tmp1.enabled = true;


    }
    // This is just some remote controlled player, don't execute direct
    // user input on this. DO enable multiplayer controll
    else
    {
    thisName="Remote"+Random.Range(1,10);
    name += thisName;

    transform.Find("Camera").gameObject.active=false;

    var tmp2 : PlayerControls = GetComponent(PlayerControls) as PlayerControls;
    tmp2.enabled = false;
    //var tmp5 : MouseLook = GetComponent(MouseLook) as MouseLook;
    //tmp5.enabled = false;

    networkView.RPC("askName", networkView.viewID.owner, Network.player);


    }
    }