Search Unity

GameObject spawns but it is not accessible by Variable

Discussion in 'Multiplayer' started by CatDoge, Mar 20, 2019.

  1. CatDoge

    CatDoge

    Joined:
    Aug 8, 2014
    Posts:
    13
    So I am making a Homing Missile for my multiplayer game

    My code below works if I play on the server but if I try to shoot on a client the Rocket that gets instantiated is not accessible. It gets spawned on both sites but the script that spawned it has no access:

    I have a normal Rocket Script where everything works, i copied it and added stuff to it to make it a homing rocket. Could be this the problem that there are double variables but it shouldnt be a problem i think because there are 2 different scripts?

    Code (CSharp):
    1. UnassignedReferenceException: The variable bulleto of autorocket has not been assigned.
    2. You probably need to assign the bulleto variable of the autorocket script in the inspector.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Networking;
    5. using UnityStandardAssets.CrossPlatformInput;
    6. using UnityEngine.EventSystems;
    7.  
    8.  
    9. public class autorocket : NetworkBehaviour
    10. {
    11.  
    12.  
    13.     public Transform Gun;
    14.  
    15.     public GameObject exp;
    16.  
    17.     public GameObject roc;
    18.     public Transform parentGameObject;
    19.  
    20.     public int Speed = 50;
    21.  
    22.     private Rigidbody rigidBody;
    23.     public GameObject closest;
    24.     public Vector3 lookVector;
    25.     public Quaternion lookRotation;
    26.     public Quaternion rot;
    27.     public Vector3 v3;
    28.     public GameObject bullet;
    29.     public GameObject bulleto;
    30.     public bool shootok = true;
    31.     public bool aim = false;
    32.     public GameObject[] gos;
    33.     public GameObject TARGETENEMY;
    34.  
    35.  
    36.     private void Start()
    37.     {
    38.         aim = false;
    39.     }
    40.  
    41.  
    42.  
    43.     private void Update()
    44.     {
    45.         if (isLocalPlayer)
    46.         {
    47.  
    48.             if (CrossPlatformInputManager.GetButton("autoshootbutton") && shootok == true)
    49.             {
    50.                 shootok = false;
    51.                 TARGETENEMY = FindClosestEnemy();
    52.  
    53.                 CmdFire();
    54.                 StartCoroutine(Test());
    55.  
    56.             }
    57.        
    58.        
    59.         }
    60.    
    61.         if (aim)
    62.         {
    63.             var v3 = bulleto.transform.forward * 2 * Speed;
    64.             v3.y = rigidBody.velocity.y;
    65.             rigidBody.velocity = v3;
    66.  
    67.             rot = Quaternion.LookRotation(TARGETENEMY.transform.position - parentGameObject.transform.position);
    68.             bulleto.transform.rotation = Quaternion.Slerp(bulleto.transform.rotation, rot, Time.deltaTime * 5f);
    69.  
    70.         }
    71.  
    72.        
    73.        
    74.  
    75.     }
    76.  
    77.     [Command]
    78.     void CmdFire()
    79.     {
    80.  
    81.     bulleto = GameObject.Instantiate(roc, parentGameObject.position, Gun.rotation) as GameObject;
    82.     //GameObject bullet = (GameObject)Instantiate(roc, parentGameObject.position, Gun.rotation);
    83.  
    84. // here might be a problem
    85.  
    86.         rigidBody = bulleto.GetComponent<Rigidbody>();
    87.         NetworkServer.Spawn(bulleto);
    88.    
    89.         //StartCoroutine(AimF());
    90.    
    91.     }
    92.  
    93.  
    94.  
    95.      public GameObject FindClosestEnemy() {
    96.  
    97.          gos = GameObject.FindGameObjectsWithTag("Player");
    98.  
    99.          float distance = Mathf.Infinity;
    100.          Vector3 position = transform.position;
    101.      
    102.          foreach (GameObject go in gos) {
    103.  
    104.                 if (go == this.gameObject) continue;
    105.  
    106.              Vector3 diff = go.transform.position - position;
    107.              float curDistance = diff.sqrMagnitude;
    108.              if (curDistance < distance) {
    109.                  closest = go;
    110.                  distance = curDistance;
    111.                
    112.            
    113.             }
    114.          }
    115.          return closest;
    116.  
    117.         }
    118.  
    119.     private IEnumerator Test()
    120.     {
    121.         aim = true;
    122.         float time = 0.5f;
    123.         yield return new WaitForSeconds(time);
    124.         aim = false;
    125.    
    126.  
    127.     }
    128.  
    129.     private void OnTriggerEnter(Collider collision)
    130.     {
    131.         if (collision.gameObject.tag == "ROCKET")
    132.         {
    133.             shootok = true;
    134.         }
    135.     }
    136.  
    137.  
    138.  
    139. }
     
    Last edited: Mar 20, 2019
    m1nas likes this.
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    The client's copy of the bulleto reference is not being set to the reference of the spawned object. You are setting that reference inside the CmdFire() Command, and none of the code within a Command is ever run on any client. You'll have to get that reference set on the client through some other means (you could try a ClientRpc, having the bulleto object set this reference itself during its own Start method, or some other option).
     
  3. CatDoge

    CatDoge

    Joined:
    Aug 8, 2014
    Posts:
    13
    Do you have any idea how I can achieve this?

    I am struggling for hours now, when I try to instantiate it before the CmdFire(); it doesnt work either.

    How can I spawn the object and still interact with it without making a new script for the whole rocket itself because I think if I try to make a script finding the closest enemy it will be hard to seperate the parent gameobject from all players.

    One hint would be nice to a documentation or so
     
  4. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    When you call CmdFire from the client it takes a while for the object to then appear on the client. This is because it will take several update loops before the server receives and runs the Command, and several more until the client then receives the packet telling it to spawn the object. So you have to build into your script that after running CmdFire it will not immediately have that reference.

    You can then in a Start method of the object being spawned have it find the object with the autorocket script and set bulleto to itself, if this is the client which fired it.
     
    CatDoge likes this.
  5. CatDoge

    CatDoge

    Joined:
    Aug 8, 2014
    Posts:
    13

    I tried it like that -> New Script for the Rocket

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Mirror;
    5.  
    6. public class rocketass : NetworkBehaviour
    7. {
    8.  
    9.  
    10.     public NetworkIdentity playerID;
    11.     public GameObject owner;
    12.     public autorocket ownerauto;
    13.  
    14.     void Start()
    15.     {
    16.         owner = NetworkServer.FindLocalObject(playerID.netId);
    17.         Debug.Log(owner);
    18.         ownerauto = owner.GetComponent<autorocket>();
    19.         ownerauto.bullet = this.gameObject;
    20.  
    21.     }
    22.  
    23.     void Update()
    24.     {
    25.    
    26.     }
    27.  
    28. }
    29.  
    Code (CSharp):
    1. [Command]
    2.     void CmdFire()
    3.     {
    4.          bullet = GameObject.Instantiate(roc, parentGameObject.position, Gun.rotation) as GameObject;
    5.          rigidBody = bullet.GetComponent<Rigidbody>();
    6.          bulletrocket = bullet.GetComponent<rocketass>();
    7.          bulletrocket.owner = this.gameObject;
    8.          bulletrocket.playerID = m_Identity;
    9.          NetworkServer.Spawn(bullet);
    10.    
    11.         Debug.Log(bulletrocket.owner);
    12.         launched = true;
    13.     }
    I dont get it, the Server works fine but the Client makes problems :/

    Do I need to use an ClientRPC somehow?


    Tried this one too with an ClientRpc but thats something I dont understand to be honest:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Mirror;
    5.  
    6. public class rocketass : NetworkBehaviour
    7. {
    8.  
    9.  
    10.     public NetworkIdentity playerID;
    11.     public GameObject owner;
    12.     public autorocket ownerauto;
    13.     public int owner2;
    14.     // Start is called before the first frame update
    15.     void Start()
    16.     {
    17.  
    18.         if (isServer)
    19.              RpcFire();
    20.          else
    21.              CmdFire();
    22.     }
    23.  
    24.     // Update is called once per frame
    25.     void Update()
    26.     {
    27.      
    28.     }
    29.  
    30.     [ClientRpc]
    31.     void RpcFire()
    32.     {
    33.         CmdFire();
    34.  
    35.      
    36.     }
    37.  
    38.     [Command]
    39.     void CmdFire()
    40.     {
    41.         owner = NetworkServer.FindLocalObject(playerID.netId);
    42.         Debug.Log(owner);
    43.         ownerauto = owner.GetComponent<autorocket>();
    44.         ownerauto.bullet = this.gameObject;
    45.     }
    46.  
    47. }
    48.  
    49.  

    I actually wanted to write a script for the rocket itself that chases the enemy but then I came across the problem that I cant exclude my player who spawns the rocket from all players :/

    What I also dont understand why does this script works flawlessly on both ends?


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Mirror;
    5. using UnityStandardAssets.CrossPlatformInput;
    6. using UnityEngine.EventSystems;
    7.  
    8.  
    9. public class rocket : NetworkBehaviour
    10. {
    11.     public Transform Gun;
    12.     public Transform Gun2;
    13.  
    14.     public Transform Target;
    15.  
    16.     public float secs;
    17.     public GameObject exp;
    18.     public GameObject expo;
    19.     public List<GameObject> explosions = new List<GameObject>();
    20.     public float horiz;
    21.     public float vert;
    22.  
    23.     public GameObject roc;
    24.     public Transform parentGameObject;
    25.     int i = 0;
    26.     float pss;
    27.     public int Speed = 50;
    28.     public Vector3 tempvel;
    29.  
    30.     public ParticleSystem ps;
    31.     private Rigidbody rigidBody;
    32.     private Rigidbody rigidBody2;
    33.  
    34.     public static bool launched;
    35.  
    36.     private rocketcol rocketcoll;
    37.     public Vector3 vec;
    38.     public Vector3 vec2;
    39.     public GameObject bullet;
    40.     public bool shootok = true;
    41.  
    42.     public bool aim;
    43.  
    44.     public List<Transform> enemlst = new List<Transform>();
    45.  
    46.     private void Start()
    47.     {
    48.      
    49.         shootok = true;
    50.  
    51.         aim = false;
    52.         rigidBody2 = GetComponent<Rigidbody>();
    53.         launched = false;
    54.     }
    55.  
    56.  
    57.     private void Update()
    58.  
    59.     {
    60.  
    61.         if (isLocalPlayer)
    62.         {
    63.             Gun.localEulerAngles = new Vector3(-15 * vert, 35 * horiz, 0);
    64.  
    65.  
    66.             tempvel = rigidBody2.velocity;
    67.             if (CrossPlatformInputManager.GetButton("shootbutton") && shootok == true)
    68.             {
    69.  
    70.                 CmdFire();
    71.                 StartCoroutine(Test());
    72.              
    73.             }
    74.          
    75.         }
    76.  
    77.  
    78.  
    79.         if (launched)
    80.         {
    81.             var v3 = bullet.transform.forward * 2 * Speed;
    82.             v3.y = rigidBody.velocity.y;
    83.             rigidBody.velocity = v3;
    84.             launched = false;
    85.  
    86.         }
    87.  
    88.  
    89.  
    90.  
    91.     }
    92.  
    93.  
    94.  
    95.     private IEnumerator Test()
    96.     {
    97.         shootok = false;
    98.         float time = 0.5f;
    99.         yield return new WaitForSeconds(time);
    100.         shootok = true;
    101.      
    102.  
    103.     }
    104.  
    105.  
    106.     [Command]
    107.     void CmdFire()
    108.     {
    109.  
    110.      
    111.         bullet = GameObject.Instantiate(roc, parentGameObject.position, Gun.rotation) as GameObject;
    112.         rigidBody = bullet.GetComponent<Rigidbody>();
    113.        
    114.         NetworkServer.Spawn(bullet);
    115.  
    116.        
    117.         launched = true;
    118.      
    119.     }
    120.  
    121.  
    122.  
    123. }
     
    Last edited: Mar 23, 2019
  6. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    In CmdFire you are setting the owner property only on the server. It will be null on all clients. Understand that inside a Command, none of this code is ever run on the clients, and all variables that aren't passed as parameters to the Command are local variables to the server, none of them are values from the client.

    In rocketass' Start method you are calling NetworkServer.FindLocalObject even on the clients, but obviously anything under NetworkServer can't be run on clients. You're probably getting errors or warnings in the log when run on the clients.
     
  7. CatDoge

    CatDoge

    Joined:
    Aug 8, 2014
    Posts:
    13

    Well I solved the problem somehow, it spawns on both clients, and operates as it should but sometimes there are some rockets that have strange behaviour i need to look into that
    On the client it jitters a lot :/

    Script on the Rocketprefab that gets spawned:

    Code (CSharp):
    1. public class rocketass : NetworkBehaviour
    2. {
    3.  
    4.     public Rigidbody rb;
    5.     public uint playerID;
    6.     public GameObject owner;
    7.     public autorocket ownerauto;
    8.     public int owner2;
    9.     public Vector3 Position;
    10.     public Quaternion Rotation;
    11.     public Quaternion rot;
    12.     public GameObject TARGETENEMY;
    13.     public uint enemyID;
    14.     public int i;
    15.  
    16.     // Start is called before the first frame update
    17.     void Start()
    18.     {
    19.         rb = gameObject.GetComponent<Rigidbody>();
    20.         rb.detectCollisions = false;
    21.  
    22.     }
    23.  
    24.     // Update is called once per frame
    25.     void Update()
    26.     {
    27.         for(int i = 1; i < 15; i++){ // To reduce Network Traffic only 15 frames searching for an enemy
    28.         TARGETENEMY = NetworkServer.FindLocalObject(enemyID);
    29.         }
    30.      
    31.             rb.detectCollisions = true;
    32.      
    33.         owner = NetworkServer.FindLocalObject(playerID);
    34.      
    35.         if(owner != null)
    36.         {
    37.         ownerauto = owner.GetComponent<autorocket>();
    38.         ownerauto.bullet = gameObject;
    39.         }
    40.        
    41.         if(TARGETENEMY != null){
    42.         rot = Quaternion.LookRotation(TARGETENEMY.transform.position - transform.position);
    43.         transform.rotation = Quaternion.Slerp(transform.rotation, rot, Time.deltaTime * 5f);
    44.        
    45.         }
    46.      
    47.      
    48.     }

    Code (CSharp):
    1.  
    2.  
    3.  private void Update()
    4.     {
    5.         if (isLocalPlayer)
    6.         {
    7.          
    8.             if (CrossPlatformInputManager.GetButton("autoshootbutton") && shootok == true)
    9.             {
    10.                 TARGETENEMY = FindClosestEnemy();
    11.                 shootok=false;
    12.                 CmdFire(TARGETENEMY);
    13.                 StartCoroutine(Test());
    14.              
    15.             }
    16.          
    17.         }
    18.  
    19. if (isLocalPlayer)
    20.         {
    21.         Position = parentGameObject.position;
    22.         if (launched && bullet != null)
    23.         {
    24.  
    25.             rigidBody = bullet.GetComponent<Rigidbody>();
    26.             var v3 = bullet.transform.forward * 2.5f * Speed;
    27.             v3.y = rigidBody.velocity.y;
    28.            
    29.             rigidBody.velocity = v3;
    30.            
    31.             rot = Quaternion.LookRotation(TARGETENEMY.transform.position - parentGameObject.transform.position);
    32.             bullet.transform.rotation = Quaternion.Slerp(bullet.transform.rotation, rot, Time.deltaTime * 5f);
    33.             Position = bullet.transform.position;
    34.             MoveTo(bullet,Position, TARGETENEMY);
    35.         }
    36.         }
    37.      
    38.     }
    39.  
    40.  
    41.   [Command]
    42.     void CmdFire(GameObject target)
    43.     {
    44.  
    45.  
    46.         GameObject bullet = (GameObject) Instantiate(roc, parentGameObject.position, Gun.rotation);
    47.  
    48.         NetworkServer.Spawn(bullet);
    49.  
    50.         if(target != null)
    51.         {
    52.         RpcFire(bullet.GetComponent<NetworkIdentity>().netId, target.GetComponent<NetworkIdentity>().netId);
    53.         }else{
    54.         }
    55.     }
    56.  
    57.     [ClientRpc]
    58.     void RpcFire(uint id, uint enemyid)
    59.     {
    60.      
    61.         GameObject go = NetworkServer.FindLocalObject(id);
    62.      
    63.         bulletrocket = go.GetComponent<rocketass>();
    64.         bulletrocket.playerID = gameObject.GetComponent<NetworkIdentity>().netId;
    65.         bulletrocket.enemyID = enemyid;
    66.     }
    67.  
    68.     public void MoveTo(GameObject go, Vector3 newPosition, GameObject target)
    69.      {
    70.          if (isServer)
    71.              RpcMoveTo(go,newPosition, target);
    72.          else
    73.              CmdMoveTo(go,newPosition, target);
    74.      }
    75.  
    76.  
    77.      [Command]
    78.      public void CmdMoveTo(GameObject go, Vector3 newPosition, GameObject target)
    79.      {
    80.          RpcMoveTo(go,newPosition, target);
    81.      }
    82.      [ClientRpc]
    83.      void RpcMoveTo(GameObject go, Vector3 newPosition, GameObject target) {
    84.          
    85.             rigidBody2 = go.GetComponent<Rigidbody>();
    86.          
    87.          
    88.             var v3 = bullet.transform.forward * 2.5f * Speed;
    89.             v3.y = rigidBody2.velocity.y;
    90.          
    91.             rigidBody2.velocity = v3;
    92.            
    93.             rot = Quaternion.LookRotation(target.transform.position - parentGameObject.transform.position);
    94.             go.transform.rotation = Quaternion.Slerp(go.transform.rotation, rot, Time.deltaTime * 5f);
    95.            
    96.          
    97.      }
    As you may see I am updating the position via an RPC is there any other option for that because it seems to jitter on clients