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

Only host can attack players

Discussion in 'Multiplayer' started by PvTGreg, May 25, 2017.

  1. PvTGreg

    PvTGreg

    Joined:
    Jan 29, 2014
    Posts:
    365
    Hi i cant seem to get my clients to attack others.
    the target variable dosent get filled adn even when i fill it manually they still dont attack
    it works perfectly fine for the host tho

    here is my attacking code





    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.AI;
    5. using UnityEngine.Networking;
    6. public class Attacking : NetworkBehaviour {
    7.     NavMeshAgent agent;
    8.     public Transform target;
    9.     public int Damage;
    10.     public float attackSpeed = 5;
    11.     public float distance;
    12.     public float attackDistance = 5;
    13.     private float nextDamage;
    14.     // Use this for initialization
    15.     public override void OnStartLocalPlayer()
    16.     {
    17.         agent = GetComponent<NavMeshAgent>();
    18.     }
    19.     private void Start()
    20.     {
    21.         nextDamage = Time.time + attackSpeed;
    22.     }
    23.     // Update is called once per frame
    24.     void FixedUpdate () {
    25.         if (!isLocalPlayer)
    26.         {
    27.             return;
    28.         }
    29.         if (Input.GetMouseButton(0))
    30.         {
    31.             target = null;
    32.         }
    33.             if (Input.GetMouseButton(1))
    34.         {
    35.             RaycastHit hit;
    36.  
    37.             if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 100))
    38.             {
    39.                 if (hit.collider.gameObject.tag == "enemy" || hit.collider.gameObject.tag == "Player")
    40.                 {
    41.                     target = hit.collider.transform;
    42.                 }
    43.                    
    44.             }
    45.         }
    46.         if(target != null)
    47.         {
    48.             distance = Vector3.Distance(transform.position, target.position);
    49.             agent.destination = target.position;
    50.             if (distance <= attackDistance)
    51.              {
    52.                 agent.isStopped = true;
    53.                 agent.ResetPath();
    54.                 if (nextDamage <= Time.time)
    55.                 {
    56.                     nextDamage = Time.time + attackSpeed;
    57.                     CmdTakeDamage(Damage);
    58.                 }
    59.             }
    60.         }
    61.     }
    62.     [Command]
    63.     public void CmdTakeDamage(int amount)
    64.     {
    65.         target.GetComponent<PlayerStats>().RpcTakeDamage(amount);
    66.     }
    67. }
    68.  



    and here is my health script


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityEngine.Networking;
    6. public class PlayerStats : NetworkBehaviour {
    7.     public const int maxHealth = 100;
    8.     public Transform spawnpoint;
    9.     [SyncVar]
    10.     public int currentHealth = maxHealth;
    11.  
    12.     public Slider healthSlider;                            
    13.     public Image damageImage;
    14.     public float flashSpeed = 5f;                            
    15.     public Color flashColour = new Color(1f, 0f, 0f, 0.1f);
    16.     public bool damaged;
    17.     // Use this for initialization
    18.     public override void OnStartLocalPlayer()
    19.     {
    20.         healthSlider = GameObject.Find("HUDCanvas/HealthUI/Slider").GetComponent<Slider>();
    21.         damageImage = GameObject.Find("HUDCanvas/HealthUI/DamageImage").GetComponent<Image>();
    22.         spawnpoint = GameObject.Find("SpawnPoint").transform;
    23.     }
    24.  
    25.     // Update is called once per frame
    26.     void Update () {
    27.         if (damaged)
    28.         {
    29.             // ... set the colour of the damageImage to the flash colour.
    30.             damageImage.color = flashColour;
    31.         }
    32.         // Otherwise...
    33.         else if (damageImage != null)
    34.         {
    35.             // ... transition the colour back to clear.
    36.             damageImage.color = Color.Lerp(damageImage.color, Color.clear, flashSpeed * Time.deltaTime);
    37.         }
    38.         damaged = false;
    39.  
    40.         if (Input.GetKeyDown(KeyCode.Space))
    41.         {
    42.             RpcTakeDamage(5);
    43.         }
    44.         healthSlider.value = currentHealth;
    45.     }
    46.     [ClientRpc]
    47.     public void RpcTakeDamage(int amount)
    48.     {
    49.          currentHealth -= amount;
    50.          RpcDamageEffect();
    51.          if (currentHealth <= 0)
    52.          {
    53.              currentHealth = maxHealth;
    54.              RpcRespawn();
    55.          }
    56.     }
    57.    
    58.     void RpcDamageEffect()
    59.     {
    60.         if (isLocalPlayer)
    61.         {
    62.             damaged = true;
    63.         }
    64.     }
    65.  
    66.     [ClientRpc]
    67.     void RpcRespawn()
    68.     {
    69.         if (isLocalPlayer)
    70.         {
    71.             // move back to zero location
    72.             transform.position = spawnpoint.position;
    73.         }
    74.     }
    75. }
    76.  
     
  2. PvTGreg

    PvTGreg

    Joined:
    Jan 29, 2014
    Posts:
    365
    ive tried every combination under the sun of client,target rpc's comammnds.

    the only way i was able to get it to slightly work was remove all of the clientrpc
    but then the damage effect and health bar wouldn't get updated
     
  3. PvTGreg

    PvTGreg

    Joined:
    Jan 29, 2014
    Posts:
    365
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.AI;
    5. using UnityEngine.Networking;
    6. public class Attacking : NetworkBehaviour {
    7.     NavMeshAgent agent;
    8.     public Transform target;
    9.     public int Damage;
    10.     public float attackSpeed = 5;
    11.     public float distance;
    12.     public float attackDistance = 5;
    13.     private float nextDamage;
    14.     // Use this for initialization
    15.     public override void OnStartLocalPlayer()
    16.     {
    17.         agent = GetComponent<NavMeshAgent>();
    18.     }
    19.     private void Start()
    20.     {
    21.         nextDamage = Time.time + attackSpeed;
    22.     }
    23.     // Update is called once per frame
    24.     void FixedUpdate () {
    25.         if (!isLocalPlayer) return;
    26.         if (Input.GetMouseButton(0))
    27.         {
    28.             target = null;
    29.         }
    30.             if (Input.GetMouseButton(1))
    31.         {
    32.             RaycastHit hit;
    33.  
    34.             if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 100))
    35.             {
    36.                 if (hit.collider.gameObject.tag == "enemy" || hit.collider.gameObject.tag == "Player")
    37.                 {
    38.                     target = hit.collider.transform;
    39.                 }
    40.                    
    41.             }
    42.         }
    43.         if(target != null)
    44.         {
    45.             distance = Vector3.Distance(transform.position, target.position);
    46.             agent.destination = target.position;
    47.             if (distance <= attackDistance)
    48.              {
    49.                 agent.isStopped = true;
    50.                 agent.ResetPath();
    51.                 if (nextDamage <= Time.time)
    52.                 {
    53.                     nextDamage = Time.time + attackSpeed;
    54.                     if (target.GetComponent<PlayerStats>())
    55.                     {
    56.                         target.GetComponent<PlayerStats>().TargetTakeDamage(Damage);
    57.                     }
    58.                     if (target.GetComponent<EnemyStats>())
    59.                     {
    60.                         target.GetComponent<EnemyStats>().TargetTakeDamage(Damage);
    61.                     }
    62.                     Debug.Log("attack sent");
    63.                 }
    64.             }
    65.         }
    66.     }
    67. }
    68.  



    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityEngine.Networking;
    6. public class PlayerStats : NetworkBehaviour {
    7.     public const int maxHealth = 100;
    8.     public Transform spawnpoint;
    9.  
    10.     [SyncVar(hook = "OnChangeHealth")]
    11.     public int currentHealth = maxHealth;
    12.  
    13.     public Slider healthSlider;                            
    14.     public Image damageImage;
    15.     public float flashSpeed = 5f;                            
    16.     public Color flashColour = new Color(1f, 0f, 0f, 0.1f);
    17.     public bool damaged;
    18.     // Use this for initialization
    19.     public override void OnStartLocalPlayer()
    20.     {
    21.         healthSlider = GameObject.Find("HUDCanvas/HealthUI/Slider").GetComponent<Slider>();
    22.         damageImage = GameObject.Find("HUDCanvas/HealthUI/DamageImage").GetComponent<Image>();
    23.         spawnpoint = GameObject.Find("SpawnPoint").transform;
    24.     }
    25.  
    26.     // Update is called once per frame
    27.     void Update () {
    28.         if (!isLocalPlayer) return;
    29.         if (damaged)
    30.         {
    31.             // ... set the colour of the damageImage to the flash colour.
    32.             damageImage.color = flashColour;
    33.         }
    34.         // Otherwise...
    35.         else if (damageImage != null)
    36.         {
    37.             // ... transition the colour back to clear.
    38.             damageImage.color = Color.Lerp(damageImage.color, Color.clear, flashSpeed * Time.deltaTime);
    39.         }
    40.         damaged = false;
    41.  
    42.         if (Input.GetKeyDown(KeyCode.Space))
    43.         {
    44.             TargetTakeDamage(5);
    45.         }
    46.     }
    47.  
    48.     public void TargetTakeDamage(int amount)
    49.     {
    50.         Debug.Log("Attack recived");
    51.         currentHealth -= amount;
    52.         RpcDamageEffect();
    53.         if (currentHealth <= 0)
    54.         {
    55.             currentHealth = maxHealth;
    56.             RpcRespawn();
    57.         }
    58.     }
    59.     [ClientRpc]
    60.     void RpcDamageEffect()
    61.     {
    62.         if (isLocalPlayer)
    63.         {
    64.             damaged = true;
    65.         }
    66.     }
    67.     void OnChangeHealth(int currentHealth)
    68.     {
    69.         healthSlider.value = currentHealth;
    70.     }
    71.     [ClientRpc]
    72.     void RpcRespawn()
    73.     {
    74.         if (isLocalPlayer)
    75.         {
    76.             // move back to zero location
    77.             transform.position = spawnpoint.position;
    78.         }
    79.     }
    80. }
    81.  



    ok with my current code the only error i get is

    RPC Function RpcDamageEffect called on client.
    UnityEngine.Debug:LogError(Object)
    PlayerStats:CallRpcDamageEffect()
    PlayerStats:TargetTakeDamage(Int32) (at Assets/PlayerStats.cs:52)
    Attacking:FixedUpdate() (at Assets/Attacking.cs:56)


    similar errors for when the player dies it wont call his re spawn function

    how can i get around this?
     
  4. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,462
    currentHealth is a SyncVar so you can only modify it on the Server. Just apply the change on the server and the clients will update their variable, you can still Rpc call the damage routine, but there is no need to modify a SyncVar on clients.
     
  5. PvTGreg

    PvTGreg

    Joined:
    Jan 29, 2014
    Posts:
    365
    fixed it by changing my atacking code

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.AI;
    5. using UnityEngine.Networking;
    6. public class Attacking : NetworkBehaviour {
    7.     NavMeshAgent agent;
    8.     public Transform target;
    9.     public string targetIdentity;
    10.     public int Damage;
    11.     public float attackSpeed = 5;
    12.     public float distance;
    13.     public float attackDistance = 5;
    14.     private float nextDamage;
    15.     // Use this for initialization
    16.     public override void OnStartLocalPlayer()
    17.     {
    18.         agent = GetComponent<NavMeshAgent>();
    19.     }
    20.     private void Start()
    21.     {
    22.         nextDamage = Time.time + attackSpeed;
    23.     }
    24.     // Update is called once per frame
    25.     void FixedUpdate () {
    26.         if (!isLocalPlayer) return;
    27.         if (Input.GetMouseButton(0))
    28.         {
    29.             target = null;
    30.         }
    31.             if (Input.GetMouseButton(1))
    32.         {
    33.             RaycastHit hit;
    34.  
    35.             if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 100))
    36.             {
    37.                 if (hit.collider.gameObject.tag == "enemy" || hit.collider.gameObject.tag == "Player")
    38.                 {
    39.                     target = hit.collider.transform;
    40.                 }
    41.                    
    42.             }
    43.         }
    44.         if(target != null)
    45.         {
    46.             distance = Vector3.Distance(transform.position, target.position);
    47.             agent.destination = target.position;
    48.             if (distance <= attackDistance)
    49.              {
    50.                 agent.isStopped = true;
    51.                 agent.ResetPath();
    52.                 if (nextDamage <= Time.time)
    53.                 {
    54.                     nextDamage = Time.time + attackSpeed;
    55.                     if (target.GetComponent<PlayerStats>())
    56.                     {
    57.                         targetIdentity = target.name;
    58.                         CmdWhatWasShot(targetIdentity,Damage);
    59.                     }
    60.                     if (target.GetComponent<EnemyStats>())
    61.                     {
    62.                         targetIdentity = target.name;
    63.                         CmdWhatWasShot(targetIdentity, Damage);
    64.                     }
    65.                 }
    66.             }
    67.         }
    68.     }
    69.     [Command]
    70.     void CmdWhatWasShot(string id,int dmg)
    71.     {
    72.         GameObject go = GameObject.Find(id);
    73.         if (go.GetComponent<PlayerStats>())
    74.         {
    75.             go.GetComponent<PlayerStats>().TakeDamage(dmg);
    76.         }
    77.         if (go.GetComponent<EnemyStats>())
    78.         {
    79.             go.GetComponent<EnemyStats>().TakeDamage(dmg);
    80.         }
    81.     }
    82.  
    83. }
    84.