XRoom_Unity/Assets/Scripts/AssetBundleDownloader/SceneDownloader.cs

216 lines
6.5 KiB
C#

using System.Collections;
using System.Collections.Generic;
using RTLTMPro;
using TMPro;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class SceneDownloader : MonoBehaviour
{
[SerializeField] private GameObject buttonPrefab;
[SerializeField] private Transform buttonParent;
private Dictionary<string, AssetBundle> downloadedBundles = new();
private Dictionary<string, string> sceneNames = new();
void Start()
{
StartCoroutine(GenerateButtonsForSpaces());
}
public void loadSceneManually()
{
EN.instance.selectedSpaceId = "coaching";
}
private IEnumerator GenerateButtonsForSpaces()
{
while (EN.instance == null || EN.instance.spaces == null || EN.instance.spaces.Count == 0)
yield return null;
foreach (var space in EN.instance.spaces)
{
if (!string.IsNullOrEmpty(space.assetBundleRoomId?.url))
{
string fullUrl = "http://194.62.43.230:8000/" + space.assetBundleRoomId.url;
GameObject buttonObj = Instantiate(buttonPrefab, buttonParent);
buttonObj.name = "Button_" + space.name;
RTLTextMeshPro btnText = buttonObj.GetComponentInChildren<RTLTextMeshPro>();
btnText.text = space.name;
GameObject progressPanel = buttonObj.transform.Find("progressPanel").gameObject;
TMP_Text progressText = FindTextWithTag(progressPanel, "percent");
progressPanel.SetActive(false);
Button btn = buttonObj.GetComponent<Button>();
btn.onClick.AddListener(() =>
{
StartCoroutine(OnSpaceButtonClicked(space, fullUrl, progressPanel, progressText));
});
}
}
}
private IEnumerator OnSpaceButtonClicked(UserSpace space, string bundleUrl, GameObject progressPanel, TMP_Text progressText)
{
string spaceName = space.name;
if (downloadedBundles.ContainsKey(spaceName))
{
LoadScene(space);
yield break;
}
progressPanel.SetActive(true);
progressText.text = "0%";
// Use a hardcoded or dynamic hash to uniquely version your bundles
Hash128 bundleHash = Hash128.Parse("0123456789abcdef0123456789abcdef"); // replace with your actual versioning logic
// Check if bundle is already cached
bool isCached = Caching.IsVersionCached(bundleUrl, bundleHash);
if (isCached)
{
Debug.Log("Loading from cache: " + bundleUrl);
}
UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(bundleUrl, bundleHash, 0);
var operation = request.SendWebRequest();
while (!operation.isDone)
{
int percent = Mathf.RoundToInt(operation.progress * 100);
progressText.text = percent + "%";
yield return null;
}
if (request.result != UnityWebRequest.Result.Success)
{
Debug.LogError("Failed to download AssetBundle: " + request.error);
progressText.text = "Error!";
yield return new WaitForSeconds(1.5f);
progressPanel.SetActive(false);
}
else
{
AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);
if (bundle == null)
{
progressText.text = "Load failed!";
yield return new WaitForSeconds(1.5f);
progressPanel.SetActive(false);
yield break;
}
downloadedBundles[spaceName] = bundle;
string scenePath = bundle.GetAllScenePaths()[0];
string sceneName = System.IO.Path.GetFileNameWithoutExtension(scenePath);
sceneNames[spaceName] = sceneName;
progressText.text = "Done!";
yield return new WaitForSeconds(0.5f);
progressPanel.SetActive(false);
}
}
private void LoadScene(UserSpace space)
{
string spaceName = space.name;
if (!sceneNames.ContainsKey(spaceName))
{
Debug.LogError("No scene for space: " + spaceName);
return;
}
string sceneToLoad = sceneNames[spaceName];
EN.instance.selectedSpaceId = space.assetBundleRoomId.id.ToString(); // Save scene ID for use elsewhere
SceneManager.sceneLoaded += OnSceneLoaded;
SceneManager.LoadScene(sceneToLoad);
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
Debug.Log("Scene loaded, fixing shaders and skybox...");
Renderer[] renderers = GameObject.FindObjectsOfType<Renderer>(true);
foreach (Renderer renderer in renderers)
{
foreach (Material mat in renderer.sharedMaterials)
{
FixMaterialShader(mat);
}
}
if (RenderSettings.skybox == null || RenderSettings.skybox.shader == null)
{
Material fallbackSkybox = Resources.Load<Material>("FallbackSkybox");
if (fallbackSkybox != null)
{
RenderSettings.skybox = fallbackSkybox;
Debug.Log("Applied fallback skybox.");
}
else
{
Debug.LogWarning("FallbackSkybox material not found in Resources.");
}
}
else
{
Shader skyboxShader = Shader.Find(RenderSettings.skybox.shader.name);
if (skyboxShader != null)
{
RenderSettings.skybox.shader = skyboxShader;
Debug.Log("Skybox shader fixed: " + skyboxShader.name);
}
else
{
Debug.LogWarning("Skybox shader not found: " + RenderSettings.skybox.shader.name);
}
}
SceneManager.sceneLoaded -= OnSceneLoaded;
}
private void FixMaterialShader(Material mat)
{
if (mat == null || mat.shader == null) return;
Shader foundShader = Shader.Find(mat.shader.name);
if (foundShader != null)
{
mat.shader = foundShader;
}
else
{
Debug.LogWarning("Shader not found: " + mat.shader.name);
}
}
public void UnloadAllBundles()
{
foreach (var bundle in downloadedBundles.Values)
bundle.Unload(false);
downloadedBundles.Clear();
sceneNames.Clear();
}
private TMP_Text FindTextWithTag(GameObject parent, string tag)
{
foreach (Transform child in parent.transform)
{
if (child.CompareTag(tag))
return child.GetComponent<TMP_Text>();
}
return null;
}
}