Search Unity

How do I make a client hosted game with multiple character classes?

Discussion in 'Multiplayer' started by Wab17, Jun 18, 2017.

  1. Wab17

    Wab17

    Joined:
    Jun 16, 2017
    Posts:
    9
    So I've got a network manager, enemy spawner, players which are synced and can shoot projectiles with a health system and spawn points, but I now want to diversify my game (it's meant to be a MoBA so different classes are a necessity) and I'm running into issues. The first is setting up what class players are when they connect, but there is only 1 set prefab I can spawn a player as within the network manager. How would I make the player prefab change on connection depending on what character has been selected. Im assuming I would have to neglect the player prefab and just add it to the list of spawnables to the server, but I dont know how you would cause a character to be spawned if a player connects.

    It's a 2d sidescroller.

    New to C# and programming in Unity so rigorous reasoning is appreciated, need this game for my Coursework.
     
  2. robochase

    robochase

    Joined:
    Mar 1, 2014
    Posts:
    244
    decouple the character art from your player prefab. in otherwords, just make your player prefab a shell of sorts that can load the appropriate character via command/rpc/whatever else
     
    Wab17 likes this.
  3. Wab17

    Wab17

    Joined:
    Jun 16, 2017
    Posts:
    9
    Ah makes sense. So should the prefab load and replace itself with another prefab?

    EDIT: on another note I need help with directional shooting, I make the server run the Command to instantiate a bullet based on the normalized directional vector from player -> mouse. When a player spawns in, they instantiate a child camera and tag it "MainCamera". The issue is that the direction vector finds the mouse position from the first initialised camera, so in this case the host. This happens since I'm using Camera.main.ScreenToWorldPoint(Input.mousePosition) where main is the first camera initialised. Any ideas on how to reference the camera the input user is using?
     
    Last edited: Jun 18, 2017
  4. Wab17

    Wab17

    Joined:
    Jun 16, 2017
    Posts:
    9
    Code (CSharp):
    1.    
    2. [Command]
    3.     void CmdFire() {
    4.         Vector3 worldMousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    5.         print(worldMousePos);
    6.         Vector2 direction = (Vector2)(worldMousePos)- (Vector2)this.transform.position;
    7.         print(direction);
    8.         direction.Normalize();
    9.         var projectile = (GameObject)Instantiate(projectilePrefab, transform.position + (Vector3)(direction * 0.5f), Quaternion.identity);
    10.         projectile.GetComponent<Rigidbody2D>().velocity = direction * bulletVelocity;
    11.         NetworkServer.Spawn(projectile);
    12.         Destroy(projectile, 2f);
    13.     }
    14.     void GenerateCamera() {
    15.         Vector3 pos= new Vector3(transform.position.x, transform.position.y, -5f);
    16.         var cam = (GameObject)Instantiate(cameraPrefab, pos, transform.rotation);
    17.         cam.transform.parent = transform;
    18.         cam.tag = "MainCamera";
    19. }
     
  5. robochase

    robochase

    Joined:
    Mar 1, 2014
    Posts:
    244
    no, you don't want the player prefab to replace itself - you should keep it intact. i mean something roughly like this...

    Code (CSharp):
    1. // you'll set this static characterType var before the player joins the game...like based on what they chose at the character select menu for example.
    2. static public int CharacterType = 2;// pretend 2 == Wizard, etc.
    3.  
    4. override public void OnStartLocalPlayer()
    5. {
    6.     if (!isServer)
    7.     {
    8.         // tell server we want to switch to the character we chose in the character select menu.
    9.         CmdSwitchTo(CharacterType);
    10.     }
    11.     else
    12.     {
    13.         // server can just switch right away.
    14.         DoSwitch(CharacterType);
    15.     }
    16. }
    17.  
    18. [Command]
    19. void CmdSwitchTo(int characterType)
    20. {
    21.     // server should check to see if it's ok to switch characters here.  but for now just assume it's fine and tell everyone that this player is switching
    22.     RpcSwitchTo(characterType);
    23. }
    24.  
    25. [ClientRpc]
    26. void RpcSwitchTo(int characterType)
    27. {
    28.     DoSwitch(characterType);
    29. }
    30.  
    31. void DoSwitch(int characterType)
    32. {
    33.     // GetCharacterPrefabForCharacterType would be a funciton that returns a character prefab when given an index. for example, if you pass it '2', it would return the Wizard prefab
    34.     GameObject characterInstance = (GameObject) Instantiate(GetCharacterPrefabForCharacterType(characterType));
    35.  
    36.     // (optional) parent the character to the player. it should now move along with the player.
    37.     characterInstance.transform.parent = transform.parent;
    38.     characterInstance.transform.localPosition = Vector3.zero;
    39.     characterInstance.transform.localRotation = Quaternion.identity;
    40. }
     
    Wab17 likes this.
  6. Wab17

    Wab17

    Joined:
    Jun 16, 2017
    Posts:
    9
    Thank you so much, perfect
     
  7. Deleted User

    Deleted User

    Guest

    Make a public Gameobject MyCamera variable in one of your networkbehaviours, link the camera from the player prefab onto it and disable that object by default. Then in your public override void OnStartLocalPlayer() function you enable this camera only for your player.
    Then use this: MyCamera.getcomponent<Camera>().ScreenToWorldPoint(Input.mousePosition) instead of:
    Camera.main.ScreenToWorldPoint(Input.mousePosition)

    I hope this helps

    -Speedex
     
  8. Wab17

    Wab17

    Joined:
    Jun 16, 2017
    Posts:
    9
    I fixed it, simply made the calculations be processed locally and then telling the server to instantiate