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. Dismiss Notice

Change a variable from client side

Discussion in 'Multiplayer' started by msd1357, Sep 7, 2016.

  1. msd1357

    msd1357

    Joined:
    Jul 7, 2014
    Posts:
    8
    Hello,
    I made a simple multiplayer game. The Update() scrip of player is as below. when player press spacebar it spawn an enemy in a predefined position.

    void Update ()
    {
    if (!isLocalPlayer)
    return;
    if (Input.GetKeyDown(KeyCode.Space))
    CmdMakeEnemy ();​
    }
    [Command]
    public void CmdMakeEnemy()
    {
    //posArray is some predefined positions
    int index = Random.Range (0, 4);
    var enemy = (GameObject)Instantiate (EnemyPrefab, posArray [index], rotArray [index]);
    NetworkServer.Spawn (enemy);​
    }
    then when i click on enemy I want to its play an animation and death. then i wrote this script for enemy:
    private int animationStep = 1;
    public void OnMouseDown()
    {
    animationStep = 2;​
    }
    void Update ()
    {
    if (animationStep == 1)
    {
    //Play run animation on enemy;
    }
    if (animationStep == 2)
    {
    //Play Death animation and death;
    }​
    }
    When I run two instance of game(one for server and the other for client) and click on enemy in the server version everything is fine and death animation played in both side client and server for that enemy. but when i click on an enemy in the client, only the client version is dead and enemy in the server version playe animation in setp 1 and does not death. in fact animationStep variable doesn't set to 2 in server side. I also use [SyncVar] for animationStep variable but nothing happen.
    please help me what should I do?
     
    Last edited: Sep 7, 2016
  2. Chom1czek

    Chom1czek

    Joined:
    Sep 19, 2015
    Posts:
    66
    Code (CSharp):
    1. [SyncVar (hook="OnAnimationStepChanged")] private int animationStep = 1;
    2.  
    3. public override void OnStartClient()
    4. {
    5.    OnAnimationStepChanged(animationStep);
    6. }
    7.  
    8. public void OnAnimationStepChanged(int animationStep)
    9. {
    10.    this.animationStep = animationStep;
    11.    **Player animation here**
    12. }
    13.  
    14. [Command] public void CmdSetAnimationStep(int newAnimationStep)
    15. {
    16.    animationStep = newAnimationStep;
    17. }
    18.  
    19. void Update()
    20. {
    21.    if( ! isLocalPlayer) return;
    22.  
    23.    if(SomeInput)
    24.    {
    25.      CmdSetAnimationStep(2);
    26.    }
    27. }
     
  3. msd1357

    msd1357

    Joined:
    Jul 7, 2014
    Posts:
    8
    Thanks for your response. But are you sure about your script? I implement it in my enemy code but get approximately same result as previous. when i click on the enemy in the client nothing happened but when I click it on server plays step 2 animation. I just remove isLocalPlayer checking from update function because it always returns false and then update function never continues.
     
  4. Chom1czek

    Chom1czek

    Joined:
    Sep 19, 2015
    Posts:
    66
    Im pretty much sure that it should work, tell me more about this enemy code. Is this script on every player in the game or is it networked scene object? If it's not on the client side then u need to assign authority or try:

    Code (CSharp):
    1. [Command]
    2. public void CmdChangeAnimationEnemy(GameObject enemyObject, int animationStep)
    3. {
    4.    enemyObject.GetComponent<AnimationScript>().animationStep = animationStep;
    5. }
    Anyway I need more info to help.
     
  5. msd1357

    msd1357

    Joined:
    Jul 7, 2014
    Posts:
    8
    Hello again. In my game I have two main objects. EnemySpawner and enemy.
    This is the source code which attached to EnemySpawner:
    Code (CSharp):
    1. public class EnemySpawner : NetworkBehaviour {
    2.  
    3.     public GameObject EnemyPrefab;
    4.  
    5.     void Update ()
    6.     {
    7.         if (!isLocalPlayer)
    8.             return;
    9.  
    10.         if (Input.GetKeyDown(KeyCode.Space))        
    11.             CmdMakeEnemy ();
    12.  
    13.     }
    14.     [Command]
    15.     public void CmdMakeEnemy()
    16.     {
    17.         Vector3 position = new Vector3 (238.25f,0.04193115f,183.5433f);
    18.         Quaternion rotation = new Quaternion (0.05533944f,0.9961376f,-0.0403282f,0.05496508f);
    19.         GameObject en = GameObject.FindGameObjectWithTag ("enemy");
    20.         if (en != null)
    21.             Destroy (en);
    22.  
    23.         var enemy = (GameObject)Instantiate (EnemyPrefab, position, rotation);
    24.         enemy.tag = "enemy";
    25.         NetworkServer.Spawn (enemy);
    26.  
    27.     }
    28. }
    29.  
    And this is attached to enemy object(I rewrite it by your help):
    Code (CSharp):
    1. public class Enemy : NetworkBehaviour
    2. {
    3.     [SyncVar (hook="OnAnimationStepChanged")]
    4.     public int animationStep = 1;
    5.  
    6.     [Command] public void CmdSetAnimationStep(int newAnimationStep)
    7.     {
    8.         animationStep = newAnimationStep;
    9.     }
    10.     public void OnAnimationStepChanged(int animStep)
    11.     {
    12.         this.animationStep = animStep;
    13.         //**Player animation here**
    14.         if (animationStep == 1)
    15.         {
    16.             gameObject.GetComponent<Animation> ().wrapMode = WrapMode.Loop;
    17.             gameObject.GetComponent<Animation> ().Play ("Fire_standing");
    18.         }
    19.  
    20.         if (animationStep == 2)
    21.         {
    22.             gameObject.GetComponent<Animation> ().wrapMode = WrapMode.Once;
    23.             gameObject.GetComponent<Animation> ().Play ("Die_on_back");
    24.         }
    25.     }
    26.  
    27.     public override void OnStartClient()
    28.     {
    29.         OnAnimationStepChanged(1);
    30.     }
    31.  
    32.     void Update () {
    33.  
    34.         //if( ! isLocalPlayer) return;
    35.         if (Input.GetMouseButtonDown (0))
    36.         {
    37.             CmdSetAnimationStep(2);
    38.         }                
    39.     }
    40. }
    This is EnemySpawner config:
    EnemySpawner.png

    This is enemy config:
    Enemy.png

    and This is the NetworkManager object config:
    NetworkManager.png
    (in above picture soldier prefab in my enemy)

    Hope that info enough to help me. thank you for your help.
    when I click enemy in client version nothing happened(Die animation doesn't play) but in server version every thing fine.
     
  6. Chom1czek

    Chom1czek

    Joined:
    Sep 19, 2015
    Posts:
    66
    Ok, Enemy is seperate being so you are not in authority to call a Command from it's script however you can make an Command from your script where you have an authority so you need to add component to your player prefab, or add this method to it:


    If you want to click and change the animationStep:
    Code (CSharp):
    1. void Update()
    2. {
    3. if(!isLocalPlayer) return;
    4.  
    5.    if(Input.GetKeyDown(KeyCode.Mouse0)
    6.    {
    7.      Ray ray = Camera.main.ScreenToRay(Input.mousePosition);
    8.      RaycastHit hit;
    9.      if(Physics.Raycast(ray, out hit, 100f))
    10.      {
    11.         CmdChangeAnimationStep(hit.collider.gameObject, newAnimationStep);
    12.      }
    13.    }
    14. }
    15.  
    16. [Command]
    17. public void CmdChangeAnimationStep(GameObject enemyObject, int newAnimationStep)
    18. {
    19.    enemyObject.GetComponent<EnemyScript>().animationStep = newAnimationStep;
    20. }
    21.  
    Remember this code must be there where you have an authority (basically where you have localPlayer in NetworkIdentity enabled)

    Please, it must work :D
     
  7. msd1357

    msd1357

    Joined:
    Jul 7, 2014
    Posts:
    8
    Hello, I changed scrips as below.
    EnemySpawner script:
    Code (CSharp):
    1. public class EnemySpawner : NetworkBehaviour {
    2.  
    3.     public GameObject EnemyPrefab;
    4.  
    5.     void Update ()
    6.     {
    7.         if (!isLocalPlayer)
    8.             return;
    9.  
    10.         if (Input.GetKeyDown(KeyCode.Space))          
    11.             CmdMakeEnemy ();
    12.  
    13.         if(Input.GetKeyDown(KeyCode.Mouse0))
    14.         {
    15.             Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    16.             RaycastHit hit;
    17.             if(Physics.Raycast(ray, out hit, 1000f))
    18.             {
    19.                 CmdChangeAnimationStep(hit.collider.gameObject, 2);
    20.             }
    21.         }
    22.     }
    23.     [Command]
    24.     public void CmdChangeAnimationStep(GameObject enemyObject, int newAnimationStep)
    25.     {
    26.         enemyObject.GetComponent<Enemy>().animationStep = newAnimationStep;
    27.     }
    28.  
    29.     [Command]
    30.     public void CmdMakeEnemy()
    31.     {
    32.         Vector3 position = new Vector3 (238.25f,0.04193115f,183.5433f);
    33.         Quaternion rotation = new Quaternion (0.05533944f,0.9961376f,-0.0403282f,0.05496508f);
    34.         GameObject en = GameObject.FindGameObjectWithTag ("enemy");
    35.         if (en != null)
    36.             Destroy (en);
    37.  
    38.         var enemy = (GameObject)Instantiate (EnemyPrefab, position, rotation);
    39.         enemy.tag = "enemy";
    40.         NetworkServer.Spawn (enemy);
    41.  
    42.     }
    43. }
    Enemy Script:
    Code (CSharp):
    1. public class Enemy : NetworkBehaviour
    2. {
    3.     public int animationStep = 1;
    4.     void Update ()
    5.     {
    6.         if(Input.GetKeyDown(KeyCode.Mouse0))
    7.         {
    8.             Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    9.             RaycastHit hit;
    10.             if(Physics.Raycast(ray, out hit, 1000f))
    11.             {
    12.                 animationStep = 2;
    13.             }
    14.         }
    15.  
    16.         if (animationStep == 1)
    17.         {
    18.             gameObject.GetComponent<Animation> ().wrapMode = WrapMode.Loop;
    19.             gameObject.GetComponent<Animation> ().Play ("Fire_standing");
    20.             animationStep = 0;
    21.         }
    22.  
    23.         if (animationStep == 2)
    24.         {
    25.             gameObject.GetComponent<Animation> ().wrapMode = WrapMode.Once;
    26.             gameObject.GetComponent<Animation> ().Play ("Die_on_back");
    27.             animationStep = 0;
    28.         }
    29.     }
    30. }
    EnemySpawner Config:
    EnemySpawnerConfig.png

    Enemy Config:
    EnemyConfig.png

    Now when I click on enemy in client version of game, the death animation played on both client and server. but when I click on enemy in server version the animation does not play in client version.:(
    What I do wrong?