如何让加载UI等待关卡数据加载完成后再隐藏?

问题描述 投票:0回答:1

我正在开发一款游戏,从 JSON 文件加载关卡数据并根据该数据实例化对象和地形 (SpriteShape)。我正在使用 Unity 和 C#。我的问题是我的加载 UI 立即隐藏,无需等待关卡数据完成加载。这是加载逻辑脚本:

void Start()
    {
        StartCoroutine(LoadLevel());
    }

    private IEnumerator LoadLevel()
    {
        loadingLevelUI.SetActive(true);
        GameObject ground = GameObject.Find("Ground");
        playerSpawn = GameObject.Find("PlayerSpawn");

        // Construct the full file path based on createdLevelsPath and currentLevel
        string createdLevelsPath = Path.Combine(Application.persistentDataPath, "CreatedLevels");
        string filePath = Path.Combine(createdLevelsPath, currentLevel);

        // Check if the file exists
        if (File.Exists(filePath))
        {
            // Read the file content
            string fileContent = File.ReadAllText(filePath, Encoding.UTF8); // Specify UTF-8 encoding for JSON

            try
            {
                // Deserialize the JSON data into a LevelData object
                LevelData levelData = JsonUtility.FromJson<LevelData>(fileContent);

                if (levelData.defaultSpawn != null && playerSpawn)
                {
                    playerSpawn.transform.position = new Vector3(levelData.defaultSpawn.x, levelData.defaultSpawn.y, -5.4f);
                }

                // Access and process the levelContent array
                if (levelData.levelContent != null)
                {
                    foreach (LevelData.LevelObject levelObject in levelData.levelContent)
                    {
                        // Remove "(Clone)" from the object name, if present
                        string objectName = levelObject.objectName.Replace("(Clone)", "").Trim();

                        // Find the prefab based on the object name
                        GameObject prefab = GetPrefab(objectName);

                        // Check if prefab was found
                        if (prefab == null)
                        {
                            Debug.LogWarning("Prefab for object '" + objectName + "' not found.");
                            continue; // Skip to next level object
                        }

                        // Instantiate the prefab
                        GameObject newObject = Instantiate(prefab);
                        Quaternion objectRot = levelObject.rotation;

                        // Set object position based on levelObject position
                        newObject.transform.position = levelObject.position;
                        newObject.transform.rotation = objectRot;
                        newObject.transform.localScale = levelObject.size;

                        // Parent the instantiated object to the ground
                        if (ground != null)
                            newObject.transform.parent = ground.transform;
                        else
                            Debug.LogWarning("Ground object not found.");
                    }

                    foreach (LevelData.LevelTerrain levelTerrain in levelData.levelTerrains)
                    {
                        string objectName = levelTerrain.terrainName.Replace("(Clone)", "").Replace("_p", "").Trim();

                        // Find the prefab based on the object name
                        GameObject prefab = GetPrefab(objectName);

                        // Check if prefab was found
                        if (prefab == null)
                        {
                            Debug.LogWarning("Prefab for terrain '" + objectName + "' not found.");
                            continue; // Skip to the next level terrain
                        }

                        // Instantiate the terrain prefab
                        GameObject newObject = Instantiate(prefab);
                        Quaternion objectRot = levelTerrain.rotation;
                        Vector2 size = levelTerrain.size;

                        // Set object position based on levelTerrain position
                        newObject.transform.position = levelTerrain.position;
                        newObject.transform.rotation = objectRot;
                        newObject.transform.localScale = new Vector3(size.x, size.y, 1f); // Ensure size is correctly set

                        if (ground != null)
                        {
                            newObject.transform.parent = ground.transform;
                        }
                        else
                        {
                            Debug.LogWarning("Ground object not found.");
                        }

                        Debug.Log("Instantiated Terrain: " + objectName + " at position: " + levelTerrain.position);
                        Debug.Log("Terrain size: " + levelTerrain.size);

                        // Clear existing points before loading new ones
                        SpriteShapeController terrainController = newObject.GetComponent<SpriteShapeController>();
                        if (terrainController != null)
                        {
                            terrainController.spline.Clear(); // Clear all existing points
                        }
                        else
                        {
                            Debug.LogError("Terrain prefab '" + objectName + "' does not have a SpriteShapeController component.");
                            continue; // Skip to the next level terrain if component is missing
                        }

                        // Load new points from levelTerrain.points
                        foreach (Vector3 point in levelTerrain.points)
                        {
                            Vector3 localPosition = point; // Use the saved position directly
                            terrainController.spline.InsertPointAt(terrainController.spline.GetPointCount(), localPosition);

                            int pointIndex = levelTerrain.points.IndexOf(point);
                            if (pointIndex >= 0 && pointIndex < levelTerrain.tangentMode.Count) // Check for valid index
                            {
                                ShapeTangentMode tangentMode = levelTerrain.tangentMode[pointIndex];
                                terrainController.spline.SetTangentMode(terrainController.spline.GetPointCount() - 1, tangentMode);

                                // Check if left and right tangent data exists (assuming separate lists)
                                if (pointIndex >= 0 && pointIndex < levelTerrain.leftTangents.Count && pointIndex < levelTerrain.rightTangents.Count)
                                {
                                    Vector3 leftTangent = levelTerrain.leftTangents[pointIndex];
                                    Vector3 rightTangent = levelTerrain.rightTangents[pointIndex];
                                    terrainController.spline.SetLeftTangent(terrainController.spline.GetPointCount() - 1, leftTangent);
                                    terrainController.spline.SetRightTangent(terrainController.spline.GetPointCount() - 1, rightTangent);
                                }
                                else
                                {
                                    Debug.LogWarning("Missing left/right tangent data for point " + pointIndex + " in terrain " + levelTerrain.terrainName);
                                }
                            }
                            else
                            {
                                Debug.LogError("Missing tangent mode data for point " + pointIndex + " in terrain " + levelTerrain.terrainName);
                            }
                        }
                    }
                }
                else
                {
                    Debug.Log("Level has no objects in levelContent.");
                }

                // Set isLevelLoaded to true after loading is complete
                isLevelLoaded = true;
            }
            catch (System.Exception e)
            {
                Debug.LogError("Error loading level data: " + e.Message);
            }
        }
        else
        {
            Debug.LogWarning("Level file not found: " + filePath);
        }

        // Wait until isLevelLoaded is true
        while (!isLevelLoaded)
        {
            yield return null;
        }

        // Once loaded, hide the loading UI
        loadingLevelUI.SetActive(false);
    }

它只是立即隐藏加载关卡 UI,导致大关卡加载时间更长,这意味着关卡在启动时将为空。

c# unity-game-engine
1个回答
0
投票

您可以通过在每个循环后使用

yield return null;
来解决它。这可确保在下一帧中处理每个对象和地形点。因此,它将保持加载 UI 可见,直到关卡完全加载。

所以它看起来就像这样:

foreach (LevelData.LevelObject levelObject in levelData.levelContent)
{
    //your current code
    yield return null; // add this at the end of the loop
}

foreach (LevelData.LevelTerrain levelTerrain in levelData.levelTerrains)
{
   //your current code
    yield return null; // same with this
}
© www.soinside.com 2019 - 2024. All rights reserved.