加載場(chǎng)景有兩種方法,一種是常規(guī)的build settings添加scene,一種是通過(guò)AssetBundle加載Scene。
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneTest : MonoBehaviour
{
void Start()
{
SceneManager.LoadSceneAsync("xxx1", LoadSceneMode.Additive);
SceneManager.LoadSceneAsync("xxx2", LoadSceneMode.Additive);
SceneManager.LoadSceneAsync("xxx3", LoadSceneMode.Additive);
}
}
?上面是標(biāo)準(zhǔn)的異步加載場(chǎng)景,如果不在build settings中添加場(chǎng)景,直接加載scene,就會(huì)報(bào)下面的錯(cuò)。
因此對(duì)于需要熱更新的項(xiàng)目,如果場(chǎng)景.unity資源變更了,無(wú)法在build settings中重新設(shè)置,只能用Assetbundle加載場(chǎng)景。?
下面是打ab包的工具(BuildAssetBundleTool放到Scripts/Editor文件夾下)和標(biāo)準(zhǔn)化路徑工具。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
/// <summary>
/// 構(gòu)建工具類:
/// 創(chuàng)建了三種構(gòu)建方法windows android ios。
/// Build方法:從所有路徑查找文件,排除meta后,把每個(gè)文件名作為被打包資源名和bundle名(當(dāng)然一個(gè)bundle可以打包多個(gè)文件)
/// </summary>
public class BuildAssetBundleTool : Editor
{
//如何使用Build呢,直接添加工具欄
[MenuItem("Tools/Build Windows Bundle")]
static void BundleWindowsBuild()
{
Build(BuildTarget.StandaloneWindows);
}
//如何使用Build呢,直接添加工具欄
[MenuItem("Tools/Build Android Bundle")]
static void BundleAndroidBuild()
{
Build(BuildTarget.Android);
}
//如何使用Build呢,直接添加工具欄
[MenuItem("Tools/Build IOS Bundle")]
static void BundleIOSBuild()
{
Build(BuildTarget.iOS);
}
//為了能夠構(gòu)建多平臺(tái),需要把目標(biāo)平臺(tái)作為參數(shù)傳入。
static void Build(BuildTarget target)
{
//主要目的是收集這個(gè)build信息,需要打哪些文件,需要給bundle包用一個(gè)什么樣的名字,BuildAssetBundles函數(shù)用到這個(gè)Build數(shù)組
List<AssetBundleBuild> assetBundleBuilds = new List<AssetBundleBuild>();
//第一步搜索出我們這個(gè)所有文件的文件名Directory.GetDirectories和Directory.GetFiles對(duì)應(yīng)兩種打包策略一個(gè)獲取文件夾一個(gè)獲取文件,GetFiles比較簡(jiǎn)單
//searchPattern通配符,*是默認(rèn) https://www.cnblogs.com/ost/archive/2006/08/20/481625.html
string[] files = Directory.GetFiles(PathUtil.BuildResourcesPath, "*", SearchOption.AllDirectories);
//所有文件都找出來(lái)了,需要排除調(diào)meta文件
for (int i = 0; i < files.Length; i++)
{
if (files[i].EndsWith(".meta"))
{
continue;
}
//創(chuàng)建一個(gè)需要build的Bundle
AssetBundleBuild assetBundle = new AssetBundleBuild();
//處理出來(lái)的路徑斜杠可能不同。需要規(guī)范一下
string fileName = PathUtil.GetStandardPath(files[i]);
string assetName = PathUtil.GetUnityPath(fileName);//獲取unity相對(duì)路徑
//一個(gè)assetBundle可以打包多個(gè)文件,這里只放一個(gè)文件
assetBundle.assetNames = new string[] { assetName };//assetBundle是一個(gè)相對(duì)路徑文件名
//創(chuàng)建包名
string bundleName = fileName.Replace(PathUtil.BuildResourcesPath, "").ToLower();
assetBundle.assetBundleName = bundleName + ".ab";//Bundle需要后綴是.ab,,,,,,,,至此,Bundle的信息收集完了,需要放進(jìn)list
assetBundleBuilds.Add(assetBundle);
}
//為什么不用另一個(gè)重載BuildAssetBundles(string outputPath, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform),是因?yàn)樾枰约喝ベY源設(shè)置bundle名打標(biāo)簽,很麻煩
//第二個(gè)參數(shù)把list轉(zhuǎn)為array數(shù)組
//第三個(gè)參數(shù)是壓縮格式,選擇默認(rèn)
//第四個(gè)參數(shù)是目標(biāo)平臺(tái),先選擇win
if(Directory.Exists(PathUtil.BundleOutPath))
{
//判斷是否有路徑,如果有這個(gè)文件夾,就刪掉文件,,遞歸recursive刪掉所有文件和子文件。
Directory.Delete(PathUtil.BundleOutPath, true);
}
Directory.CreateDirectory(PathUtil.BundleOutPath);//刪除路徑后,創(chuàng)建路徑
BuildPipeline.BuildAssetBundles(PathUtil.BundleOutPath, assetBundleBuilds.ToArray(), BuildAssetBundleOptions.None, target);
}
}
/// <summary>
/// 路徑工具類:
/// 1定義了所有用到的路徑
/// 2返回標(biāo)準(zhǔn)路徑或返回unity下的幾個(gè)文件夾的相對(duì)路徑
/// </summary>
//因?yàn)樗新窂蕉家玫?,所以?xiě)入一個(gè)只讀變量中,用來(lái)后期訪問(wèn)
public class PathUtil
{
//為什么要把Application定義出來(lái),因?yàn)槊恳淮卧L問(wèn)都需要GC一次,定義出來(lái)就訪問(wèn)一次;
public static readonly string AssetPath = Application.dataPath;
//只讀的,需要打Bundle的目錄
public static readonly string BuildResourcesPath = AssetPath + "/BuildResources/";
//Bundle輸出目錄
public static readonly string BundleOutPath = Application.streamingAssetsPath;
/// <summary>
/// 獲取Unity的相對(duì)路徑
/// </summary>
/// <param name="path">絕對(duì)路徑</param>
/// <returns></returns>
public static string GetUnityPath(string path)
{
if(string.IsNullOrEmpty(path))
{
return string.Empty;
}
//從Assets位置拿到相對(duì)目錄
return path.Substring(path.IndexOf("Assets"));
}
/// <summary>
/// 獲取標(biāo)準(zhǔn)路徑
/// </summary>
/// <param name="path">路徑</param>
/// <returns></returns>
public static string GetStandardPath(string path)
{
if (string.IsNullOrEmpty(path))
{
return string.Empty;
}
//先處理空格,在處理反斜杠
return path.Trim().Replace("\\", "/");
}
}
這兩個(gè)工具放到文件夾后,在unity工具欄的位置出現(xiàn)Editor新工具,選擇第一個(gè)構(gòu)建Bundle,就可以把創(chuàng)建好的場(chǎng)景打包到StreamingAssets路徑下,,,在SceneTest中通過(guò)這個(gè)路徑,加載AssetBundle包,就可以動(dòng)態(tài)加載場(chǎng)景了。
?重新編寫(xiě)SceneTest場(chǎng)景加載的腳本,掛到起始場(chǎng)景的任意物體上,就可以動(dòng)態(tài)加載場(chǎng)景了。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class sceneTest : MonoBehaviour
{
// Start is called before the first frame update
IEnumerator Start()
{
yield return LoadSceneAB("xxx1");
yield return LoadSceneAB("xxx2");
yield return LoadSceneAB("xxx3");
}
IEnumerator LoadSceneAB(string sceneName)
{
string assetBundleName = "scenes/" + sceneName +".unity.ab";
string path = Application.dataPath + "/StreamingAssets/" + assetBundleName;
AssetBundleCreateRequest myLoadedAssetBundle = AssetBundle.LoadFromFileAsync(path);
yield return myLoadedAssetBundle;
if (myLoadedAssetBundle != null)
{
SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
}
}
}
?運(yùn)行前后
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-506847.html
?如果該場(chǎng)景中依賴于其他物體、材質(zhì)等,也是通過(guò)打包才能獲取的,那么需要將其他物體也通過(guò)AssetBundle獲取,獲取方法需要編寫(xiě)一個(gè)依賴文件,說(shuō)明此資源依賴于哪些資源,并通過(guò)遞歸的方法,加載這些依賴資源的ab包,下次再寫(xiě)這個(gè)地方的實(shí)現(xiàn)。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-506847.html
到了這里,關(guān)于AssetBundle動(dòng)態(tài)加載Scene場(chǎng)景的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!