1.项目工程路径下创建文件夹:ABundles
2.AB包打包脚本:
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
public class AssetBundlePackage {
static string[] GetBuildScenes() {
List<string> sceneArray = new List<string>();
foreach (EditorBuildSettingsScene e in EditorBuildSettings.scenes) {
if (e == null) continue;
if (e.enabled) sceneArray.Add(e.path);
}
return sceneArray.ToArray();
}
[MenuItem("BuildScene/Build")]
public static void BuildScene() {
//BundleAssetsBundle_Webgl();
string folderPath = EditorUtility.OpenFolderPanel("Select Folder", "", "");
Debug.Log("Selected Folder: " + folderPath);
BuildPipeline.BuildPlayer(new string[] { "Assets/GameStart.unity" }, folderPath, BuildTarget.WebGL, BuildOptions.AutoRunPlayer);
}
[MenuItem("BuildScene/BuildForMobile")]
public static void BuildSceneForMobile()
{
//BundleAssetsBundle_Webgl();
string folderPath = EditorUtility.OpenFolderPanel("Select Folder", "", "");
Debug.Log("Selected Folder: " + folderPath);
BuildPipeline.BuildPlayer(new string[] { "Assets/GameStartMoibile.unity" }, folderPath, BuildTarget.WebGL, BuildOptions.AutoRunPlayer);
}
[MenuItem("SceneAsset/BuildCurrent")]
public static void BuildCurrentScene() {
string rootPath = Application.dataPath.ToLower().Replace("assets", "") + "ABundles/webgl/scenes";
string scenePath = EditorSceneManager.GetActiveScene().path;
string sceneName = System.IO.Path.GetFileNameWithoutExtension(scenePath).ToLower();
AssetBundleBuild assetBundleBuild = new AssetBundleBuild();
assetBundleBuild.assetNames = new []{ scenePath };
assetBundleBuild.assetBundleName = sceneName + ".bundle";
BuildPipeline.BuildAssetBundles(rootPath, new AssetBundleBuild[] { assetBundleBuild}, BuildAssetBundleOptions.None, BuildTarget.WebGL);
}
[MenuItem("SceneAsset/BuildAllScene")]
public static void BuildAllScene() {
bool isOk = EditorUtility.DisplayDialog("确认框", "是否将所有场景打成AB包", "确认", "取消");
if (!isOk) {
return;
}
//AB包路径是ABundles
string rootPath = Application.dataPath.ToLower().Replace("assets","") + "ABundles/webgl/scenes";
var allScenesPath = GetBuildScenes();
foreach (var scenePath in allScenesPath) {
string sceneName = System.IO.Path.GetFileNameWithoutExtension(scenePath).ToLower();
AssetBundleBuild assetBundleBuild = new AssetBundleBuild();
assetBundleBuild.assetNames = new[] { scenePath };
assetBundleBuild.assetBundleName = sceneName + ".bundle";
Debug.Log(sceneName + scenePath);
BuildPipeline.BuildAssetBundles(rootPath, new AssetBundleBuild[] { assetBundleBuild }, BuildAssetBundleOptions.None, BuildTarget.WebGL);
}
}
[MenuItem("AssetBundle/BuildWebGL")]
public static void BundleAssetsBundle_Webgl() {
Debug.Log("BundleAssetsBundle WebGL");
BuildAllAssetBundles();
}
private static void BuildAssetsBundle(BuildTarget target) {
//string packagePath = Application.streamingAssetsPath;
//if (packagePath.Length <= 0 && !Directory.Exists(packagePath))
//{
// return;
//}
//BuildPipeline.BuildAssetBundles(packagePath, BuildAssetBundleOptions.UncompressedAssetBundle, target);
}
//Asset/BundleAsset/Prefab/Com/a.bundle Prefab/Com/a
public static string RemovePrefix(string inputString) {
inputString = inputString.Replace("\\", "/");
string prefix = "Assets/BundleAsset/";
string result = inputString.Replace(prefix, "");
return result.Replace(".bundle", "");
}
static void BuildAllAssetBundles() {
string prefabsFolderPath = "Assets/BundleAsset/Prefab";
if (!Directory.Exists(prefabsFolderPath)) {
Debug.LogError($"Folder {prefabsFolderPath} does not exist!");
return;
}
//AB包路径是ABundles
string rootPath = Application.dataPath.ToLower().Replace("assets", "") + "ABundles/webgl";
if (!Directory.Exists(rootPath)) {
Debug.LogError($"Folder {rootPath} does not exist!");
return;
}
string[] prefabGUIDs = AssetDatabase.FindAssets("t:Prefab", new[] { prefabsFolderPath });
foreach (var prefabGUID in prefabGUIDs) {
string prefabPath = AssetDatabase.GUIDToAssetPath(prefabGUID);
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
if (prefab == null) {
continue;
}
var assetPath = AssetDatabase.GetAssetPath(prefab);
var dependencies = GetAllDependencies(assetPath).ToArray();
var withoutEx = Path.GetFileNameWithoutExtension(prefabPath);
AssetBundleBuild assetBundleBuild = new AssetBundleBuild();
assetBundleBuild.assetBundleName = RemovePrefix(withoutEx).ToLower() + ".bundle";
assetBundleBuild.assetNames = dependencies;
var directName = Path.GetDirectoryName(assetPath);
var outPackagePath = $"{rootPath}/{RemovePrefix(directName).ToLower()}";
Debug.Log($"prefabPath {prefabPath}");
if (!Directory.Exists(outPackagePath)) {
Directory.CreateDirectory(outPackagePath);
}
BuildPipeline.BuildAssetBundles(outPackagePath, new AssetBundleBuild[] { assetBundleBuild }, BuildAssetBundleOptions.None, BuildTarget.WebGL);
}
Debug.Log("BuildAssetBundles ok");
}
public static List<string> GetAllDependencies(string assetPath) {
var list = new List<string>();
var dependencies = AssetDatabase.GetDependencies(assetPath, false);
foreach (var dependency in dependencies) {
if (Path.GetExtension(dependency) == ".cs" || Path.GetExtension(dependency) == ".meta" || Path.GetExtension(dependency) == ".DS_Store") {
continue;
}
list.Add(dependency);
}
list.Add(assetPath);
return list;
}
}
3.需要打包的场景添加到打包配置:
4.unity编辑器生成菜单:
5.场景加载AB包管理器:
using Cysharp.Threading.Tasks;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.SceneManagement;
using System.IO;
using UnityEngine.Networking;
using GLTFast;
using LitJson;
using System.Web;
public class SceneLoader : MonoBehaviour {
public int TemplateId;
public bool useBundle;
public bool isDeBug;
public bool isShowCase;
public bool isMobileTest;
[Header("天空盒材质球")]
public UnityEngine.Material skyboxMaterial;
bool sceneIsLoaded = false;
[DllImport("__Internal")]
private static extern string GetUA();
public virtual void Awake() {
#if !UNITY_EDITOR && UNITY_WEBGL
string a = GetUA();
if (a == "1")
{
//PC端
Debug.Log("当前运行环境在PC端");
PlayerData.Instance.isRunningPC = true;
}
if (a == "2")
{
//移动端
Debug.Log("当前运行环境在移动端");
PlayerData.Instance.isRunningPC = false;
}
#endif
#if UNITY_EDITOR
AppConst.UseAssetBundle = useBundle;
#endif
AppConst.useShowBundlePath = isShowCase;
DontDestroyOnLoad(gameObject);
EventManager.Instance.AddListener(EventName.LoadSceneAction, OnSceneLoad);
EventManager.Instance.AddListener(EventName.OnSceneCfgLoadEnd, RemoveUnuse);
}
public virtual void Start() {
var fps = transform.Find("FPS");
if (fps) {
fps.gameObject.SetActive(isDeBug);
}
if (isMobileTest) LoadNetCofig();
}
void LoadNetCofig() {
var configPath = Application.dataPath;
#if UNITY_EDITOR
var filepath = Path.Combine(Application.dataPath.Replace("Assets", ""), "config.txt");
#else
var filepath = Path.Combine(Application.dataPath, "config.txt");
#endif
Debug.Log("configPath" + filepath);
filepath = filepath.Replace("\\", "/");
StartCoroutine(LoadFileSetNetwork(filepath));
}
IEnumerator LoadFileSetNetwork(string filepath) {
UnityWebRequest www = UnityWebRequest.Get(filepath);
yield return www.SendWebRequest();
if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError) {
Debug.LogError(www.error);
}
else {
string json = www.downloadHandler.text;
var data = LitJson.JsonMapper.ToObject(json);
if ((string)data["AssetBundleIP"] != string.Empty) {
Host.AssetBundleIP = (string)data["AssetBundleIP"];
}
Host.gameServer = (string)data["local"];
Host.ApiHost = (string)data["ApiHost"];
Host.remote = (string)data["remote"];
Debug.Log("url config:" + json);
StartCoroutine(tempLoad());
}
}
public IEnumerator tempLoad() {
Debug.Log("OnBaelogin" + TemplateId);
var SceneName = TemplateId.ToString();
#if UNITY_EDITOR
if (AppConst.UseAssetBundle) {
yield return AssetBundleManager.Instance.LoadSceneSync(SceneName);
}
else {
yield return SceneManager.LoadSceneAsync(SceneName);
}
#else
yield return AssetBundleManager.Instance.LoadSceneSync(SceneName);
#endif
EventManager.Instance.TriggerEvent(EventName.OnSceneLoaded);
UIManager.Instance.PushPanel(UIPanelType.MAIN_PANEL); //这里有个坑, 如果把界面放在场景加载之前添加,会出现各种错误乱象
UIManager.Instance.PushPanel(UIPanelType.HUD_PANEL);
Debug.Log("DownLoadScenConfig");
if (HttpHelper.Instance != null) {
HttpHelper.Instance.GetDefaultSpaceImg();
HttpHelper.Instance.DownLoadScenConfig();
}
}
private void RemoveUnuse(object sender, EventArgs e) {
RemoveSceneUnUseDefault();
ResetSkyBox();
}
public void ResetSkyBox() {
JsonData sceneJson = JsonMapper.ToObject(SceneModel.Instance.sceneJsonInitData);
if (sceneJson["skyBox"] != null) {
string imgdata = sceneJson["skyBox"]["body"].ToString();
string decodedString = HttpUtility.UrlDecode(JsonMapper.ToObject(imgdata)["imgDatas"].ToString());
StartCoroutine(LoadTexturesAndGenerateCubemap(JsonMapper.ToObject<List<skyImgData>>(decodedString)));
}
}
private IEnumerator LoadTexturesAndGenerateCubemap(List<skyImgData> skyImgDataList) {
Texture2D[] textures = new Texture2D[skyImgDataList.Count];
Cubemap cubemap;
for (int i = 0; i < skyImgDataList.Count; i++) {
using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(skyImgDataList[i].url)) {
yield return www.SendWebRequest();
if (www.result == UnityWebRequest.Result.Success) {
Texture2D texture = DownloadHandlerTexture.GetContent(www);
textures[i] = texture;
}
else {
Debug.LogError("Failed to load image: " + www.error);
yield break;
}
}
}
Material material = new Material(skyboxMaterial);
material.SetTexture("_FrontTex", textures[0]);
material.SetTexture("_BackTex", textures[1]);
material.SetTexture("_LeftTex", textures[2]);
material.SetTexture("_RightTex", textures[3]);
material.SetTexture("_UpTex", textures[4]);
material.SetTexture("_DownTex", textures[5]);
RenderSettings.skybox = material;
}
/// <summary>
/// 移除场景默认设置的那些被删除的板
/// </summary>
public void RemoveSceneUnUseDefault() {
var comVOs = SceneModel.Instance.rootCfg.comCfg.comVOs;
var scene = SceneManager.GetActiveScene();
GameObject[] roots = scene.GetRootGameObjects();
foreach (GameObject root in roots) {
var loaders = root.GetComponentsInChildren<ComLoader>();
foreach (var loader in loaders) {
if (comVOs.TryGetValue(loader.instanceName, out _) == false) {
StartCoroutine(waitSeconds(loader.gameObject));
}
}
}
}
IEnumerator waitSeconds(GameObject go) {
yield return new WaitForEndOfFrame();
GameObject.Destroy(go);
}
IEnumerator coLoadSceneAsync() {
if (PlayerData.Instance.isRunningPC == false) {
yield return new WaitForSeconds(1f);
}
#if UNITY_EDITOR
if (SceneModel.Instance.useGlb == false) {
PlayerData.Instance.TemplateId = TemplateId;
}
#endif
var SceneName = "";
if (SceneModel.Instance.useGlb == true) {
SceneName = "1000";
}
else {
if (PlayerData.Instance.isRunningPC) {
SceneName = PlayerData.Instance.TemplateId.ToString();
}
else {
SceneName = PlayerData.Instance.TemplateId.ToString() + "_mobile";
}
}
Debug.Log("SceneName TemplateId:" + SceneName);
#if UNITY_EDITOR
if (AppConst.UseAssetBundle) {
yield return AssetBundleManager.Instance.LoadSceneSync(SceneName);
}
else {
yield return SceneManager.LoadSceneAsync(SceneName);
}
#else
yield return AssetBundleManager.Instance.LoadSceneSync(SceneName);
#endif
}
/// <summary>
/// 发布态场景加载完成
/// </summary>
/// <param name="arg0"></param>
/// <param name="arg1"></param>
private void OnPublishModeSceneLoadSuccess(Scene arg0, LoadSceneMode arg1) {
UIManager.Instance.PushPanel(UIPanelType.EDITOR_MODE_PANEL);
UIManager.Instance.PushPanel(UIPanelType.HUD_PANEL);
EventManager.Instance.TriggerEvent(EventName.OnSceneLoaded);
HttpHelper.Instance.GetDefaultSpaceImg();
SceneModel.Instance.setDefaultSceneConfig();
if (PlayerController.Instance.gameObject.GetComponent<RoleInfoUICtr>()) {
PlayerController.Instance.gameObject.GetComponent<RoleInfoUICtr>().publicModeForName();
PlayerController.Instance.gameObject.GetComponent<RoleInfoUICtr>().isShowOwnerObj(true);
}
if (SceneModel.Instance.useGlb) {
EventManager.Instance.TriggerEvent(EventName.onGlbSceneLoad, new GlbLoadEvenArg { url = SceneModel.Instance.glbPath });
}
}
public void OnSceneLoad(object sender, EventArgs e) {
if (sceneIsLoaded == true) {
return;
}
sceneIsLoaded = true;
var arg = e as SceneLoadActionArgs;
Debug.Log("OnSceneLoad:" + arg.state);
if (arg.state == AppConst.PublicMode) //创建态
{
SceneManager.sceneLoaded += OnPublishModeSceneLoadSuccess;
}
else { //浏览态
SceneManager.sceneLoaded += OnViewSceneLoadOk;
}
StartCoroutine(coLoadSceneAsync());
}
/// <summary>
/// 浏览态场景加载完成
/// </summary>
/// <param name="arg0"></param>
/// <param name="arg1"></param>
private void OnViewSceneLoadOk(Scene arg0, LoadSceneMode arg1) {
EventManager.Instance.TriggerEvent(EventName.OnSceneLoaded);
if (PlayerData.Instance.isRunningPC == true) {
UIManager.Instance.PushPanel(UIPanelType.HUD_PANEL);
}
//ToastPanel.Show("OnViewSceneLoadOk");
//AlertPanel.Show("OnViewSceneLoadOk", null);
//Debug.Log("DownLoadScenConfig");
//if (HttpHelper.Instance != null)
//{
// HttpHelper.Instance.GetDefaultSpaceImg();
// //HttpHelper.Instance.DownLoadScenConfig(); //挪到登陆的时候请求场景数据
//}
if (SceneModel.Instance.useGlb) {
EventManager.Instance.TriggerEvent(EventName.onGlbSceneLoad, new GlbLoadEvenArg { url = SceneModel.Instance.glbPath });
}
if (PlayerData.Instance.isRunningPC) {
SceneModel.Instance.ImplementComLoder();
UIManager.Instance.PushPanel(UIPanelType.MAIN_PANEL);
}
else {
if (SceneModel.Instance.useGlb) {
EventManager.Instance.AddListener(EventName.onGlbSceneLoadOK, (s, e) => {
StartCoroutine(waitSeconds(1, () => {
UIManager.Instance.PushPanel(UIPanelType.MAIN_PANEL);
}));
});
StartCoroutine(waitSeconds(1, () => {
if (SceneModel.Instance.useGlb) {
EventManager.Instance.TriggerEvent(EventName.onGlbSceneLoad, new GlbLoadEvenArg { url = SceneModel.Instance.glbPath });
}
}));
}
else {
StartCoroutine(waitSeconds(1, () => {
UIManager.Instance.PushPanel(UIPanelType.MAIN_PANEL);
}));
}
}
}
private IEnumerator waitSeconds(float scecond, Action call) {
yield return new WaitForSeconds(scecond);
call();
}
public virtual void Onlogin() {
}
}