1053 lines
37 KiB
C#
1053 lines
37 KiB
C#
using UnityEngine;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System;
|
|
using System.Linq;
|
|
using UnityEngine.SceneManagement;
|
|
#if AT_STREAMER2
|
|
using Atavism;
|
|
#endif
|
|
|
|
namespace WorldStreamer2
|
|
{
|
|
/// <summary>
|
|
/// Streams async scene tiles
|
|
/// </summary
|
|
#if AT_STREAMER2
|
|
public class Streamer : AtavismStreamer
|
|
#else
|
|
public class Streamer : MonoBehaviour
|
|
#endif
|
|
{
|
|
/// <summary>
|
|
/// Activates/deactivates streamer.
|
|
/// </summary>
|
|
[Tooltip("This checkbox deactivates streamer and unload or doesn't load it's data.")]
|
|
public bool streamerActive = true;
|
|
|
|
/// <summary>
|
|
/// The streamer tag.
|
|
/// </summary>
|
|
public static string STREAMERTAG = "SceneStreamer";
|
|
|
|
// [HideInInspector]
|
|
[Tooltip("Drag and drop here your scene collection prefab. You could find it in catalogue with scenes which were generated by scene splitter.")]
|
|
/// <summary>
|
|
/// The scene collection of tiles.
|
|
/// </summary>
|
|
public List<SceneCollectionManager> sceneCollectionManagers;
|
|
|
|
[Header("Settings")] [Tooltip("Frequancy in seconds in which you want to check if grid element is close /far enough to load/unload.")]
|
|
/// <summary>
|
|
/// How often streamer checks player position.
|
|
/// </summary>
|
|
public float positionCheckTime = 0.1f;
|
|
|
|
[Tooltip("Time in seconds after which grid element will be unloaded.")]
|
|
/// <summary>
|
|
/// Destroys unloaded tiles after seconds.
|
|
/// </summary>
|
|
public float destroyTileDelay = 2;
|
|
|
|
[Tooltip("Number of empty frames between loading actions.")]
|
|
/// <summary>
|
|
/// The async scene load wait frames.
|
|
/// </summary>
|
|
public int sceneLoadWaitFrames = 2;
|
|
|
|
[Space(10)] [Tooltip("If you want to fix small holes from LODs system at unity terrain borders, drag and drop object here from scene hierarchy that contains our \"Terrain Neighbours\" script.")]
|
|
/// <summary>
|
|
/// The terrain neighbours manager.
|
|
/// </summary>
|
|
public TerrainNeighbours terrainNeighbours;
|
|
|
|
|
|
[Space(10)] [Tooltip("Enable looping system, each layer is streamed independently, so if you want to synchronize them, they should have the same XYZ size. More info at manual.")]
|
|
/// <summary>
|
|
/// Is world looping on.
|
|
/// </summary>
|
|
public bool looping = false;
|
|
|
|
|
|
/// <summary>
|
|
/// Override scene split range limit
|
|
/// </summary>
|
|
public bool overideRangeLimit = true;
|
|
|
|
/// <summary>
|
|
/// Override scene limits in scene collections
|
|
/// </summary>
|
|
public bool overideScenesLimits = true;
|
|
|
|
[Space(10)]
|
|
[Header("Player Settings")]
|
|
[Tooltip("Drag and drop here, an object that system have to follow during streaming process.")]
|
|
/// <summary>
|
|
/// The player transform.
|
|
/// </summary>
|
|
[SerializeField]
|
|
private Transform _player;
|
|
|
|
public Transform player
|
|
{
|
|
get
|
|
{
|
|
if (spawnedPlayer && _player == null && !string.IsNullOrEmpty(playerTag))
|
|
{
|
|
GameObject playerGO = GameObject.FindGameObjectWithTag(playerTag);
|
|
if (playerGO != null)
|
|
_player = playerGO.transform;
|
|
}
|
|
|
|
return _player;
|
|
}
|
|
set => _player = value;
|
|
}
|
|
|
|
[Tooltip("Streamer will wait for player spawn and fill it automatically")]
|
|
/// <summary>
|
|
/// Streamer will wait for player spawn and fill it automatically
|
|
/// </summary>
|
|
public bool spawnedPlayer;
|
|
|
|
[HideInInspector] public string playerTag = "Player";
|
|
|
|
[HideInInspector]
|
|
/// <summary>
|
|
/// The show loading screen on start?
|
|
/// </summary>
|
|
public bool showLoadingScreen = true;
|
|
|
|
|
|
[HideInInspector]
|
|
/// <summary>
|
|
/// The loading screen UI.
|
|
/// </summary>
|
|
public UILoadingStreamer loadingStreamer;
|
|
|
|
[HideInInspector] public bool initialized = false;
|
|
|
|
[HideInInspector]
|
|
/// <summary>
|
|
/// The tiles to load.
|
|
/// </summary>
|
|
public int tilesToLoad = int.MaxValue;
|
|
|
|
[HideInInspector]
|
|
/// <summary>
|
|
/// The tiles loaded.
|
|
/// </summary>
|
|
public int tilesLoaded;
|
|
|
|
/// <summary>
|
|
/// Gets the loading progress.
|
|
/// </summary>
|
|
/// <value>The loading progress.</value>
|
|
public float LoadingProgress
|
|
{
|
|
get { return (tilesToLoad > 0) ? tilesLoaded / (float)tilesToLoad : 1; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The world mover.
|
|
/// </summary>
|
|
[HideInInspector] public WorldMover
|
|
worldMover;
|
|
|
|
[HideInInspector]
|
|
/// <summary>
|
|
/// The current move.
|
|
/// </summary>
|
|
public Vector3 currentMove = Vector3.zero;
|
|
|
|
|
|
[HideInInspector] public bool xLimitsOverrideIs = false;
|
|
[HideInInspector] public bool yLimitsOverrideIs = false;
|
|
[HideInInspector] public bool zLimitsOverrideIs = false;
|
|
|
|
[HideInInspector] public Vector2Int xLimitsOverride = new Vector2Int(-100000, 100000);
|
|
[HideInInspector] public Vector2Int yLimitsOverride = new Vector2Int(-100000, 100000);
|
|
[HideInInspector] public Vector2Int zLimitsOverride = new Vector2Int(-100000, 100000);
|
|
|
|
/// <summary>
|
|
/// The scenes to load.
|
|
/// </summary>
|
|
List<SceneSplit> scenesToLoad = new List<SceneSplit>();
|
|
|
|
/// <summary>
|
|
/// The scene load frame next.
|
|
/// </summary>
|
|
int sceneLoadFrameNext = 0;
|
|
|
|
/// <summary>
|
|
/// The scene load frames next waited.
|
|
/// </summary>
|
|
bool sceneLoadFramesNextWaited = false;
|
|
|
|
|
|
public static StreamerLoadingManager loadingManager;
|
|
|
|
static bool canUnload = true;
|
|
static float waitTillNextUnload = 20;
|
|
static bool unloadNext = false;
|
|
|
|
/// <summary>
|
|
/// Awakes this instance and resets player position;
|
|
/// </summary>
|
|
void Awake()
|
|
{
|
|
//if (spawnedPlayer)
|
|
//{
|
|
// player = null;
|
|
//}
|
|
#if AT_STREAMER2
|
|
if (ClientAPI.GetPlayerObject() != null)
|
|
{
|
|
GameObject go = ClientAPI.GetPlayerObject().GameObject;
|
|
if (go != null)
|
|
player = go.transform;
|
|
}
|
|
#endif
|
|
foreach (var sceneCollectionManager in sceneCollectionManagers)
|
|
{
|
|
sceneCollectionManager.ResetPosition();
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Start this instance, prepares scene collection into scene array, starts player position checker
|
|
/// </summary>
|
|
void Start()
|
|
{
|
|
Debug.Log($"loadingManager {loadingManager}");
|
|
if (loadingManager != null)
|
|
Debug.Log($"loadingManager streamer {loadingManager.Streamer}");
|
|
|
|
loadingManager = new StreamerLoadingManager() { Streamer = this };
|
|
|
|
Debug.Log($"New streamer loading manager {loadingManager.Streamer}");
|
|
|
|
|
|
if (sceneCollectionManagers != null && sceneCollectionManagers.Count > 0)
|
|
{
|
|
PrepareScenesArray();
|
|
|
|
StartCoroutine(PositionChecker());
|
|
canUnload = true;
|
|
}
|
|
/*else
|
|
{
|
|
enabled = false;
|
|
Debug.LogError("No scene collection in streamer");
|
|
}*/
|
|
}
|
|
|
|
#region prepare scene
|
|
|
|
/// <summary>
|
|
/// Prepares the scenes array from collection
|
|
/// </summary>
|
|
void PrepareScenesArray()
|
|
{
|
|
Vector2Int xLimits = Vector2Int.zero;
|
|
Vector2Int yLimits = Vector2Int.zero;
|
|
Vector2Int zLimits = Vector2Int.zero;
|
|
|
|
if (sceneCollectionManagers.Count > 1)
|
|
{
|
|
sceneCollectionManagers[0].GetSceneCollectionWolrdLimits(out xLimits, out yLimits, out zLimits);
|
|
}
|
|
|
|
if (xLimitsOverrideIs)
|
|
{
|
|
xLimits = xLimitsOverride;
|
|
}
|
|
|
|
if (yLimitsOverrideIs)
|
|
{
|
|
yLimits = yLimitsOverride;
|
|
}
|
|
|
|
if (zLimitsOverrideIs)
|
|
{
|
|
zLimits = zLimitsOverride;
|
|
}
|
|
|
|
Debug.Log(xLimits + " " + yLimits + " " + zLimits);
|
|
|
|
|
|
foreach (var sceneCollectionManager in sceneCollectionManagers)
|
|
{
|
|
sceneCollectionManager.unloadRangeConnectParent = null;
|
|
}
|
|
|
|
foreach (var sceneCollectionManager in sceneCollectionManagers)
|
|
{
|
|
if (sceneCollectionManager.useUnloadRangeConnect && sceneCollectionManager.unloadRangeConnect != null)
|
|
{
|
|
sceneCollectionManager.unloadRangeConnect.unloadRangeConnectParent = sceneCollectionManager;
|
|
}
|
|
|
|
if (overideScenesLimits && sceneCollectionManagers.Count > 1)
|
|
{
|
|
sceneCollectionManager.CalculateLoadingLimits(looping, looping && overideRangeLimit, looping && overideScenesLimits, xLimits, yLimits, zLimits);
|
|
sceneCollectionManager.PrepareScenesArray(overideRangeLimit, overideScenesLimits, xLimits, yLimits, zLimits);
|
|
}
|
|
else
|
|
{
|
|
sceneCollectionManager.CalculateLoadingLimits(looping, looping && overideRangeLimit);
|
|
sceneCollectionManager.PrepareScenesArray(looping && overideRangeLimit);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts scene name into position
|
|
/// </summary>
|
|
/// <param name="sceneName">Scene name.</param>
|
|
/// <param name="posX">Position x.</param>
|
|
/// <param name="posY">Position y.</param>
|
|
/// <param name="posZ">Position z.</param>
|
|
public static void SceneNameToPos(SceneCollectionManager sceneCollectionManager, string sceneName, out int posX, out int posY, out int posZ)
|
|
{
|
|
posX = 0;
|
|
posY = 0;
|
|
posZ = 0;
|
|
|
|
string[] values = sceneName.Replace(sceneCollectionManager.prefixScene, "").Replace(".unity", "").Split(new char[]
|
|
{
|
|
'_'
|
|
}, System.StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
foreach (var item in values)
|
|
{
|
|
if (item[0] == 'x')
|
|
{
|
|
posX = int.Parse(item.Replace("x", ""));
|
|
}
|
|
|
|
if (item[0] == 'y')
|
|
{
|
|
posY = int.Parse(item.Replace("y", ""));
|
|
}
|
|
|
|
if (item[0] == 'z')
|
|
{
|
|
posZ = int.Parse(item.Replace("z", ""));
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
public static int mod(int x, int m)
|
|
{
|
|
return (x % m + m) % m;
|
|
}
|
|
|
|
#region scene loading
|
|
|
|
// called second
|
|
public void OnSceneLoaded(Scene scene, SceneSplit split)
|
|
{
|
|
GameObject[] rootGameObjects = scene.GetRootGameObjects();
|
|
|
|
|
|
if (rootGameObjects.Length > 0)
|
|
{
|
|
AddSceneGoMin(split, rootGameObjects[0]);
|
|
}
|
|
}
|
|
|
|
public void AddSceneGoMin(SceneSplit split, GameObject sceneGo)
|
|
{
|
|
SceneCollectionManager sceneCollectionManager = split.sceneCollectionManager;
|
|
int posX = 0;
|
|
int posY = 0;
|
|
int posZ = 0;
|
|
|
|
SceneNameToPos(split.sceneCollectionManager, split.sceneName, out posX, out posY, out posZ);
|
|
Vector3Int posInt = new Vector3Int(posX, posY, posZ);
|
|
|
|
|
|
SceneSplitManager sceneSplitManager = sceneGo.GetComponent<SceneSplitManager>();
|
|
|
|
tilesLoaded++;
|
|
|
|
float x = split.posX - posInt.x;
|
|
float y = split.posY - posInt.y;
|
|
float z = split.posZ - posInt.z;
|
|
|
|
Vector3 posSplit = new Vector3(sceneCollectionManager.xSize * x, sceneCollectionManager.ySize * y, sceneCollectionManager.zSize * z) + currentMove +
|
|
new Vector3(split.posXLimitMove, split.posYLimitMove, split.posZLimitMove);
|
|
|
|
|
|
if (split.sceneGo != null)
|
|
{
|
|
Debug.Log("Scene already loaded " + split.sceneName);
|
|
//return;
|
|
}
|
|
|
|
// Debug.Log("Added " + posInt + " " + posIntMoved);
|
|
BaseSplitSetup(split, sceneGo);
|
|
|
|
sceneGo.transform.position = posSplit;
|
|
sceneGo.name += $"split loaded on pos {posInt.x} {posInt.y} {posInt.z}";
|
|
|
|
|
|
SceneCollectionManager unloadSceneCollectionManager = null;
|
|
if (sceneCollectionManager.useUnloadRangeConnect && sceneCollectionManager.unloadRangeConnect != null)
|
|
{
|
|
unloadSceneCollectionManager = sceneCollectionManager.unloadRangeConnect;
|
|
}
|
|
|
|
if (sceneCollectionManager.unloadRangeConnectParent != null && sceneCollectionManager.unloadRangeConnectParent.useUnloadRangeConnect)
|
|
{
|
|
unloadSceneCollectionManager = sceneCollectionManager.unloadRangeConnectParent;
|
|
}
|
|
|
|
|
|
if (unloadSceneCollectionManager != null)
|
|
{
|
|
SceneSplit splitCheck;
|
|
float count = unloadSceneCollectionManager.loadedScenes.Count;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
splitCheck = unloadSceneCollectionManager.loadedScenes[i];
|
|
|
|
if (splitCheck.loadingFinished)
|
|
{
|
|
if (split.basePosX == splitCheck.basePosX && split.basePosY == splitCheck.basePosY && split.basePosZ == splitCheck.basePosZ)
|
|
{
|
|
if (posSplit == splitCheck.sceneGo.transform.position)
|
|
{
|
|
//Debug.Log("----Unloaded " + split.sceneName);
|
|
|
|
|
|
UnloadScenesSync(splitCheck);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void BaseSplitSetup(SceneSplit split, GameObject sceneGo)
|
|
{
|
|
split.sceneGo = sceneGo;
|
|
split.scene = sceneGo.scene;
|
|
split.loadingFinished = true;
|
|
split.sceneCollectionManager.currentlySceneLoading--;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region update functions
|
|
|
|
/// <summary>
|
|
/// Update this instance, starts load level async
|
|
/// </summary>
|
|
void Update()
|
|
{
|
|
LoadLevelAsyncManage();
|
|
loadingManager.Update();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Manages async scene loading
|
|
/// </summary>
|
|
void LoadLevelAsyncManage()
|
|
{
|
|
//Debug.Log("--------------------------------" + scenesToLoad.Count);
|
|
|
|
if (scenesToLoad.Count > 0)
|
|
{
|
|
if (LoadingProgress < 1 || sceneLoadFramesNextWaited && sceneLoadFrameNext <= 0)
|
|
{
|
|
//Debug.Log(LoadingProgress);
|
|
sceneLoadFramesNextWaited = false;
|
|
sceneLoadFrameNext = sceneLoadWaitFrames;
|
|
|
|
scenesToLoad = scenesToLoad.OrderBy(x => x.sceneCollectionManager.priority).ToList();
|
|
|
|
|
|
int i = 0;
|
|
while (scenesToLoad.Count > 0 && i < scenesToLoad.Count)
|
|
{
|
|
SceneSplit split = scenesToLoad[i];
|
|
|
|
if (split.sceneCollectionManager.currentlySceneLoading < split.sceneCollectionManager.maxParallelSceneLoading)
|
|
{
|
|
//Debug.Log(split.sceneName);
|
|
scenesToLoad.Remove(split);
|
|
split.sceneCollectionManager.currentlySceneLoading++;
|
|
loadingManager.LoadSceneAsync(split);
|
|
i--;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sceneLoadFramesNextWaited = true;
|
|
sceneLoadFrameNext--;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Coroutine checks player position
|
|
/// </summary>
|
|
/// <returns>The checker.</returns>
|
|
IEnumerator PositionChecker()
|
|
{
|
|
yield return new WaitForSeconds(positionCheckTime);
|
|
while (true)
|
|
{
|
|
if (spawnedPlayer && player == null && !string.IsNullOrEmpty(playerTag))
|
|
{
|
|
GameObject playerGO = GameObject.FindGameObjectWithTag(playerTag);
|
|
#if AT_STREAMER2
|
|
if(ClientAPI.GetPlayerObject() != null && playerGO==null)
|
|
playerGO = ClientAPI.GetPlayerObject().GameObject;
|
|
#endif
|
|
if (playerGO != null)
|
|
player = playerGO.transform;
|
|
}
|
|
|
|
|
|
if (streamerActive && player != null)
|
|
{
|
|
CheckPositionTiles();
|
|
}
|
|
else
|
|
{
|
|
#if !AT_STREAMER2
|
|
bool loadedScenes = false;
|
|
|
|
foreach (var sceneCollectionManager in sceneCollectionManagers)
|
|
{
|
|
if (sceneCollectionManager.loadedScenes.Count > 0)
|
|
{
|
|
loadedScenes = true;
|
|
sceneCollectionManager.ResetPosition();
|
|
}
|
|
}
|
|
|
|
if (loadedScenes)
|
|
UnloadAllScenes();
|
|
#endif
|
|
}
|
|
|
|
|
|
yield return new WaitForSeconds(positionCheckTime);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks the position of player in tiles.
|
|
/// </summary>
|
|
public void CheckPositionTiles()
|
|
{
|
|
Vector3 pos = player.position;
|
|
|
|
pos -= currentMove;
|
|
|
|
bool changed = false;
|
|
|
|
foreach (var sceneCollectionManager in sceneCollectionManagers)
|
|
{
|
|
if (sceneCollectionManager.CheckPosition(pos))
|
|
changed = true;
|
|
}
|
|
|
|
if (changed)
|
|
{
|
|
SceneLoading();
|
|
Invoke(nameof(SceneUnloading), destroyTileDelay);
|
|
|
|
if (worldMover != null)
|
|
{
|
|
worldMover.CheckMoverDistance(sceneCollectionManagers[0].xPos, sceneCollectionManagers[0].yPos, sceneCollectionManagers[0].zPos);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region loading and unloading
|
|
|
|
/// <summary>
|
|
/// Loads tiles in range
|
|
/// </summary>
|
|
void SceneLoading()
|
|
{
|
|
//show splash screen
|
|
if (showLoadingScreen && loadingStreamer != null)
|
|
{
|
|
showLoadingScreen = false;
|
|
if (tilesLoaded >= tilesToLoad)
|
|
{
|
|
tilesToLoad = int.MaxValue;
|
|
tilesLoaded = 0;
|
|
}
|
|
}
|
|
|
|
|
|
int tilesToLoadNew = 0;
|
|
int count = 0;
|
|
|
|
foreach (var scm in sceneCollectionManagers)
|
|
{
|
|
if (!scm.active)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
int x = scm.xPos;
|
|
int y = scm.yPos;
|
|
int z = scm.zPos;
|
|
|
|
|
|
int LoadingRangeX = (int)scm.loadingRange.x * 2 + 1;
|
|
int LoadingRangeZ = (int)scm.loadingRange.z * 2 + 1;
|
|
int xs = 0, zs = 0, dx = 0, dy = -1;
|
|
int t = Math.Max(LoadingRangeX, LoadingRangeZ);
|
|
int maxI = t * t;
|
|
|
|
|
|
//Debug.Log(LoadingRangeX);
|
|
//Debug.Log(LoadingRangeZ);
|
|
SceneSplit split;
|
|
for (int i = 0; i < maxI; i++)
|
|
{
|
|
if ((-LoadingRangeX / 2 <= xs) && (xs <= LoadingRangeX / 2) && (-LoadingRangeZ / 2 <= zs) && (zs <= LoadingRangeZ / 2))
|
|
{
|
|
for (int ys = 0; ys <= scm.loadingRange.y; ys++)
|
|
{
|
|
for (int yi = -1; yi <= 1; yi += 2)
|
|
{
|
|
if (ys == 0 && yi != -1)
|
|
continue;
|
|
|
|
count++;
|
|
|
|
if (scm.useLoadingRangeMin)
|
|
if (xs >= -scm.loadingRangeMin.x && xs <= scm.loadingRangeMin.x &&
|
|
ys >= -scm.loadingRangeMin.y && ys <= scm.loadingRangeMin.y &&
|
|
zs >= -scm.loadingRangeMin.z && zs <= scm.loadingRangeMin.z)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
x = xs + scm.xPos;
|
|
y = ys * yi + scm.yPos;
|
|
z = zs + scm.zPos;
|
|
|
|
|
|
Vector3Int sceneID = new Vector3Int(x, y, z);
|
|
|
|
//Debug.Log(sceneID);
|
|
|
|
|
|
float xMoveLimit = 0;
|
|
int xDeloadLimit = 0;
|
|
|
|
float yMoveLimit = 0;
|
|
int yDeloadLimit = 0;
|
|
|
|
float zMoveLimit = 0;
|
|
int zDeloadLimit = 0;
|
|
|
|
//set scene possition according to looping
|
|
if (looping)
|
|
{
|
|
if (scm.xSplitIs)
|
|
{
|
|
int xFinal = mod((x + Mathf.Abs(scm.xLoadingLimitx)), scm.xLoadingRange) + scm.xLoadingLimitx;
|
|
|
|
xDeloadLimit = (int)Math.Ceiling((x - scm.xLoadingLimity) / (float)scm.xLoadingRange) * scm.xLoadingRange;
|
|
xMoveLimit = xDeloadLimit * scm.xSize;
|
|
|
|
sceneID[0] = xFinal;
|
|
}
|
|
|
|
if (scm.ySplitIs)
|
|
{
|
|
int yFinal = mod((y + Mathf.Abs(scm.yLoadingLimitx)), scm.yLoadingRange) + scm.yLoadingLimitx;
|
|
|
|
yDeloadLimit = (int)Math.Ceiling((y - scm.yLoadingLimity) / (float)scm.yLoadingRange) * scm.yLoadingRange;
|
|
yMoveLimit = yDeloadLimit * scm.ySize;
|
|
sceneID[1] = yFinal;
|
|
}
|
|
|
|
|
|
if (scm.zSplitIs)
|
|
{
|
|
int zFinal = mod((z + Mathf.Abs(scm.zLoadingLimitx)), scm.zLoadingRange) + scm.zLoadingLimitx;
|
|
|
|
zDeloadLimit = (int)Math.Ceiling((z - scm.zLoadingLimity) / (float)scm.zLoadingRange) * scm.zLoadingRange;
|
|
zMoveLimit = zDeloadLimit * scm.zSize;
|
|
sceneID[2] = zFinal;
|
|
}
|
|
}
|
|
|
|
|
|
//Debug.Log(sceneID[0] + " " + sceneID[1] + " " + sceneID[2]);
|
|
|
|
//load scene if scene array contains it and set up scene offset position according to looping
|
|
if (scm.scenesArray.TryGetValue(sceneID, out split))
|
|
{
|
|
// Debug.Log(sceneID[0] + " " + sceneID[1] + " " + sceneID[2]);
|
|
|
|
if (!split.loaded)
|
|
{
|
|
split.loaded = true;
|
|
|
|
split.posXLimitMove = xMoveLimit;
|
|
split.xDeloadLimit = xDeloadLimit;
|
|
|
|
split.posYLimitMove = yMoveLimit;
|
|
split.yDeloadLimit = yDeloadLimit;
|
|
|
|
split.posZLimitMove = zMoveLimit;
|
|
split.zDeloadLimit = zDeloadLimit;
|
|
|
|
scenesToLoad.Add(split);
|
|
scm.loadedScenes.Add(split);
|
|
tilesToLoadNew++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//Debug.Log(scm.name+ " no scene id " + sceneID);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if ((xs == zs) || ((xs < 0) && (xs == -zs)) || ((xs > 0) && (xs == 1 - zs)))
|
|
{
|
|
t = dx;
|
|
dx = -dy;
|
|
dy = t;
|
|
}
|
|
|
|
xs += dx;
|
|
zs += dy;
|
|
}
|
|
}
|
|
|
|
|
|
tilesToLoad = tilesToLoadNew;
|
|
|
|
initialized = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Unloads tiles out of range
|
|
/// </summary>
|
|
void SceneUnloading()
|
|
{
|
|
List<SceneSplit> scenesToDestroy = new List<SceneSplit>();
|
|
|
|
|
|
SceneSplit splitCheck;
|
|
float count;
|
|
|
|
|
|
foreach (var scm in sceneCollectionManagers)
|
|
{
|
|
count = scm.loadedScenes.Count;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
splitCheck = scm.loadedScenes[i];
|
|
if (!scm.active)
|
|
{
|
|
scenesToDestroy.Add(splitCheck);
|
|
continue;
|
|
}
|
|
|
|
if (scm.unloadRangeConnectParent != null)
|
|
{
|
|
SceneCollectionManager connectedScm = scm.unloadRangeConnectParent;
|
|
|
|
//Debug.Log($"unloadRangeConnectParent {splitCheck.sceneName} {splitCheck.sceneGo.name} {splitCheck.sceneGo.scene.name}");
|
|
//Debug.Log(Mathf.Abs(splitCheck.posX + splitCheck.xDeloadLimit - scm.xPos) > scm.deloadingRange.x);
|
|
if ((Mathf.Abs(splitCheck.posX + splitCheck.xDeloadLimit - scm.xPos) > scm.deloadingRange.x ||
|
|
Mathf.Abs(splitCheck.posY + splitCheck.yDeloadLimit - scm.yPos) > scm.deloadingRange.y ||
|
|
Mathf.Abs(splitCheck.posZ + splitCheck.zDeloadLimit - scm.zPos) > scm.deloadingRange.z) &&
|
|
(Mathf.Abs(splitCheck.posX + splitCheck.xDeloadLimit - scm.xPos) > connectedScm.deloadingRange.x ||
|
|
Mathf.Abs(splitCheck.posY + splitCheck.yDeloadLimit - scm.yPos) > connectedScm.deloadingRange.y ||
|
|
Mathf.Abs(splitCheck.posZ + splitCheck.zDeloadLimit - scm.zPos) > connectedScm.deloadingRange.z))
|
|
if (splitCheck.sceneGo != null)
|
|
{
|
|
//Debug.Log($"split {splitCheck.sceneName} {splitCheck.sceneGo.name} {splitCheck.sceneGo.scene.name}");
|
|
scenesToDestroy.Add(splitCheck);
|
|
}
|
|
|
|
|
|
continue;
|
|
}
|
|
|
|
|
|
if (Mathf.Abs(splitCheck.posX + splitCheck.xDeloadLimit - scm.xPos) > (int)scm.deloadingRange.x
|
|
|| Mathf.Abs(splitCheck.posY + splitCheck.yDeloadLimit - scm.yPos) > (int)scm.deloadingRange.y
|
|
|| Mathf.Abs(splitCheck.posZ + splitCheck.zDeloadLimit - scm.zPos) > (int)scm.deloadingRange.z)
|
|
if (splitCheck.sceneGo != null)
|
|
{
|
|
// Debug.Log($"splitCheck.sceneName {splitCheck.sceneName} {splitCheck.sceneGo.name} {splitCheck.sceneGo.scene.name} base");
|
|
|
|
scenesToDestroy.Add(splitCheck);
|
|
}
|
|
|
|
if (scm.useLoadingRangeMin && !scm.useUnloadRangeConnect)
|
|
{
|
|
//Debug.Log($"splitCheck.sceneName {splitCheck.sceneName} {splitCheck.sceneGo.name} {splitCheck.sceneGo.scene.name} !useUnloadRangeConnect");
|
|
if (Mathf.Abs(splitCheck.posX + splitCheck.xDeloadLimit - scm.xPos) <= scm.loadingRangeMin.x &&
|
|
Mathf.Abs(splitCheck.posY + splitCheck.yDeloadLimit - scm.yPos) <= scm.loadingRangeMin.y &&
|
|
Mathf.Abs(splitCheck.posZ + splitCheck.zDeloadLimit - scm.zPos) <= scm.loadingRangeMin.z)
|
|
if (splitCheck.sceneGo != null)
|
|
{
|
|
//Debug.Log($"splitCheck.sceneName {splitCheck.sceneName} {splitCheck.sceneGo.name} {splitCheck.sceneGo.scene.name} useUnloadRangeConnect");
|
|
scenesToDestroy.Add(splitCheck);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
UnloadScenes(scenesToDestroy);
|
|
scenesToDestroy.Clear();
|
|
|
|
|
|
Streamer.UnloadAssets(this);
|
|
}
|
|
|
|
private void UnloadScenesSync(SceneSplit item)
|
|
{
|
|
if (item.sceneGo != null)
|
|
{
|
|
Terrain childTerrain = item.sceneGo.GetComponentInChildren<Terrain>();
|
|
if (childTerrain)
|
|
{
|
|
GameObject childTerrainGo = childTerrain.gameObject;
|
|
|
|
Destroy(childTerrain);
|
|
childTerrain = null;
|
|
Destroy(childTerrainGo);
|
|
childTerrainGo = null;
|
|
}
|
|
}
|
|
|
|
|
|
item.loaded = false;
|
|
item.loadingFinished = false;
|
|
item.sceneCollectionManager.loadedScenes.Remove(item);
|
|
item.sceneGo = null;
|
|
|
|
loadingManager.UnloadSplitAsync(item);
|
|
}
|
|
|
|
private void UnloadScenes(List<SceneSplit> scenesToDestroy)
|
|
{
|
|
foreach (var item in scenesToDestroy)
|
|
{
|
|
item.loaded = false;
|
|
item.loadingFinished = false;
|
|
item.sceneCollectionManager.loadedScenes.Remove(item);
|
|
item.sceneGo = null;
|
|
#if AT_STREAMER2
|
|
tilesLoaded--;
|
|
#endif
|
|
|
|
loadingManager.UnloadSplitAsync(item);
|
|
}
|
|
|
|
|
|
if (terrainNeighbours)
|
|
terrainNeighbours.CreateNeighbours();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Unloads all tiles of streamer
|
|
/// </summary>
|
|
public void UnloadAllScenes()
|
|
{
|
|
Debug.Log("UnloadAllScenes start");
|
|
|
|
foreach (var sceneCollectionManager in sceneCollectionManagers)
|
|
{
|
|
foreach (var item in sceneCollectionManager.scenesArray)
|
|
{
|
|
if (item.Value.sceneGo != null)
|
|
{
|
|
//Terrain childTerrain = item.Value.sceneGo.GetComponentInChildren<Terrain>();
|
|
//if (childTerrain)
|
|
//{
|
|
// GameObject childTerrainGO = childTerrain.gameObject;
|
|
|
|
// Destroy(childTerrain);
|
|
// childTerrain = null;
|
|
// Destroy(childTerrainGO);
|
|
// childTerrainGO = null;
|
|
|
|
//}
|
|
|
|
try
|
|
{
|
|
loadingManager.UnloadSplitAsync(item.Value);
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.Log(item.Value.sceneName);
|
|
Debug.Log(item.Value.sceneGo.name);
|
|
Debug.Log(item.Value.sceneGo.scene.name);
|
|
Debug.LogError(ex.Message);
|
|
}
|
|
}
|
|
|
|
|
|
item.Value.loaded = false;
|
|
item.Value.loadingFinished = false;
|
|
item.Value.sceneGo = null;
|
|
}
|
|
|
|
sceneCollectionManager.loadedScenes.Clear();
|
|
}
|
|
|
|
|
|
if (terrainNeighbours)
|
|
terrainNeighbours.CreateNeighbours();
|
|
|
|
Streamer.UnloadAssets(this);
|
|
Debug.Log("UnloadAllScenes finish");
|
|
}
|
|
|
|
|
|
public static void UnloadAssets(Streamer streamer)
|
|
{
|
|
if (Streamer.canUnload)
|
|
{
|
|
Streamer.canUnload = false;
|
|
|
|
streamer.StartCoroutine(streamer.UnloadAssetsWait());
|
|
}
|
|
else
|
|
unloadNext = true;
|
|
}
|
|
|
|
public IEnumerator UnloadAssetsWait()
|
|
{
|
|
do
|
|
{
|
|
unloadNext = false;
|
|
//Debug.Log("Resources.UnloadUnusedAssets");
|
|
Resources.UnloadUnusedAssets();
|
|
yield return new WaitForSeconds(waitTillNextUnload);
|
|
} while (unloadNext);
|
|
|
|
canUnload = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
//// called first
|
|
//void OnEnable()
|
|
//{
|
|
|
|
// SceneManager.sceneLoaded += OnSceneLoaded;
|
|
//}
|
|
|
|
|
|
//void OnDisable()
|
|
//{
|
|
// SceneManager.sceneLoaded -= OnSceneLoaded;
|
|
//}
|
|
|
|
void OnDrawGizmosSelected()
|
|
{
|
|
if (sceneCollectionManagers == null)
|
|
return;
|
|
Vector3 size = Vector3.zero;
|
|
Vector3 position = Vector3.zero;
|
|
Vector3Int loadingRange = Vector3Int.zero;
|
|
foreach (var scm in sceneCollectionManagers)
|
|
{
|
|
if (scm && scm.showDebug && scm.active)
|
|
{
|
|
Gizmos.color = scm.color;
|
|
size.x = scm.xSize == 0 ? 2 : scm.xSize;
|
|
size.y = scm.ySize == 0 ? 2 : scm.ySize;
|
|
size.z = scm.zSize == 0 ? 2 : scm.zSize;
|
|
|
|
loadingRange.x = !scm.xSplitIs ? 0 : scm.loadingRange.x;
|
|
loadingRange.y = !scm.ySplitIs ? 0 : scm.loadingRange.y;
|
|
loadingRange.z = !scm.zSplitIs ? 0 : scm.loadingRange.z;
|
|
|
|
|
|
for (int x = -(int)loadingRange.x + scm.xPos; x <= (int)loadingRange.x + scm.xPos; x++)
|
|
{
|
|
for (int y = -(int)loadingRange.y + scm.yPos; y <= (int)loadingRange.y + scm.yPos; y++)
|
|
{
|
|
for (int z = -(int)loadingRange.z + scm.zPos; z <= (int)loadingRange.z + scm.zPos; z++)
|
|
{
|
|
if (scm.useLoadingRangeMin && x - scm.xPos >= -scm.loadingRangeMin.x && x - scm.xPos <= scm.loadingRangeMin.x &&
|
|
y - scm.yPos >= -scm.loadingRangeMin.y && y - scm.yPos <= scm.loadingRangeMin.y &&
|
|
z - scm.zPos >= -scm.loadingRangeMin.z && z - scm.zPos <= scm.loadingRangeMin.z)
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (Application.isPlaying)
|
|
{
|
|
position.x = x * size.x;
|
|
position.y = y * size.y;
|
|
position.z = z * size.z;
|
|
}
|
|
else
|
|
{
|
|
position.x = (x - scm.xPos) * size.x;
|
|
position.y = (y - scm.yPos) * size.y;
|
|
position.z = (z - scm.zPos) * size.z;
|
|
}
|
|
|
|
|
|
Gizmos.DrawWireCube(position + size * 0.5f + currentMove, size);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Gizmos.color = Color.green;
|
|
|
|
if (Application.isPlaying)
|
|
|
|
Gizmos.DrawWireCube(new Vector3(scm.xPos * size.x, scm.yPos * size.y, scm.zPos * size.z) + size * 0.5f + currentMove, size);
|
|
else
|
|
Gizmos.DrawWireCube(size * 0.5f, size);
|
|
}
|
|
}
|
|
}
|
|
#if AT_STREAMER2
|
|
public override int GetTilesToLoad()
|
|
{
|
|
return tilesToLoad;
|
|
}
|
|
|
|
public override int GetTilesLoaded()
|
|
{
|
|
return tilesLoaded;
|
|
}
|
|
|
|
public override float GetLoadingProgress()
|
|
{
|
|
return (tilesToLoad > 0) ? tilesLoaded / (float)tilesToLoad : 1;
|
|
}
|
|
#endif
|
|
}
|
|
} |