using UnityEngine;
using System.Collections;
using System;
using Object = UnityEngine.Object;
public class ZoneLoader : MonoBehaviour
{
const float m_LoadDistance = 1500.0F;
const float m_UnloadDistance = 2500.0F;
//EDDIE CHANGE TO FIT NEW TERRAIN SIZE
public const float m_GridSize = 8046.0F;
public const int m_ZoneCount = 12;
static public ZoneLoader ms_Singleton;
static ZoneLoader singleton
{
get
{
// @TODO: use FindObjectsOfType to implement improved hotloading of scripts
if (ms_Singleton == null)
{
GameObject go = new GameObject ("ZoneLoader", typeof(ZoneLoader));
ms_Singleton = go.GetComponent(typeof(ZoneLoader)) as ZoneLoader;
}
return ms_Singleton;
}
}
bool m_IsLoading = false;
bool m_IsUnloading = false;
bool m_UseWWW = true;
bool m_UseWWWCaching = false;
int m_CacheVersion = 1;
Vector3 m_PlayerPosition;
Transform m_PlayerTransform;
static int m_ZonesUnloadedSinceLastAssetUnload = 0;
[System.Serializable]
public class Zone
{
public bool m_Loaded = false;
public bool m_IsLoadable = true;
public GameObject m_Root;
public Terrain m_Terrain;
public AssetBundle m_ZoneBundle;
public WWW m_ZoneDownload;
}
static string GetBaseUrl ()
{
if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.WindowsEditor)
return "file:// + " + Application.dataPath + "/../builds/AssetBundles/";
if (Application.platform == RuntimePlatform.OSXPlayer)
return "file:// + " + Application.dataPath + "/../../AssetBundles/";
else
return "AssetBundles/";
}
Zone[] m_Zones = new Zone[m_ZoneCount * m_ZoneCount];
static public string GetPrefix (string prefix, string postfix, int x, int y)
{
return string.Format("{0}{1}-{2}{3}", prefix, x, y, postfix);
}
static public string GetPrefix (int x, int y)
{
return GetPrefix("Map_", "", x, y);
}
IEnumerator LoadZone (int x, int y)
{
////@TODO: if (!Application.CanStreamedLevelBeLoaded (GetPrefix(x, y)))
if (m_IsLoading)
{
Debug.LogError("Already loading zone");
yield break;
}
Zone zone = m_Zones[m_ZoneCount*y + x];
// Zone cant be loaded
if (!zone.m_IsLoadable)
yield break;
m_IsLoading = true;
string levelName = GetPrefix(x, y);
if (m_UseWWWCaching || m_UseWWW)
{
string fullUrl = GetBaseUrl() + levelName + ".unity3d";
if (m_UseWWWCaching)
zone.m_ZoneDownload = WWW.LoadFromCacheOrDownload (fullUrl, m_CacheVersion);
else
zone.m_ZoneDownload = new WWW (fullUrl);
yield return zone.m_ZoneDownload;
// Make sure there were no errors in the download
if (zone.m_ZoneDownload.error != null)
{
Debug.LogError(zone.m_ZoneDownload.error);
zone.m_IsLoadable = false;
m_IsLoading = false;
zone.m_ZoneDownload.Dispose();
zone.m_ZoneDownload = null;
yield break;
}
// Load the scene so it becomes accessable from Application.LoadLevel
zone.m_ZoneBundle = zone.m_ZoneDownload.assetBundle;
zone.m_ZoneDownload.Dispose();
zone.m_ZoneDownload = null;
if (zone.m_ZoneBundle == null)
{
zone.m_IsLoadable = false;
m_IsLoading = false;
yield break;
}
}
// Load Level
AsyncOperation async = Application.LoadLevelAdditiveAsync(levelName);
yield return async;
// Necessary to prevent overwriting of another load level additive following immediately
// yield return 0;
// Find the root game object containing the level data
zone.m_Root = GameObject.Find("/" + levelName);
if (zone.m_Root != null)
{
Transform terain = zone.m_Root.transform.Find("Terrain");
if (terain)
zone.m_Terrain = terain.GetComponent(typeof(Terrain)) as Terrain;
zone.m_Loaded = true;
}
else
{
Debug.LogError(levelName + " could not be found after loading level");
}
// Hookup neighboring terrains so there are no seams in the LOD
for (int yi=Mathf.Max(y-1, 0);yi<Mathf.Min(y+2, m_ZoneCount);yi++)
{
for (int xi=Mathf.Max(x-1, 0);xi<Mathf.Min(x+2, m_ZoneCount);xi++)
{
Terrain curTerrain = GetLoadedTerrain(xi, yi);
if (curTerrain != null)
{
Terrain left = GetLoadedTerrain(xi-1, yi);
Terrain right = GetLoadedTerrain(xi+1, yi);
Terrain top = GetLoadedTerrain(xi, yi+1);
Terrain bottom = GetLoadedTerrain(xi, yi-1);
curTerrain.SetNeighbors (left, top, right, bottom);
}
}
}
m_IsLoading = false;
}
IEnumerator UnloadZone (int x, int y)
{
m_IsUnloading = true;
Zone zone = m_Zones[m_ZoneCount*y + x];
zone.m_Loaded = false;
if (zone.m_Root)
Destroy(zone.m_Root);
else
Debug.LogError("Root for zone has already been unloaded:" + GetPrefix(x, y));
zone.m_Terrain = null;
zone.m_Root = null;
yield return 0;
if (m_UseWWWCaching || m_UseWWW)
{
zone.m_ZoneBundle.Unload(true);
zone.m_ZoneBundle = null;
}
m_ZonesUnloadedSinceLastAssetUnload++;
m_IsUnloading = false;
}
/// Unload assets at some points
/// AsynchronousOperation op = Resources.GarbageCollectAssets(-1);
void OnEnable ()
{
ms_Singleton = this;
}
void Awake ()
{
ms_Singleton = this;
m_Zones = new Zone[m_ZoneCount * m_ZoneCount];
for (int i=0;i<m_Zones.Length;i++)
{
m_Zones *= new Zone();*
*}*
*if (m_UseWWWCaching)*
*{*
*///////@TODO: REMOVE THIS*
_Caching.Authorize ("test", "", 1024*1024*1000, "");_
*Caching.CleanCache();*
*}*
*// Precompute which dongs are loadable*
_/*_
*for (int y=0;y<m_DongCount;y++)*
*{*
*for (int x=0;x<m_DongCount;x++)*
*{*
<em>Dong dong = m_Dongs[m_DongCount*y + x];</em>
*dong.m_IsLoadable = CachingManifest.singleton.HasDongInZoneType(x, y, ms_ZoneType);*
*}*
*}*
_*/_
*ms_Singleton = this;*
*}*
*float GetSqrDistance (Vector3 position, int x, int y)*
*{*
<em>float minx = x * m_GridSize;</em>
<em>float maxx = (x+1) * m_GridSize;</em>
<em>float miny = y * m_GridSize;</em>
<em>float maxy = (y+1) * m_GridSize;</em>
*float xDistance = 0.0F;*
*float yDistance = 0.0F;*
*if (position.x < minx)*
*xDistance = Mathf.Abs(minx - position.x);*
*else if (position.x > maxx)*
*xDistance = Mathf.Abs(maxx - position.x);*
*if (position.z < miny)*
*yDistance = Mathf.Abs(miny - position.z);*
*else if (position.z > maxy)*
*yDistance = Mathf.Abs(maxy - position.z);*
_return xDistance * xDistance + yDistance * yDistance;_
*}*
*public static void SetPosition (Vector3 position)*
*{*
*singleton.m_PlayerPosition = position;*
*}*
*public static void SetPlayerTransform (Transform player)*
*{*
*singleton.m_PlayerTransform = player;*
*}*
*void GetClosestZone (Vector3 position, float closestDistance, out int closestX, out int closestY)*
*{*
*closestX = -1;*
*closestY = -1;*
_closestDistance = closestDistance * closestDistance;_
*for (int y=0;y<m_ZoneCount;y++)*
*{*
*for (int x=0;x<m_ZoneCount;x++)*
*{*
<em>Zone zone = m_Zones[m_ZoneCount*y + x];</em>
*if (!zone.m_Loaded && zone.m_IsLoadable)*
*{*
*float sqrDistance = GetSqrDistance(position, x, y);*
*if (sqrDistance < closestDistance)*
*{*
*closestDistance = sqrDistance;*
*closestX = x;*
*closestY = y;*
*}*
*}*
*}*
*}*
*}*
*void Update ()*
*{*
*if (m_PlayerTransform)*
*m_PlayerPosition = m_PlayerTransform.position;*
*if (m_IsLoading || m_IsUnloading)*
*return;*
*// Unload any zone that is far enough away*
*for (int y=0;y<m_ZoneCount;y++)*
*{*
*for (int x=0;x<m_ZoneCount;x++)*
*{*
<em>Zone zone = m_Zones[m_ZoneCount*y + x];</em>
*if (zone.m_Loaded)*
*{*
*float sqrDistance = GetSqrDistance(m_PlayerPosition, x, y);*
<em>if (sqrDistance > m_UnloadDistance * m_UnloadDistance)</em>
*{*
*StartCoroutine(UnloadZone(x, y));*
*return;*
*}*
*}*
*}*
*}*
*// Try loading the closest zone*
*int closestX, closestY;*
*GetClosestZone(m_PlayerPosition, m_LoadDistance, out closestX, out closestY);*
*if (closestX != -1)*
*StartCoroutine(LoadZone (closestX, closestY));*
*}*
*Terrain GetLoadedTerrain (int x, int y)*
*{*
*if ((x >= 0 && x < m_ZoneCount) && (y >= 0 && y < m_ZoneCount))*
*{*
<em>Zone zone = m_Zones[m_ZoneCount*y + x];</em>
*if (zone.m_Loaded)*
*return zone.m_Terrain;*
*}*
*return null;*
*}*
*}*
*```*
I tried to play this on my browser and the Unity player says made with Beta can only play on your machine. I haven't updated yet to get the Beta. So I tried to rebuild on my version of Unity but got this error: Assets/Plugins/ZoneLoader.cs(130,17): error CS0246: The type or namespace name `AsynchronousOperation' could not be found. Are you missing a using directive or an assembly reference? I will go through your code though to see what I can learn from it Thanks. :)
– SoloChristianGot it going :) It's fast and tells me a lot. Thank You
– SoloChristian