尝试将对象添加到Unity中的活动场景,但是在父场景

时间:2018-03-17 19:26:42

标签: unity3d

我正在尝试构建一个简单的飞行游戏。我有两个场景 - 一个用于生成GameManager和SceneController实例的管理场景,以及一个载入玩家可以飞过一些红门的游戏场景。

一旦加载了游戏场景,我就会添加一些门。但是,在层次结构中,这些场景下的门不显示 - 它们出现在管理场景下。预制件确实出现在游戏场景中。我希望所有这些都能在游戏场景中出现。

两个问题:

  1. 我是否在不正确地加载游戏场景?是否还需要其他东西来使其完全活跃?
  2. 我不明白场景是如何运作的,如果是这样,我应该采取哪些不同的做法?
  3. SceneController代码:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    
    public class SceneController : MonoBehaviour {
    
        // This is a singleton
        private static SceneController _instance;
    
        public static SceneController Instance { get { return _instance; } }
    
        private void Awake()
        {
            if (_instance != null && _instance != this)
            {
                Destroy(this.gameObject);
            } else {
                _instance = this;
            }
        }
    
        // Scene names
        private string sceneNameGameScene = "GameScene";
    
        // Use this for initialization
        void Start () {
            SceneManager.sceneLoaded += OnSceneLoaded;
            StartCoroutine(LoadSceneAdditive(sceneNameGameScene, LoadSceneMode.Additive));
        }
    
        void OnSceneLoaded(Scene scene, LoadSceneMode mode) {
            if (scene.name == sceneNameGameScene) {
                SceneManager.SetActiveScene(scene);
                Debug.Log("OnSceneLoaded Active Scene : " + SceneManager.GetActiveScene().name);
                SetupGameScene();
            }
        }
    
        IEnumerator LoadSceneAdditive(string sceneName, LoadSceneMode loadSceneMode){
            AsyncOperation _async = new AsyncOperation();
            _async = SceneManager.LoadSceneAsync(sceneName, loadSceneMode);
    
            while (!_async.isDone) {
                yield return null;
            }
    
            Scene nextScene = SceneManager.GetSceneByName( name );
            if (nextScene.IsValid ()) {
                SceneManager.SetActiveScene (nextScene);
            }
        }
    
    
        private void SetupGameScene() {
    
            // Create a game map
            GameMap gameMap = new GameMap();
            gameMap.Setup(this.transform);
        }
    }
    

    GameMap代码:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    
    public class GameMap {
        private GameObject gatePrefab = GameObject.Instantiate(Resources.Load("GatePrefab")) as GameObject;
        private Transform transform;
    
        public GameMap() {}
    
        public void Setup (Transform parentTransform) {
            transform = parentTransform;
            Vector3 position;
            Quaternion rotation;
    
            position = new Vector3(0, 0, 0);
            rotation = Quaternion.identity;
            CreateGate(position, rotation, 10.0f, 2.0f, "Gate 1");
    
            position = new Vector3(0, 0, 20);
            rotation =  Quaternion.identity * Quaternion.Euler(0, 45, 0);
            CreateGate(position, rotation, 10.0f, 1.0f, "Gate 2");
    
            position = new Vector3(20, 0, 20);
            rotation =  Quaternion.identity * Quaternion.Euler(0, 90, 0);
            CreateGate(position, rotation, 8.0f, 1.0f, "Gate 3");
    
            CreateGround();
        }
    
        private void CreateGate(Vector3 position, Quaternion rotation, float lengthOfSide, float thickness, string name) {
            // Create the gates, and call the "Initialize" method to populate properties as Unity doesn't have constructors.
            GameObject clone = GameObject.Instantiate(gatePrefab, position, rotation, transform) as GameObject;
            clone.name = name;
            clone.GetComponent<Gate>().Initialize(lengthOfSide, thickness);
        }
    
        private void CreateGround() {
            Debug.Log("OnSceneLoaded Active Scene : " + SceneManager.GetActiveScene().name);
            GameObject ground = GameObject.CreatePrimitive(PrimitiveType.Plane);
            ground.name = "Ground";
            ground.transform.parent = transform;
            ground.transform.localPosition = new Vector3(0, -10, 0);
            ground.transform.localRotation = Quaternion.identity;
            ground.transform.localScale = new Vector3(50, 1, 50);
    
            ground.GetComponent<Renderer>().material.color = Color.grey;
        }
    }
    

    门码:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Gate : MonoBehaviour {
        float lengthOfSide;
        float thickness;
    
        public void Initialize (float lengthOfSide, float thickness) {
            this.lengthOfSide = lengthOfSide;
            this.thickness = thickness;
        }
    
        // Use this for initialization
        void Start () {
            SetupRigidBody();
            Setup3dEntities();
        }
    
        void SetupRigidBody() {
            Rigidbody rb = this.gameObject.AddComponent<Rigidbody>();
            rb.detectCollisions = true;
            rb.mass = 1000;
            rb.useGravity = false;
        }
    
        // Create the physical gate
        void Setup3dEntities() {
            Vector3 position;
            Vector3 scale;
            float lengthOfVeritcalSegment = lengthOfSide - (2 * thickness);
            float yPosHorizontalSegment = (lengthOfSide - thickness) / 2;
            float xPosVerticalSegment = lengthOfSide - thickness;
    
            // Bottom
            position = new Vector3(0, -yPosHorizontalSegment, 0);
            scale = new Vector3(lengthOfSide, thickness, thickness);
            CreatePrimitiveCube(position, scale);
    
            // Top
            position = new Vector3(0, yPosHorizontalSegment, 0);
            scale = new Vector3(lengthOfSide, thickness, thickness);
            CreatePrimitiveCube(position, scale);
    
            // Left
            position = new Vector3(xPosVerticalSegment/2, 0, 0);
            scale = new Vector3(thickness, lengthOfVeritcalSegment, thickness);
            CreatePrimitiveCube(position, scale);
    
            // Right
            position = new Vector3(-xPosVerticalSegment/2, 0, 0);
            scale = new Vector3(thickness, lengthOfVeritcalSegment, thickness);
            CreatePrimitiveCube(position, scale);
        }
    
        void CreatePrimitiveCube(Vector3 position, Vector3 scale) {
            // Create a primitive cube. Note that we want to set the position and rotation to match the parent!
            GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
            cube.transform.parent = gameObject.transform;
            cube.transform.localPosition = position;
            cube.transform.localRotation = Quaternion.identity;
            cube.transform.localScale = scale;
    
            // TODO: Make a better color/material mechanism!
            cube.GetComponent<Renderer>().material.color = Color.red;
    
    //      Debug.Log("Cube.parent: " + cube.transform.parent.gameObject.name);
    //      Debug.Log("Cube.localScale: " + cube.transform.localScale);
        }
    }
    

    截图 - 笔记层次结构很奇怪:

    enter image description here

2 个答案:

答案 0 :(得分:2)

您的SceneController将其变换传递给GameMap Setup方法。 (我假设SceneController转换是“app”对象?)

GameMap Setup方法然后创建门并使用给定的parentTransform 作为每个门的父级(因为它是GameObject.Instantiate方法中的passend)

所以我觉得Gate对象是管理场景中“app”对象的孩子是否有意义?

如果你想让他们在另一个场景中,那么你必须传递一个不同的父母或没有父母。

答案 1 :(得分:0)

所以,据我所知,你想要一个管理场景,你可以用脚本来管理游戏。

我的想法是你不要使用LoadSceneAdditive而是使用DontDestroyOnLoad。这将使您的脚本仍然加载,即使您加载另一个场景。这也将使游戏对象在当前加载的场景中产生。

因此,您只需使用LoadSceneMode.Single代替LoadSceneMode.Additive

另一种选择是使用SceneManager.SetActiveScene来更改要设置为&#34;父级场景&#34;或者想要在其上产生游戏对象的场景。