Search Unity

[uNet] how to spawn the object

Discussion in 'Scripting' started by SovietGeneral, Aug 23, 2016.

  1. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    I do so (method not have attributes)

    Code (CSharp):
    1. GameObject AnotherProjectile = Instantiate(ProjectileTypePrefab, FirePosition.transform.position, FirePosition.transform.rotation) as GameObject;
    2.         ClientScene.RegisterPrefab(AnotherProjectile);
    3.         Bullet proj = AnotherProjectile.GetComponent<Bullet>();
    4.         proj.Damage = Damage;
    5.      
    6.         Vector3 target = new Vector3(FirePosition.transform.position.x * Random.Range(-FireDispersionRadius, FireDispersionRadius), FirePosition.transform.position.y * Random.Range(-FireDispersionRadius, FireDispersionRadius), FirePosition.transform.position.z);
    7.         target.z *= MaxDistance;
    8.      
    9.         NetworkServer.Spawn(AnotherProjectile);
    10.         AnotherProjectile.GetComponent<Rigidbody>().AddForce(Vector3.RotateTowards(transform.forward, target, Time.deltaTime, 0f) * FireForcePower);
    But nothing happens...
    Please, help. Thanks.
     
    Last edited: Aug 23, 2016
  2. Vedrit

    Vedrit

    Joined:
    Feb 8, 2013
    Posts:
    514
    First, please use the code tags.

    Second, are you getting any errors or messages in the console? Where is this script? NetworkServer.Spawn can only be called from the server. Clients usually pass the needed information to the server and the server spawns the object with the necessary information at the desired location.
     
  3. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
  4. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    It hangs on the script of the weapon, the weapon in turn a child object of the player to prefab.
    Error: NetworkServer is not active
     
    Last edited: Aug 23, 2016
  5. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    How fix this error?
     
  6. Pagi

    Pagi

    Joined:
    Dec 18, 2015
    Posts:
    132
    From what I know, you must register every networked prefab on start of the game and on every client - every client must know what object to spawn when you use NetworkServer.Spawn(). So you register for example all the gun and bullet prefabs in Start(), then on server you Instantiate it, set its SyncVars and then Spawn it.
     
  7. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    then enter the problem because I have implemented a spawn shooting through the bullets. can register them in Start() of the bullet?
     
  8. Pagi

    Pagi

    Joined:
    Dec 18, 2015
    Posts:
    132
    Yes you can, but make sure that everything is registered in the same order on all clients. There is a list of registered prefabs, and if server tells clients to instantiate for example 5. gameobject, it must be the same gameobject everywhere.
     
  9. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    5 - it is name?

    it seems there is no example not to understand...
     
    Last edited: Aug 24, 2016
  10. Pagi

    Pagi

    Joined:
    Dec 18, 2015
    Posts:
    132
    No sorry it was just an example. I'll try to show it better. Let's say you have various networked objects:
    1. Gun
    2. Bullet
    3. AmmoPack
    You register them all in Start(). IF Start() of each of your object runs in the same order everytime it is ok, but on some client it can register in this order:
    1. Gun
    2. AmmoPack
    3. Bullet
    Now on server you Instantiate a bullet and call Spawn(bullet). Server tells all clients to instantiate their bullet and expects it to be registered prefab number 2. But on some clients the Start in AmmoPack ran earlier than in Bullet for some reason, and now what happens is that the client instantiates AmmoPack, because for it it's registered prefab number 2.

    That's why you should register your prefabs in the same order every time preferably in one method, so they register the same way everytime.

    Also you register the PREFABS and not the actual instantiated objects, so you can't even ClientScene.RegisterPrefab() in Start() of bullet, because Start() of bullet runs AFTER you instantiate it. You need to register it before any bullet instantiates.
     
  11. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    Result the method that is called when a player shoots to spawn a bullet.
    (method have not attributes)

    Code (CSharp):
    1.     void CmdSpawnProjectile()
    2.     {
    3.         GameObject AnotherProjectile = ProjectileTypePrefab;
    4.         Bullet proj = AnotherProjectile.GetComponent<Bullet>();
    5.         proj.Damage = Damage;
    6.         ClientScene.RegisterPrefab(AnotherProjectile);
    7.         NetworkServer.Spawn(AnotherProjectile);
    8.         AnotherProjectile = Instantiate(AnotherProjectile, FirePosition.transform.position, FirePosition.transform.rotation) as GameObject;
    9.  
    10.         Vector3 target = new Vector3(FirePosition.transform.position.x * Random.Range(-FireDispersionRadius, FireDispersionRadius), FirePosition.transform.position.y * Random.Range(-FireDispersionRadius, FireDispersionRadius), FirePosition.transform.position.z);
    11.         target.z *= MaxDistance;
    12.      
    13.         AnotherProjectile.GetComponent<Rigidbody>().AddForce(Vector3.RotateTowards(transform.forward, target, Time.deltaTime, 0f) * FireForcePower);
    14.     }
     
  12. Pagi

    Pagi

    Joined:
    Dec 18, 2015
    Posts:
    132
    My explaining skills may be seriously impaired. Now you registered it before, that is nice, but what i meant is that the prefab needs to be registered once on start of the game, then you can Instantiate and Spawn it how many times you want.
    Example from docs changed to gun:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Networking;
    3.  
    4. public class Gun : NetworkBehaviour {
    5.  
    6.     public GameObject bulletPrefab;
    7.  
    8.     public void OnStartClient()
    9.     {
    10.         ClientScene.RegisterPrefab(bulletPrefab);
    11.     }
    12.  
    13.     [Command]
    14.     public CmdSpawnBullet(Vector3 pos, Quaternion rot)
    15.     {
    16.         var plant = (GameObject)Instantiate(bulletPrefab, pos, rot);
    17.         NetworkServer.Spawn(plant);
    18.     }
    19. }
     
  13. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    And we have:
    SpawnObject for Test Bullet Prefab(Clone) (UnityEngine.GameObject), NetworkServer is not active. Cannot spawn objects without an active server.
    UnityEngine.Networking.NetworkServer:Spawn(GameObject)
    FireArms:CmdSpawnProjectile() (at Assets/Resources/Scripts/Shooting System/Weapons/FireArms.cs:99)
    FireArms:Fire() (at Assets/Resources/Scripts/Shooting System/Weapons/FireArms.cs:55)
    UnityStandardAssets.Characters.FirstPerson.FirstPersonController:Update() (at Assets/Resources/Scripts/Controller/FirstPersonController.cs:103)
     
  14. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    You have to actually start a networked game in order to spawn things over the network......
     
  15. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    I network and do.
     
  16. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    I don't know what that means.

    Unity isn't lying to you. It's telling you that your server isn't active.
     
  17. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    Okay, but then what do I do?
     
  18. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Where's your code that starts a networked game?
     
  19. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    That is? I have an object with NetworkManager and it is NetworkManagerHUD and through it create and join. Or you another meant?
     
  20. Pagi

    Pagi

    Joined:
    Dec 18, 2015
    Posts:
    132
    is the Spawn in that CmdSomething method? If it is, then weird, it should execute on server.
     
  21. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    You can only use NetworkServer.Spawn if you're the host. Other players should send a Command to the host to spawn stuff. I noticed your method isn't decorated with the Command attribute - it has to be.
     
  22. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    First method:
    Code (CSharp):
    1.     public override void Fire()
    2.     {
    3.         Debug.Log(CurrentAmmoInto + "/" + CurrentMagazines);
    4.         if (Input.GetButton("Fire") && CurrentAmmoInto > 0 && ShootTimer <= 0 && ReloadTimer <= 0)
    5.         {
    6.             FireParticle();
    7.  
    8.             var AnotherProjectile = ProjectileTypePrefab;
    9.             Bullet proj = AnotherProjectile.GetComponent<Bullet>();
    10.             proj.Damage = Damage;
    11.             CmdSpawn(AnotherProjectile, FirePosition.transform.position, FirePosition.transform.rotation);
    12.  
    13.             Vector3 target = new Vector3(FirePosition.transform.position.x * Random.Range(-FireDispersionRadius, FireDispersionRadius), FirePosition.transform.position.y * Random.Range(-FireDispersionRadius, FireDispersionRadius), FirePosition.transform.position.z);
    14.             target.z *= MaxDistance;
    15.  
    16.             AnotherProjectile.GetComponent<Rigidbody>().AddForce(Vector3.RotateTowards(transform.forward, target, Time.deltaTime, 0f) * FireForcePower);
    17.  
    18.             Debug.Log("Shot");
    19.             ShootTimer = FireShootingSpeed;
    20.             CurrentAmmoInto--;
    21.             m_AudioSource.PlayOneShot(ShootClip);
    22.             /*Vector3 targetDir = transform.position * 100 - transform.position;
    23.             float step = 100 * Time.deltaTime;
    24.             Vector3 newDir = Vector3.RotateTowards(transform.forward, targetDir, step, 0.0F);
    25.             Debug.DrawRay(transform.position, newDir, Color.red);
    26.             transform.rotation = Quaternion.LookRotation(newDir);*/
    27.         }
    28.     }
    Second Method:
    Code (CSharp):
    1.     [Command] void CmdSpawn(GameObject Object, Vector3 position, Quaternion rotation)
    2.     {
    3.         Object = Instantiate(Object, position, rotation) as GameObject;
    4.         NetworkServer.Spawn(Object);
    5.     }
    The above methods do not work, and more specifically - spawn.
     
  23. Pagi

    Pagi

    Joined:
    Dec 18, 2015
    Posts:
    132
    Nothing there is striking me as wrong, the only thing that comes to mind is if you have set Local Player Authority in your NetworkIdentity in inspector.
     
  24. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    AnotherProjectile isn't the networked projectile so manipulating its Rigidbody won't do what you think it will.

    EDIT:

    I bet your input code is running for every networked prefab. You should check isLocalPlayer so it only runs for the objects the player controls.
     
  25. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    And third:
    Code (CSharp):
    1.     public override void OnStartClient()
    2.     {
    3.         ClientScene.RegisterPrefab(ProjectileTypePrefab);
    4.     }
    No, there is no Local Authority

    I would now at least the object to spawn.
    the bullet has not LocalPlayerAuthority.
    .
     
    Last edited: Aug 24, 2016
  26. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    checked LocalPlayerAuthority on the projectile so that that's not exactly working. and even locally does not appear.

    EDIT:
    checked the script input off on other prefab locally for everyone but himself.
     
    Last edited: Aug 24, 2016
  27. Pagi

    Pagi

    Joined:
    Dec 18, 2015
    Posts:
    132
    Set LocalPlayerAuthority for the gameObject that has the script spawning bullets. Without LocalPlayerAuthority scripts can't(from what I know) use Commands.
     
  28. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    upload_2016-8-24_18-6-34.png upload_2016-8-24_18-6-56.png
    I put down, but something does not work.
     
  29. Pagi

    Pagi

    Joined:
    Dec 18, 2015
    Posts:
    132
    I think you can only have NetworkIdentity on root gameObject, and Commands too, so remove the second NetowrkIdentity and find a way to have the Command in root gameObject.
     
    SovietGeneral likes this.
  30. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    Therefore, for the sake of the test script hung the weapons on the main object. Worked. Probably have to do object Spawner with the script spawn and giving the link arms, to invoke the method.

    so, now the error is more fun. He says, well, what object to spawn there. And so, the actual question is: how to spawn an object from a child object?
     
  31. Pagi

    Pagi

    Joined:
    Dec 18, 2015
    Posts:
    132
    Soo you can have method in the root object like:
    Code (CSharp):
    1. [Command]
    2. public void CmdSpawnPrefab(GameObject prefab){
    3. GameObject go = Instantiate(prefab) as GameObject;
    4. NetworkServer.Spawn(go);
    5. }
    And call it from the child weapon with the right bullet as argument.
     
  32. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    I use this method:
    Code (CSharp):
    1.     [Command] public virtual void CmdSpawn(GameObject Object, Vector3 position, Quaternion rotation)
    2.     {
    3.         Object = Instantiate(Object, position, rotation) as GameObject;
    4.         NetworkServer.Spawn(Object);
    5.     }
    But the console says when I call it, Nullreferenceexception. In this case, all of what is going on call it is not happening.
     
  33. Pagi

    Pagi

    Joined:
    Dec 18, 2015
    Posts:
    132
    You can check when the object becomes null.
     
    SovietGeneral likes this.
  34. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    Thank you, I did itю

    EDIT:
    And Yes, I also want to ask to apply physics to Rigidbody also need to do it via the [Command]?

    started test with two clients. The client and host, creates all fine. And here's one that a client can not do anything.
     
  35. Pagi

    Pagi

    Joined:
    Dec 18, 2015
    Posts:
    132
    if one client works and other doesn't, you will have to find some mistake somewhere, and the yes, speed to rigidbody can be also applied in the command.
     
  36. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    For the answer to the question about physics thank you. And what about this problem, I think I missed something.
     
  37. Pagi

    Pagi

    Joined:
    Dec 18, 2015
    Posts:
    132
    Frankly I have no idea what might do that, so you will have to check which methods are running, which aren't, generally just find the problem.
     
  38. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    Randomly do not register prefabs in networkmanager, where SpawnableNetworkPrefabs?
     
  39. Pagi

    Pagi

    Joined:
    Dec 18, 2015
    Posts:
    132
    If you mean that the prefab sometimes doesn't register, you can either figure out why does it happen, something must make the code not run, like the class that registers it isn't active, isn't in the scene etc, or you can just put the prefab in RegisteredSpawnablePrefabs in NetworkManager in the inspector, and then you don't have to use NetworkServer.RegisterPrefab()
     
  40. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    I think I found it. The clients somehow do not register prefabs.
     
  41. SovietGeneral

    SovietGeneral

    Joined:
    Jul 31, 2016
    Posts:
    41
    Review console on the server when the client calls command:
    ArgumentException: The Object you want to instantiate is null.
    UnityEngine.Object.CheckNullArgument (System.Object arg, System.String message) (at C:/buildslave/unity/build/Runtime/Export/UnityEngineObject.cs:196)
    UnityEngine.Object.Instantiate (UnityEngine.Object original, Vector3 position, Quaternion rotation) (at C:/buildslave/unity/build/Runtime/Export/UnityEngineObject.cs:143)
    NetworkController.CmdSpawn (UnityEngine.GameObject Object, Vector3 position, Quaternion rotation) (at Assets/Resources/Scripts/Network/NetworkController.cs:16)
    NetworkController.InvokeCmdCmdSpawn (UnityEngine.Networking.NetworkBehaviour obj, UnityEngine.Networking.NetworkReader reader)
    UnityEngine.Networking.NetworkIdentity.HandleCommand (Int32 cmdHash, UnityEngine.Networking.NetworkReader reader) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkIdentity.cs:620)
    UnityEngine.Networking.NetworkServer.OnCommandMessage (UnityEngine.Networking.NetworkMessage netMsg) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkServer.cs:1297)
    UnityEngine.Networking.NetworkConnection.HandleReader (UnityEngine.Networking.NetworkReader reader, Int32 receivedSize, Int32 channelId) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkConnection.cs:453)
    UnityEngine.Networking.NetworkConnection.HandleBytes (System.Byte[] buffer, Int32 receivedSize, Int32 channelId) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkConnection.cs:409)
    UnityEngine.Networking.NetworkConnection.TransportRecieve (System.Byte[] bytes, Int32 numBytes, Int32 channelId) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkConnection.cs:561)
    UnityEngine.Networking.NetworkServer.OnData (UnityEngine.Networking.NetworkConnection conn, Int32 receivedSize, Int32 channelId) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkServer.cs:753)
    UnityEngine.Networking.NetworkServer+ServerSimpleWrapper.OnData (UnityEngine.Networking.NetworkConnection conn, Int32 receivedSize, Int32 channelId) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkServer.cs:1845)
    UnityEngine.Networking.NetworkServerSimple.HandleData (Int32 connectionId, Int32 channelId, Int32 receivedSize, Byte error) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkServerSimple.cs:382)
    UnityEngine.Networking.NetworkServerSimple.Update () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkServerSimple.cs:248)
    UnityEngine.Networking.NetworkServer.InternalUpdate () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkServer.cs:705)
    UnityEngine.Networking.NetworkServer.Update () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkServer.cs:655)
    UnityEngine.Networking.NetworkIdentity.UNetStaticUpdate () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkIdentity.cs:1060)

    EDIT:
    Fixed by this method:
    Code (CSharp):
    1.        [HideInInspector] public GameObject LastSpawnedGameObject;
    2.  [Command] public virtual void CmdSpawnAtResources(string ObjectResourcesPath, Vector3 position, Quaternion rotation)
    3.     {
    4.         GameObject Object = Instantiate(Resources.Load(ObjectResourcesPath), position, rotation) as GameObject;
    5.         NetworkServer.Spawn(Object);
    6.         LastSpawnedGameObject = Object;
    7.         Debug.Log("Object spawned[" + Object.name + "]");
    8.     }
     
    Last edited: Aug 25, 2016