Search Unity

[SOLVED] Client raycast not working

Discussion in 'Multiplayer' started by Joozua, Feb 3, 2016.

  1. Joozua

    Joozua

    Joined:
    Mar 24, 2014
    Posts:
    18
    Hey,

    Ran into a weird problem while testing out my shooting function in 2D game. Apparently only the servers host has a working raycast + only the host is able to deal damage (because of the working raycast). Meanwhile the clients raycast is all bonkers. Any idea what is causing this?

    This is the script handling the shooting.
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.Networking;
    4.  
    5. public class Shoot : NetworkBehaviour {
    6.  
    7.     public int dmg = 1;
    8.     [SerializeField]
    9.     private RaycastHit2D hit;
    10.  
    11.     GameObject player = GameObject.FindGameObjectWithTag("Player");
    12.  
    13.     Transform Shootpoint;
    14.  
    15.     // Use this for initialization
    16.     void Awake () {
    17.  
    18.         Shootpoint = transform.FindChild("Shootpoint");
    19.         if (Shootpoint == null)
    20.         {
    21.             Debug.Log("No 'shootpoint' set!");
    22.         }
    23.     }
    24.  
    25.     // Update is called once per frame
    26.     void Update ()
    27.     {
    28.         CheckShooting();
    29.     }
    30.  
    31.     void Shooting()
    32.     {
    33.         //Debug.Log("Testi testi");
    34.         Vector2 ShootPointPos = new Vector2(Shootpoint.position.x, Shootpoint.position.y);
    35.         Vector2 ShootDirection = (Vector2)GameObject.FindGameObjectWithTag("Player").transform.position - ShootPointPos;
    36.  
    37.         RaycastHit2D hit = Physics2D.Raycast(ShootPointPos, ShootDirection.normalized, -100);
    38.         Debug.DrawLine(ShootPointPos, ShootDirection.normalized * -100);
    39.         Debug.Log(hit.transform.tag);
    40.  
    41.             if (hit.transform.tag == "Player")
    42.             {
    43.                 string uIdentity = hit.transform.name;
    44.                 CmdTellServerWhoWasShot(uIdentity, dmg);
    45.             }
    46.     }
    47.  
    48.     void CheckShooting()
    49.     {
    50.         if (!isLocalPlayer)
    51.         {
    52.             return;
    53.         }
    54.  
    55.         if (Input.GetKey(KeyCode.A))
    56.         {
    57.             Shooting();
    58.         }
    59.     }
    60.  
    61.     [Command]
    62.     void CmdTellServerWhoWasShot(string uniqueID, int dmg)
    63.     {
    64.         GameObject go = GameObject.Find(uniqueID);
    65.         go.GetComponent<hp>().lowerHealth(dmg);
    66.     }
    67.  
    68.  
    69. }
    70.  
    Here is also a gif about the problem (the raycast is swaying under the client, but the hosts raycast is pointing straight to facing direction).


    Edit: The gif is recorded on host, but the problem is on client side. The gif is only there to show you the problem.
     
    Last edited: Feb 3, 2016
  2. Scorr

    Scorr

    Joined:
    Jul 2, 2013
    Posts:
    73
    Make sure the FindGameObjectWithTag("Player") is finding the right GameObject. If your client joins when your host is already instantiated you'd have two GameObjects with the 'Player' tag.
     
  3. Joozua

    Joozua

    Joined:
    Mar 24, 2014
    Posts:
    18
    I'm using another script to give each player unique ID. Is there a way I could use this to give both players the raycasting?
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.Networking;
    4.  
    5. public class Player_ID : NetworkBehaviour {
    6.  
    7.     [SyncVar]
    8.     public string playerUnique;
    9.     private NetworkInstanceId pNetID;
    10.     private Transform ntransform;
    11.  
    12.     public override void OnStartLocalPlayer()
    13.     {
    14.         GetNetID();
    15.         SetID();
    16.     }
    17.  
    18.     // Use this for initialization
    19.     void Awake ()
    20.     {
    21.         ntransform = transform;
    22.     }
    23.    
    24.     // Update is called once per frame
    25.     void Update ()
    26.     {
    27.         if(ntransform.name == "" || ntransform.name == "Player(Clone)")
    28.         {
    29.             SetID();
    30.         }
    31.     }
    32.  
    33.     [Client]
    34.     void GetNetID()
    35.     {
    36.         pNetID = GetComponent<NetworkIdentity>().netId;
    37.         CmdTellServerMyID(MakeUniqueID());
    38.     }
    39.  
    40.     void SetID()
    41.     {
    42.         if (!isLocalPlayer)
    43.         {
    44.             ntransform.name = playerUnique;
    45.         }
    46.         else
    47.         {
    48.             ntransform.name = MakeUniqueID();
    49.         }
    50.     }
    51.  
    52.     string MakeUniqueID()
    53.     {
    54.         string uniqueName = "Player" + pNetID.ToString();
    55.         return uniqueName;
    56.     }
    57.  
    58.     [Command]
    59.     void CmdTellServerMyID(string name)
    60.     {
    61.         playerUnique = name;
    62.     }
    63. }
    64.  


    Both of these players go under the same tag ("Player").
     
  4. Scorr

    Scorr

    Joined:
    Jul 2, 2013
    Posts:
    73
    I think you're overthinking this. I don't know what your setup is but if your 'Shoot' NetworkBehaviour is attached to the player game object you could use the 'gameObject' variable to reference your player's game object.
     
  5. Joozua

    Joozua

    Joined:
    Mar 24, 2014
    Posts:
    18
    I'm not quite sure what you mean (as I'm fairly new with Unity and Unet), but I'm definitely overthinking this problem. I tried a not-so-great solution by simply checking if the player name in the hierarchy was "Player1" or "Player2" and gave both of them separate Void shooting(). This is by no means a great way to do this, but I just wanted to try what would happen. Player2 (client) now has two raycast lines, one working as intended and one broken (the one in the gif I posted before).

    Code (CSharp):
    1. if (Input.GetKey(KeyCode.A))
    2.         {
    3.             if(GameObject.Find("Player1"))
    4.             {
    5.                 Shooting();
    6.             }
    7.             if (GameObject.Find("Player2"))
    8.             {
    9.                 Shooting2();
    10.             }
    11.         }
    This is not something I want to do, but at least it did something.
     
  6. Scorr

    Scorr

    Joined:
    Jul 2, 2013
    Posts:
    73
    I'm assuming your 'Shoot' MonoBehaviour is on the player's game object.

    If so, instead of doing
    Vector2 ShootDirection = (Vector2)GameObject.FindGameObjectWithTag("Player").transform.position - ShootPointPos;

    You could do
    Vector2 ShootDirection = (Vector2)transform.position - ShootPointPos;

    'transform' here indicates the transform of the game object that the script is attached to. This way you should always get the current player's game object without having to look it up.
     
    Joozua likes this.
  7. Joozua

    Joozua

    Joined:
    Mar 24, 2014
    Posts:
    18
    Thank you Scrorr, that did the trick. I believe at some point I had a similar line of code, but somehow missed the problem itself. Like you said, I was overthinking it!