该项目的目的是同时测试和演示来自 Unity DOTS 技术堆栈的多个新包。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

186 行
6.0 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using Unity.Sample.Core;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
using UnityEngine.SceneManagement;
public enum LevelState
{
Loading,
Loaded,
}
public class Level
{
public LevelState state;
public string name;
public AsyncOperation loadOperation;
}
public class LevelManager
{
public Level currentLevel { get; private set; }
public void Init()
{
#if UNITY_EDITOR
if (GameBootStrap.IsSingleLevelPlaymode)
currentLevel = new Level {state = LevelState.Loaded, name = UnityEditor.SceneManagement.EditorSceneManager.GetSceneAt(0).name};
#endif
}
public bool IsCurrentLevelLoaded()
{
return currentLevel != null && currentLevel.state == LevelState.Loaded;
}
public bool IsLoadingLevel()
{
return currentLevel != null && currentLevel.state == LevelState.Loading;
}
public string GetScenePathFromName(string name)
{
#if UNITY_EDITOR
foreach(var l in AssetDatabase.FindAssets("t:" + typeof(LevelInfo).Name))
{
var path = AssetDatabase.GUIDToAssetPath(l);
if (path.ToLower().EndsWith("/" + name.ToLower() + ".asset"))
{
var levelInfo = AssetDatabase.LoadAssetAtPath<LevelInfo>(path);
return AssetDatabase.GetAssetPath(levelInfo.main_scene);
}
}
#else
for(int i = 0, c = SceneManager.sceneCountInBuildSettings; i < c; ++i)
{
if(SceneUtility.GetScenePathByBuildIndex(i).ToLower().EndsWith(name.ToLower()+".unity"))
{
return SceneUtility.GetScenePathByBuildIndex(i);
}
}
#endif
return "";
}
public bool CanLoadLevel(string name)
{
return GetScenePathFromName(name) != "";
}
// Name is the name of the LevelInfo asset (sans .asset)
public bool LoadLevel(string name)
{
if (currentLevel != null)
UnloadLevel();
var path = GetScenePathFromName(name);
if(path == "")
{
GameDebug.Log("Unable to find " + name + " in included scenes");
return false;
}
#if UNITY_EDITOR
AsyncOperation mainLoadOperation = UnityEditor.SceneManagement.EditorSceneManager.LoadSceneAsyncInPlayMode(path, new LoadSceneParameters(LoadSceneMode.Single));
#else
AsyncOperation mainLoadOperation = SceneManager.LoadSceneAsync(path, new LoadSceneParameters(LoadSceneMode.Single));
#endif
if (mainLoadOperation == null)
{
GameDebug.Log("Failed to load level : " + name);
return false;
}
var newLevel = new Level();
newLevel.name = name;
currentLevel = newLevel;
currentLevel.loadOperation = mainLoadOperation;
return true;
}
public void UnloadLevel()
{
if (currentLevel == null)
return;
if (currentLevel.state == LevelState.Loading)
throw new NotImplementedException("TODO : Implement unload during load");
// TODO : Load empty scene for now
SceneManager.LoadScene(1);
currentLevel = null;
}
public void Update()
{
if (currentLevel != null && currentLevel.state == LevelState.Loading)
{
var done = currentLevel.loadOperation.isDone;
if (done)
{
// Do activation here?
currentLevel.state = LevelState.Loaded;
if (Game.GameLoopCount == 1)
{
if (Game.GetGameLoop<ServerGameLoop>() != null)
StripCode(BuildType.Server, true);
else if (Game.GetGameLoop<ClientGameLoop>() != null)
StripCode(BuildType.Client, true);
else
StripCode(BuildType.Default, true);
}
else
StripCode(BuildType.Default, true);
GameDebug.Log("Scene " + currentLevel.name + " loaded");
}
}
}
// TODO (petera) this code was moved here to make it available outside of editor - until we start cooking for client/server
public enum BuildType
{
Default,
Client,
Server,
}
public static void StripCode(BuildType buildType, bool isDevelopmentBuild)
{
GameDebug.Log("Stripping code for " + buildType.ToString() + " (" + (isDevelopmentBuild ? "DevBuild" : "NonDevBuild") + ")");
var deleteBehaviors = new List<MonoBehaviour>();
var deleteGameObjects = new List<GameObject>();
foreach (var behavior in UnityEngine.Object.FindObjectsOfType<MonoBehaviour>())
{
if (behavior.GetType().GetCustomAttributes(typeof(EditorOnlyComponentAttribute), false).Length > 0)
deleteBehaviors.Add(behavior);
else if (behavior.GetType().GetCustomAttributes(typeof(EditorOnlyGameObjectAttribute), false).Length > 0)
deleteGameObjects.Add(behavior.gameObject);
else if (buildType == BuildType.Server && behavior.GetType().GetCustomAttributes(typeof(ClientOnlyComponentAttribute), false).Length > 0)
deleteBehaviors.Add(behavior);
else if (buildType == BuildType.Client && behavior.GetType().GetCustomAttributes(typeof(ServerOnlyComponentAttribute), false).Length > 0)
deleteBehaviors.Add(behavior);
else if (!isDevelopmentBuild && behavior.GetType().GetCustomAttributes(typeof(DevelopmentOnlyComponentAttribute), false).Length > 0)
deleteBehaviors.Add(behavior);
}
GameDebug.Log(string.Format("Stripping {0} game object(s) and {1} behavior(s)", deleteGameObjects.Count, deleteBehaviors.Count));
foreach (var gameObject in deleteGameObjects)
UnityEngine.Object.DestroyImmediate(gameObject);
foreach (var behavior in deleteBehaviors)
UnityEngine.Object.DestroyImmediate(behavior);
}
}