Search Unity

Unity Multiplayer Invoke Method on players [Command] VS [ClientRpc]

Discussion in 'Multiplayer' started by LiOn0X0HeaRt, Jun 24, 2015.

  1. LiOn0X0HeaRt

    LiOn0X0HeaRt

    Joined:
    Jul 14, 2014
    Posts:
    38
    Hi
    i am trying to hit a player
    i have a simple raycasting attack
    and a simple damage script

    when i use the [ClientRpc] and attack the Host i get this error
    Rpc Function ("RpcMethodName" ) called on client
    if i attack the client with the host it works fine
    if i attack the client with a client nothing happens at all no errors too

    when i use the [Command] and attack the host it works Fine
    when i attack the client with the host it works on the server only the client doesn't actually move
    because it wasn't invoked locally

    when i attack a client with a client nothing works and no errors again

    this is the code
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.Networking;
    4. public class HitSimulate : NetworkBehaviour {
    5. public Transform raycastCenter;
    6. public LayerMask playerMask;
    7. public Collider[] overlapCasts;
    8. public float radius=1;
    9.  
    10.  
    11. public PlayerGetHit playerGetHit;
    12.  
    13. public Animator animator;
    14. public bool cast1;
    15. public bool attack1;
    16. [SyncVar]
    17. public GameObject HittedPlayer;
    18.  
    19. public bool timeTillSendAttackAgain;
    20.     public float timeTillSendAttackAgainTimer = 0.2f;
    21.     // Use this for initialization
    22.     void Start () {
    23.     raycastCenter = transform.FindChild("rayCenter");
    24. playerGetHit = GetComponentInParent<PlayerGetHit>();
    25.  
    26. animator = GetComponent<Animator>();
    27.     }
    28.  
    29.     public void AnimationCast1True()
    30.     {
    31.         cast1 = true;
    32.     }
    33.     public void AnimationCast1False()
    34.     {
    35.         cast1 = false;
    36.         animator.SetBool("Attack1",false);
    37.          attack1 = false;
    38.     }
    39.    
    40.     void Update () {
    41.     if(isLocalPlayer){
    42.             if(timeTillSendAttackAgain == true)
    43.             {
    44.                 timeTillSendAttackAgainTimer -=Time.deltaTime;
    45.                 if(timeTillSendAttackAgainTimer <=0)
    46.                 {
    47.                     timeTillSendAttackAgain = false;
    48.                     timeTillSendAttackAgainTimer = 0.2f;
    49.                 }
    50.             }
    51.  
    52.     if(Input.GetMouseButton(0))
    53.     {
    54.             animator.SetBool("Attack1",true);
    55.             attack1 = true;
    56.     }
    57.     if(cast1 == true){
    58.  
    59.     overlapCasts =     Physics.OverlapSphere(raycastCenter.position,radius,playerMask);
    60.         }else{
    61.             overlapCasts = null;
    62.         }
    63.         if(overlapCasts != null){
    64.             foreach(Collider tmp in overlapCasts)
    65.             {
    66.                 if(tmp != null){
    67.                
    68.                         //Debug.DrawLine(transform.position,tmp.gameObject.transform.position,Color.red);
    69.                
    70.             //    tmp.GetComponent<PhotonView>().RPC("Damage",PhotonTargets.All,transform.parent.forward);
    71. if(timeTillSendAttackAgain == false){
    72.  
    73.        
    74.                                 CmdDamagePlayer(tmp.gameObject);
    75.                         //    RpcDamagePlayer(tmp.gameObject);
    76.  
    77.                 timeTillSendAttackAgain = true;
    78.                 }
    79.            
    80.                 }
    81.             }
    82.         }
    83.     }
    84.  
    85.     }//Update Finish
    86.  
    87.     //
    88.  
    89. [Command]
    90.     void CmdDamagePlayer(GameObject hittedPlayer)
    91.     {
    92.    
    93.    
    94.         HittedPlayer=    hittedPlayer;
    95.         Debug.Log(hittedPlayer.name);
    96.         HittedPlayer.GetComponent<PlayerGetHit>().Damage(transform.forward);
    97.         //    hittedPlayer.GetComponent<PlayerGetHit>().curHealth -=10;
    98.    
    99.     }
    100.  
    101.     /*[ClientRpc]
    102.     void RpcDamagePlayer(GameObject hittedPlayer)
    103.     {
    104.    
    105.    
    106.         HittedPlayer=    hittedPlayer;
    107.         Debug.Log(hittedPlayer.name);
    108.         HittedPlayer.GetComponent<PlayerGetHit>().Damage(transform.forward);
    109.         //    hittedPlayer.GetComponent<PlayerGetHit>().curHealth -=10;
    110.    
    111.     }
    112.     */
    113.  
    114.     }
    115.  
    116.  
    117.  
    118.  
    119.  
    120.  
    121.  
    122.  
    123.  
    124.  
    125.  
    126.  
    127.  
    128.  
    129.  
    130.  
    131.  
    132.  
    133.  

    And this is the player getting hit code
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.UI;
    4. using UnityEngine.Networking;
    5. public class PlayerGetHit : NetworkBehaviour {
    6. public JM jm;
    7. public bool canGetHit;
    8. public float canGetHitTimer = 0.4f;
    9. public bool moveBackHit;
    10. public float moveBackHitTimer = 0.5f;
    11. public Vector3 hitterForwardSave;
    12.  
    13. public float TuneValue;
    14.  
    15. public Animator animator;
    16.  
    17. public int curHealth = 100;
    18. public int maxHealth = 100;
    19.  
    20.     // Use this for initialization
    21.     void Start () {
    22.     jm = GetComponent<JM>();
    23.     animator = GetComponent<Animator>();
    24.  
    25.  
    26.     }
    27.  
    28.     // Update is called once per frame
    29.     void Update () {
    30.  
    31.     if(moveBackHit == true)
    32.     {
    33.     animator.SetBool("BackHit",true);
    34.     transform.position += hitterForwardSave * 17* Time.deltaTime;
    35.     moveBackHitTimer -= Time.deltaTime;
    36.     if(moveBackHitTimer <=0)
    37.             {    animator.SetBool("BackHit",false);
    38.     moveBackHitTimer = 0.4f;
    39.     moveBackHit = false;
    40.     hitterForwardSave = Vector3.zero;
    41.     jm.enabled = true;
    42.     }
    43.     }
    44.  
    45.     if(canGetHit == false)
    46.     {
    47.     canGetHitTimer -=Time.deltaTime;
    48.     if(canGetHitTimer<=0)
    49.     {
    50.     canGetHitTimer = 0.3f;
    51.     canGetHit= true;
    52.     }
    53.     }
    54.  
    55.  
    56.     }
    57.  
    58.     public void Damage(Vector3 hitterForward)
    59.     {
    60.     if(canGetHit == true)
    61.     {
    62.     Debug.Log("gotHit");
    63.     canGetHit  = false;
    64.     jm.enabled = false;
    65.  
    66.     hitterForwardSave = hitterForward;
    67.     moveBackHit = true;
    68.  
    69.     }
    70.  
    71.     }
    72. }
    73.  

    I tried to use [Client] and it works on all of them no matter host or client
    but it works on the server only its not invoked on the players
    is it me or Unreal engine team started to work on unity? cuz its HARD as hell
    lol
     
    Last edited: Jun 24, 2015
  2. BluetoothBoy

    BluetoothBoy

    Joined:
    Jun 17, 2015
    Posts:
    14
    Client RPCs can only be sent from the server (host). Commands can only be sent from clients. Here's how to make it work both ways:

    Code (csharp):
    1.  
    2. [Command]
    3. void CmdDamagePlayer(arguments)
    4. {
    5.      RpcDamagePlayer(arguments);
    6. }
    7.  
    8. [ClientRpc]
    9. void RpcDamagePlayer(arguments)
    10. {
    11.      //All your damage stuff here!
    12. }
    13.  
    14. void Foo()
    15. {
    16.      //If we are the server, do the Rpc. If we are a client, do the Command.
    17.      if(!Network.isServer)
    18.           CmdDamagePlayer(arguments);
    19.      else
    20.           RpcDamagePlayer(arguments);
    21. }
    22.  
    Basically, as the host, you are already the server, so you can send an RPC to all clients by calling the RPC function. As a client, however, you do not have a direct connection to the other clients - thus, you have to tell the server to tell the clients to do something. Think of the server as the middleman in this case.

    Note that this code has to be used on an object with a NetworkIdentity attached or
    Code (csharp):
    1. Network.isServer
    will not be able to tell if you are the server or a client.
     
    elehin, danh1982, Azurne and 5 others like this.
unityunity