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

Setting the player's spawn scene

Discussion in 'Netcode for GameObjects' started by brainwipe, Dec 12, 2022.

  1. brainwipe

    brainwipe

    Joined:
    Aug 21, 2017
    Posts:
    78
    My project has multiple additive scenes that is controlled by a bootstrap scene that contains game state management and the Network Manager. The player currently Spawns in that scene. Unlike other objects, for whom I can set the parent transform, the player isn't controlled by me and ignores the active scene.

    What's the correct way to set the player's spawn scene?
     
  2. RikuTheFuffs-U

    RikuTheFuffs-U

    Unity Technologies

    Joined:
    Feb 20, 2020
    Posts:
    440
    Hi @brainwipe , I'm not sure I understood your setup.

    What are you using to spawn the player?
     
    brainwipe likes this.
  3. brainwipe

    brainwipe

    Joined:
    Aug 21, 2017
    Posts:
    78
    I'm not spawning the player. The Network Manager is. All I have to call is:

    Code (CSharp):
    1. NetworkManager.Singleton.StartHost();
    or

    Code (CSharp):
    1. NetworkManager.Singleton.StartClient();
    And as long as the Network Manager has a reference to the Player Prefab, it will Spawn that player.

    I've tried:

    Code (CSharp):
    1. protected override void OnNetworkSpawn()
    2. {
    3.       // Doesn't work
    4.       _ = NetworkObject.TrySetParent(transform_in_the_other_scene);
    5. }
    But that fails for the host. Even though the transform in the other scene has a network object I use it for other things that I spawn, rather than is spawned by the Network Manager.

    I'm hoping to get the official/best answer as I make YouTube videos and mentor a few so would like to give them the "right" answer. Or at least the best default place to start!

    Many thanks!
     
    Last edited: Dec 13, 2022
  4. RikuTheFuffs-U

    RikuTheFuffs-U

    Unity Technologies

    Joined:
    Feb 20, 2020
    Posts:
    440
    Thanks for explaining! Does this also fail for client-only and server-only instances?

    I asked internally if the fact that objects from different scenes can't be parented to each other is a missing feature or a bug, I'll let you know as soon as I have an answer.
     
    brainwipe likes this.
  5. NoelStephens_Unity

    NoelStephens_Unity

    Unity Technologies

    Joined:
    Feb 12, 2022
    Posts:
    252
    Hi brainwipe! :)
    Could you give this a try?
    Code (CSharp):
    1.     public class MyPlayerObject : NetworkBehaviour
    2.     {
    3.         public bool TrySetPlayerParent(GameObject parent)
    4.         {
    5.             if(gameObject.scene != parent.scene)
    6.             {
    7.                 UnityEngine.SceneManagement.SceneManager.MoveGameObjectToScene(gameObject, parent.scene);
    8.             }
    9.  
    10.             return NetworkObject.TrySetParent(parent);
    11.         }
    12.     }
    With GameObjects and parenting, I believe both should be within the same scene. If they are not, then you need to first migrate one into the other's scene and then parent. The code above assumes you want the player object to be in the same scene as the NetworkObject you want to parent it under.
     
    Iwakura_Lain and brainwipe like this.
  6. brainwipe

    brainwipe

    Joined:
    Aug 21, 2017
    Posts:
    78
    I'm afraid I don't have client-only or server-only instances. I had a quick dabble to see if I could repro there and everything burst into flame (my code, not yours!).

    This worked, thank you!

    I'm afraid I'm seeing something else. If I instantiate and spawn a networked game object in OnServerStarted() and then TrySetParent, it works!

    For example, this code will spawn the fireSprite (a cute little 3D game object, not a 2D image) in the wrong scene and then move it to the right one (where Clomper.Instance is):

    Code (CSharp):
    1.  
    2. private void OnServerStarted()
    3. {
    4.    GameObject fireSprite = Instantiate(fireSpritePrefab, boiler.SpriteSpawn, Quaternion.identity);
    5.    var networkObject = fireSprite.GetComponent<NetworkObject>();
    6.    networkObject.Spawn();
    7.    _ = networkObject.TrySetParent(Clomper.Instance.transform);
    8. }
    9.  
    To my amateur eye, this is the correct behaviour, although I'd prefer if the active scene was used by the host by default.

    Do shout if you would like some more examples. I'm afraid I don't have a repro repo for you.
     
    RikuTheFuffs likes this.