Saturday, April 8, 2017

webgl - Open world loading/unloading with asset bundle in unity


I have a very large environment which I have to load/unload in unity Webgl as I can't load them at once. So, I have divide the environment into 1000 x 1000m (1km) (each chunk is consist of three layer like objects layer, tree layer,floor layer) chunks and on my player I have attached this script for chunk loading/unloading, thanks to this guide.


    public class TileLoadingManager : MonoBehaviour
{
//[SerializeField]
public string tileTag;


//[SerializeField]
public Vector3 tileSize;

//[SerializeField]
public int maxDistance;

public GameObject[] tiles;

// Use this for initialization

void Start()
{
this.tiles = GameObject.FindGameObjectsWithTag(tileTag);
DeactivateDistantTiles();
}

void DeactivateDistantTiles()
{
Vector3 playerPosition = this.gameObject.transform.position;


foreach (GameObject tile in tiles)
{
Vector3 tilePosition = tile.gameObject.transform.position + (tileSize / 2f);

float xDistance = Mathf.Abs(tilePosition.x - playerPosition.x);
float zDistance = Mathf.Abs(tilePosition.z - playerPosition.z);

if (xDistance + zDistance > maxDistance)
{
tile.SetActive(false);

tile.GetComponent().AbLoadCall();

}
else
{
tile.SetActive(true);
tile.GetComponent().AbUnLoadCall();
}
}
}


void Update()
{
DeactivateDistantTiles();

}
}

Its loading/unloading my chunks but a problem is that, it is a costly method for load/unload as my object chunk (tile) count is around 4 (expected to grow). Additionally I am loading asset bundle from UnityWebReqest and destroying assets on-unload, so it very heavy task. So my question is that is this the right approach or I should need to adopt anything else?


EDIT: Bundle Loading Code Snippet:



public void AbLoadCall()
{
if (AbLoadCallCortoutineRef == null)
{
AbLoadCallCortoutineRef = StartCoroutine(AbLoadCallCoroutine());
}
}

IEnumerator AbLoadCallCoroutine()
{

for (int i = 0; i < perRegionAssetBundleList.Length; i++)
{
yield return StartCoroutine(perRegionAssetBundleList[i].DownloadABCall());
}

}

Actual Loading Code:


    public IEnumerator DownloadABCall()
{

if (!abObjectInstantiated)
{
//Debug.Log(assetName + " , downloading assetbundle. . ");
yield return StartCoroutine(DownloadAB(assetBundleURL));
}
else
{
//Debug.Log("Reactivintg");
if (!abObjectInstantiated.activeInHierarchy)
{

//Debug.Log("Reactive done"+ this.assetName);
abObjectInstantiated.SetActive(true);
}

if (floorL7MeshRenderer)
{
floorL7MeshRenderer.enabled = false;
}

}

//else
//{
// Debug.Log(this.name + " , Bundle object has alread available.");
//}
}

IEnumerator DownloadAB(string bundleURL, string assetName = "")
{
Debug.Log(". . DownloadAB. . ,"+ this.name);
isBundleLoading = true;


www = UnityWebRequestAssetBundle.GetAssetBundle(bundleURL);
//Debug.Log("web req about to send : " + assetName);

yield return www.SendWebRequest();

if (www.error != null)
{
Debug.LogError("assetBundleURL : " + assetBundleURL);
Debug.LogError("www error : " + www.error);

www.Dispose();
www = null;
yield break;
}

//Debug.Log("bundle loading , "+ assetName);

// get bundle from downloadhandler
AssetBundle bundle = ((DownloadHandlerAssetBundle)www.downloadHandler).assetBundle;


GameObject bundlePrefab = null;

bundlePrefab = (GameObject)bundle.LoadAsset(bundle.GetAllAssetNames()[0]);


// if we got something out
if (bundlePrefab != null)
{

abObjectInstantiated = (GameObject)Instantiate(bundlePrefab);

abObjectInstantiated.transform.parent = envParent.transform;

if (floorL7MeshRenderer)
{
floorL7MeshRenderer.enabled = false;
}

}

www.Dispose();

www = null;

Resources.UnloadUnusedAssets();
bundle.Unload(false);
bundle = null;

isBundleLoading = false;
//Debug.Log("bundle unloading completed ," + assetName);
}


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...