1305 lines
50 KiB
C#
1305 lines
50 KiB
C#
using UnityEngine;
|
||
using UnityEditor;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Text;
|
||
using System;
|
||
using System.Text.RegularExpressions;
|
||
using UnityEngine.Rendering;
|
||
using LitJson;
|
||
|
||
namespace WeChatWASM
|
||
{
|
||
/// <summary>
|
||
/// 脚本调用的话可修改 Assets/WX-WASM-SDK/Editor/MiniGameConfig.asset配置,然后调用WXEditorWindow 的 DoExport方法导出小游戏
|
||
/// </summary>
|
||
public class WXEditorWindow : EditorWindow
|
||
{
|
||
|
||
string projectName = "";
|
||
string appid = "";
|
||
string cdn = "";
|
||
string videoUrl = "";
|
||
public static string dst = "";
|
||
string streamCDN = "";
|
||
int bundleHashLength = 32;
|
||
string bundlePathIdentifier = "StreamingAssets;";
|
||
string bundleExcludeExtensions = "json;";
|
||
string preloadFiles = ""; // 预下载文件名, 以,分隔文件
|
||
// string audioPrefix = "";
|
||
bool useAudioApi = false;
|
||
bool useFriendRelation = false;
|
||
bool developBuild = false;
|
||
bool autoProfile = false;
|
||
bool scriptOnly = false;
|
||
bool profilingFuncs = false;
|
||
bool profilingMemory = false;
|
||
bool deleteStreamingAssets = true;
|
||
int assetLoadType = 0; // 首包资源加载方式
|
||
bool webgl2 = false;
|
||
|
||
int orientation = 0;
|
||
|
||
static string SDKFilePath = "";
|
||
|
||
public static WXEditorScriptObject config;
|
||
|
||
public static string webglDir = "webgl"; //导出的webgl目录
|
||
public static string miniGameDir = "minigame"; // 生成小游戏的目录
|
||
public static string audioDir = "Assets"; //音频资源目录
|
||
public string codeMd5 = "";
|
||
public string dataMd5 = "";
|
||
public string dataFileSize = "";
|
||
public Texture tex;
|
||
public string defaultImgSrc = "Assets/WX-WASM-SDK/wechat-default/images/background.jpg";
|
||
public string bgImageSrc = "";
|
||
public int memorySize = 0;
|
||
public bool hideAfterCallMain = true;
|
||
|
||
public string dataFileSubPrefix = "";
|
||
public int maxStorage = 200;
|
||
public int defaultReleaseSize = 31457280;
|
||
public int texturesHashLength = 8;
|
||
public string texturesPath = "Assets/Textures";
|
||
public bool needCacheTextures = false;
|
||
public int loadingBarWidth = 240;
|
||
public bool needCheckUpdate = false;
|
||
|
||
[MenuItem("微信小游戏 / 转换小游戏", false, 1)]
|
||
public static void Open()
|
||
{
|
||
|
||
#if !(UNITY_2018_1_OR_NEWER)
|
||
UnityEngine.Debug.LogError("目前仅支持 Unity2018及以上的版本!");
|
||
#endif
|
||
var win = GetWindow(typeof(WXEditorWindow), false, "转换微信小游戏", true);//创建窗口
|
||
win.minSize = new Vector2(650, 800);
|
||
win.maxSize = new Vector2(1600, 950);
|
||
win.Show();
|
||
// 打开面板时自动检查更新
|
||
PluginUpdateManager.CheckUpdte();
|
||
Init();
|
||
}
|
||
|
||
public static void Init() {
|
||
|
||
PlayerSettings.WebGL.threadsSupport = false;
|
||
PlayerSettings.runInBackground = false;
|
||
|
||
PlayerSettings.WebGL.compressionFormat = WebGLCompressionFormat.Disabled;
|
||
#if UNITY_2020_1_OR_NEWER
|
||
PlayerSettings.WebGL.template = "PROJECT:WXTemplate2020";
|
||
#else
|
||
PlayerSettings.WebGL.template = "PROJECT:WXTemplate";
|
||
#endif
|
||
|
||
|
||
PlayerSettings.WebGL.linkerTarget = WebGLLinkerTarget.Wasm;
|
||
|
||
PlayerSettings.WebGL.dataCaching = false;
|
||
|
||
|
||
#if UNITY_2021_2_OR_NEWER
|
||
PlayerSettings.WebGL.debugSymbolMode = WebGLDebugSymbolMode.Embedded;
|
||
#else
|
||
PlayerSettings.WebGL.debugSymbols = true;
|
||
#endif
|
||
|
||
|
||
EditorSettings.spritePackerMode = SpritePackerMode.AlwaysOnAtlas;
|
||
|
||
}
|
||
|
||
public void OnEnable()
|
||
{
|
||
Init();
|
||
LoadData();
|
||
UpdateGraphicAPI();
|
||
}
|
||
|
||
|
||
public void LoadData() {
|
||
|
||
SDKFilePath = Path.Combine(Application.dataPath, "WX-WASM-SDK", "wechat-default", "unity-sdk", "index.js");
|
||
config = UnityUtil.GetEditorConf();
|
||
projectName = config.ProjectConf.projectName;
|
||
appid = config.ProjectConf.Appid;
|
||
cdn = config.ProjectConf.CDN;
|
||
assetLoadType = config.ProjectConf.assetLoadType;
|
||
videoUrl = config.ProjectConf.VideoUrl;
|
||
orientation = (int)config.ProjectConf.Orientation;
|
||
dst = config.ProjectConf.DST;
|
||
// streamCDN = config.ProjectConf.StreamCDN;
|
||
bundleHashLength = config.ProjectConf.bundleHashLength;
|
||
bundlePathIdentifier = config.ProjectConf.bundlePathIdentifier;
|
||
bundleExcludeExtensions = config.ProjectConf.bundleExcludeExtensions;
|
||
preloadFiles = config.ProjectConf.preloadFiles;
|
||
developBuild = config.CompileOptions.DevelopBuild;
|
||
autoProfile = config.CompileOptions.AutoProfile;
|
||
scriptOnly = config.CompileOptions.ScriptOnly;
|
||
profilingFuncs = config.CompileOptions.profilingFuncs;
|
||
profilingMemory = config.CompileOptions.ProfilingMemory;
|
||
deleteStreamingAssets = config.CompileOptions.DeleteStreamingAssets;
|
||
webgl2 = config.CompileOptions.Webgl2;
|
||
useAudioApi = config.SDKOptions.UseAudioApi;
|
||
// audioPrefix = config.ProjectConf.AssetsUrl;
|
||
useFriendRelation = config.SDKOptions.UseFriendRelation;
|
||
bgImageSrc = config.ProjectConf.bgImageSrc;
|
||
tex = AssetDatabase.LoadAssetAtPath<Texture>(bgImageSrc);
|
||
memorySize = config.ProjectConf.MemorySize;
|
||
hideAfterCallMain = config.ProjectConf.HideAfterCallMain;
|
||
|
||
// 不常用配置,先只通过MiniGameConfig.assets修改
|
||
dataFileSubPrefix = config.ProjectConf.dataFileSubPrefix;
|
||
maxStorage = config.ProjectConf.maxStorage;
|
||
defaultReleaseSize = config.ProjectConf.defaultReleaseSize;
|
||
texturesHashLength = config.ProjectConf.texturesHashLength;
|
||
texturesPath = config.ProjectConf.texturesPath;
|
||
needCacheTextures = config.ProjectConf.needCacheTextures;
|
||
loadingBarWidth = config.ProjectConf.loadingBarWidth;
|
||
needCheckUpdate = config.ProjectConf.needCheckUpdate;
|
||
}
|
||
|
||
private void OnFocus()
|
||
{
|
||
LoadData();
|
||
}
|
||
|
||
private void OnDisable()
|
||
{
|
||
EditorUtility.SetDirty(config);
|
||
}
|
||
|
||
private void OnLostFocus() {
|
||
|
||
config.ProjectConf.projectName = projectName;
|
||
config.ProjectConf.Appid = appid;
|
||
config.ProjectConf.CDN = cdn;
|
||
config.ProjectConf.assetLoadType = assetLoadType;
|
||
config.ProjectConf.VideoUrl = videoUrl;
|
||
config.ProjectConf.Orientation = (WXScreenOritation)orientation;
|
||
config.ProjectConf.DST = dst;
|
||
// config.ProjectConf.StreamCDN = streamCDN;
|
||
config.ProjectConf.bundleHashLength = bundleHashLength;
|
||
config.ProjectConf.bundlePathIdentifier = bundlePathIdentifier;
|
||
config.ProjectConf.bundleExcludeExtensions = bundleExcludeExtensions;
|
||
config.ProjectConf.preloadFiles = preloadFiles;
|
||
config.CompileOptions.DevelopBuild = developBuild;
|
||
config.CompileOptions.AutoProfile = autoProfile;
|
||
config.CompileOptions.ScriptOnly = scriptOnly;
|
||
config.CompileOptions.profilingFuncs = profilingFuncs;
|
||
config.CompileOptions.ProfilingMemory = profilingMemory;
|
||
config.CompileOptions.DeleteStreamingAssets = deleteStreamingAssets;
|
||
config.CompileOptions.Webgl2 = webgl2;
|
||
config.SDKOptions.UseAudioApi = useAudioApi;
|
||
// config.ProjectConf.AssetsUrl = audioPrefix;
|
||
config.SDKOptions.UseFriendRelation = useFriendRelation;
|
||
config.ProjectConf.bgImageSrc = bgImageSrc;
|
||
config.ProjectConf.MemorySize = memorySize;
|
||
config.ProjectConf.HideAfterCallMain = hideAfterCallMain;
|
||
|
||
config.ProjectConf.dataFileSubPrefix = dataFileSubPrefix;
|
||
config.ProjectConf.maxStorage = maxStorage;
|
||
config.ProjectConf.defaultReleaseSize = defaultReleaseSize;
|
||
config.ProjectConf.texturesHashLength = texturesHashLength;
|
||
config.ProjectConf.texturesPath = texturesPath;
|
||
config.ProjectConf.needCacheTextures = needCacheTextures;
|
||
config.ProjectConf.loadingBarWidth = loadingBarWidth;
|
||
config.ProjectConf.needCheckUpdate = needCheckUpdate;
|
||
}
|
||
|
||
|
||
static string[] GetScenePaths()
|
||
{
|
||
List<string> scenes = new List<string>();
|
||
for (int i = 0; i < EditorBuildSettings.scenes.Length; i++)
|
||
{
|
||
var scene = EditorBuildSettings.scenes[i];
|
||
UnityEngine.Debug.LogFormat("[Builder] Scenes [{0}]: {1}, [{2}]", i, scene.path, scene.enabled ? "x" : " ");
|
||
|
||
if (scene.enabled)
|
||
{
|
||
scenes.Add(scene.path);
|
||
}
|
||
}
|
||
|
||
return scenes.ToArray();
|
||
}
|
||
|
||
private int Build()
|
||
{
|
||
PlayerSettings.WebGL.emscriptenArgs = "";
|
||
PlayerSettings.runInBackground = false;
|
||
if (memorySize != 0)
|
||
{
|
||
if (memorySize >= 1024)
|
||
{
|
||
UnityEngine.Debug.LogErrorFormat($"memorySize必须小于1024,请查看GIT文档<a href=\"https://github.com/wechat-miniprogram/minigame-unity-webgl-transform/blob/main/Design/OptimizationMemory.md\">优化Unity WebGL的内存</a>");
|
||
return -1;
|
||
}
|
||
PlayerSettings.WebGL.emscriptenArgs += $" -s TOTAL_MEMORY={memorySize}MB";
|
||
}
|
||
if (profilingMemory)
|
||
{
|
||
PlayerSettings.WebGL.emscriptenArgs += " --memoryprofiler ";
|
||
}
|
||
if (profilingFuncs)
|
||
{
|
||
#if !(UNITY_2021_2_OR_NEWER)
|
||
PlayerSettings.WebGL.emscriptenArgs += " --profiling-funcs";
|
||
#else
|
||
PlayerSettings.WebGL.debugSymbolMode = WebGLDebugSymbolMode.Embedded;
|
||
#endif
|
||
}
|
||
|
||
|
||
UnityEngine.Debug.Log("[Builder] Starting to build WebGL project ... ");
|
||
|
||
UnityEngine.Debug.Log("PlayerSettings.WebGL.emscriptenArgs : "+ PlayerSettings.WebGL.emscriptenArgs);
|
||
|
||
// PlayerSettings.WebGL.memorySize = memorySize;
|
||
|
||
|
||
BuildOptions option = BuildOptions.None;
|
||
|
||
if (developBuild)
|
||
{
|
||
option |= BuildOptions.Development;
|
||
}
|
||
if (autoProfile)
|
||
{
|
||
option |= BuildOptions.ConnectWithProfiler;
|
||
}
|
||
|
||
if (scriptOnly)
|
||
{
|
||
option |= BuildOptions.BuildScriptsOnly;
|
||
}
|
||
|
||
|
||
if (EditorUserBuildSettings.activeBuildTarget != BuildTarget.WebGL)
|
||
{
|
||
UnityEngine.Debug.LogFormat("[Builder] Current target is: {0}, switching to: {1}", EditorUserBuildSettings.activeBuildTarget, BuildTarget.WebGL);
|
||
if (!EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.WebGL, BuildTarget.WebGL))
|
||
{
|
||
UnityEngine.Debug.LogFormat("[Builder] Switching to {0}/{1} failed!", BuildTargetGroup.WebGL, BuildTarget.WebGL);
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
var projDir = Path.Combine(dst, webglDir);
|
||
|
||
var result = BuildPipeline.BuildPlayer(GetScenePaths(), projDir, BuildTarget.WebGL, option);
|
||
if (result.summary.result != UnityEditor.Build.Reporting.BuildResult.Succeeded)
|
||
{
|
||
UnityEngine.Debug.LogFormat($"[Builder] BuildPlayer failed. emscriptenArgs:%s", PlayerSettings.WebGL.emscriptenArgs);
|
||
return -1;
|
||
}
|
||
|
||
UnityEngine.Debug.LogFormat("[Builder] Done: " + projDir);
|
||
return 0;
|
||
|
||
}
|
||
|
||
private static bool CopyDirectory(string SourcePath, string DestinationPath, bool overwriteexisting)
|
||
{
|
||
bool ret = false;
|
||
var separator = Path.DirectorySeparatorChar;
|
||
var ignoreFiles = new List<string>() { "unityNamespace.js" };
|
||
// eventEmitter - 改名为event-emitter
|
||
// loading和libs 是可交互视频用到的文件,先下掉可交互方案
|
||
var ignoreDirs = new List<string>() { "eventEmitter", "loading", "libs" };
|
||
try
|
||
{
|
||
|
||
if (Directory.Exists(SourcePath))
|
||
{
|
||
if (Directory.Exists(DestinationPath) == false)
|
||
{
|
||
Directory.CreateDirectory(DestinationPath);
|
||
} else
|
||
{
|
||
// 已经存在,删掉目录下无用的文件
|
||
foreach(string filename in ignoreFiles)
|
||
{
|
||
var filepath = Path.Combine(DestinationPath, filename);
|
||
if (File.Exists(filepath))
|
||
{
|
||
File.Delete(filepath);
|
||
}
|
||
}
|
||
foreach(string dir in ignoreDirs)
|
||
{
|
||
var dirpath = Path.Combine(DestinationPath, dir);
|
||
if (Directory.Exists(dirpath))
|
||
{
|
||
Directory.Delete(dirpath);
|
||
}
|
||
}
|
||
}
|
||
|
||
foreach (string fls in Directory.GetFiles(SourcePath))
|
||
{
|
||
|
||
FileInfo flinfo = new FileInfo(fls);
|
||
if (flinfo.Extension == ".meta" || ignoreFiles.Contains(flinfo.Name))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
flinfo.CopyTo(Path.Combine(DestinationPath, flinfo.Name), overwriteexisting);
|
||
|
||
|
||
|
||
|
||
}
|
||
foreach (string drs in Directory.GetDirectories(SourcePath))
|
||
{
|
||
DirectoryInfo drinfo = new DirectoryInfo(drs);
|
||
if (ignoreDirs.Contains(drinfo.Name))
|
||
{
|
||
continue;
|
||
}
|
||
if (CopyDirectory(drs, Path.Combine(DestinationPath, drinfo.Name), overwriteexisting) == false)
|
||
ret = false;
|
||
}
|
||
}
|
||
ret = true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
ret = false;
|
||
UnityEngine.Debug.LogError(ex);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
private static bool CopyMusicDirectory(string SourcePath, string DestinationPath, bool overwriteexisting)
|
||
{
|
||
bool ret = false;
|
||
try
|
||
{
|
||
|
||
if (Directory.Exists(SourcePath))
|
||
{
|
||
|
||
|
||
foreach (string fls in Directory.GetFiles(SourcePath))
|
||
{
|
||
|
||
FileInfo flinfo = new FileInfo(fls);
|
||
string[] suffix = { ".wav",".mp3", "m4a", "aac", "mp4" };
|
||
if (Array.IndexOf(suffix, flinfo.Extension.ToLower())>-1) {
|
||
UnityUtil.CreateDir(DestinationPath);
|
||
flinfo.CopyTo(Path.Combine(DestinationPath, flinfo.Name), overwriteexisting);
|
||
}
|
||
|
||
}
|
||
foreach (string drs in Directory.GetDirectories(SourcePath))
|
||
{
|
||
DirectoryInfo drinfo = new DirectoryInfo(drs);
|
||
if (CopyMusicDirectory(drs, Path.Combine(DestinationPath, drinfo.Name), overwriteexisting) == false)
|
||
ret = false;
|
||
}
|
||
}
|
||
ret = true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
ret = false;
|
||
UnityEngine.Debug.LogError(ex);
|
||
}
|
||
return ret;
|
||
|
||
}
|
||
|
||
private void ConvertCode()
|
||
{
|
||
|
||
UnityEngine.Debug.LogFormat("[Converter] Starting to adapt framewor. Dst: " + dst);
|
||
|
||
UnityUtil.DelectDir(Path.Combine(dst, miniGameDir));
|
||
|
||
#if UNITY_2020_1_OR_NEWER
|
||
string text = File.ReadAllText(Path.Combine(dst, webglDir, "Build", "webgl.framework.js"), Encoding.UTF8);
|
||
#else
|
||
string text = File.ReadAllText(Path.Combine(dst, webglDir, "Build", "webgl.wasm.framework.unityweb"), Encoding.UTF8);
|
||
#endif
|
||
int i;
|
||
for (i = 0; i < ReplaceRules.rules.Length; i++)
|
||
{
|
||
var rule = ReplaceRules.rules[i];
|
||
text = Regex.Replace(text, rule.old, rule.newStr);
|
||
}
|
||
if (PlayerSettings.WebGL.exceptionSupport == WebGLExceptionSupport.None)
|
||
{
|
||
Rule[] rules = {
|
||
new Rule()
|
||
{
|
||
old = "console.log\\(\"Exception at",
|
||
newStr= "if(Module.IsWxGame);console.log(\"Exception at"
|
||
},
|
||
new Rule()
|
||
{
|
||
old = "throw ptr",
|
||
newStr = "if(Module.IsWxGame)window.WXWASMSDK.WXUncaughtException(true);else throw ptr"
|
||
},
|
||
};
|
||
foreach (var rule in rules)
|
||
{
|
||
text = Regex.Replace(text, rule.old, rule.newStr);
|
||
}
|
||
}
|
||
if (text.Contains("UnityModule"))
|
||
{
|
||
text += ";GameGlobal.unityNamespace.UnityModule = UnityModule;";
|
||
}
|
||
else
|
||
{
|
||
if (text.StartsWith("(") && text.EndsWith(")"))
|
||
{
|
||
text = text.Substring(1, text.Length - 2);
|
||
}
|
||
text = "GameGlobal.unityNamespace.UnityModule = " + text;
|
||
}
|
||
|
||
if (!Directory.Exists(Path.Combine(dst, miniGameDir)))
|
||
{
|
||
Directory.CreateDirectory(Path.Combine(dst, miniGameDir));
|
||
}
|
||
|
||
File.WriteAllText(Path.Combine(dst, miniGameDir, "webgl.wasm.framework.unityweb.js"), text, new UTF8Encoding(false));
|
||
|
||
|
||
|
||
UnityEngine.Debug.LogFormat("[Converter] adapt framework done! ");
|
||
|
||
|
||
}
|
||
/// <summary>
|
||
/// 删掉导出目录webgl目录下旧资源包
|
||
/// </summary>
|
||
private void RemoveOldAssetPackage(string dstDir)
|
||
{
|
||
try
|
||
{
|
||
|
||
if (Directory.Exists(dstDir))
|
||
{
|
||
foreach (string path in Directory.GetFiles(dstDir))
|
||
{
|
||
FileInfo fileInfo = new FileInfo(path);
|
||
if (fileInfo.Name.Contains("webgl.data.unityweb.bin.txt"))
|
||
{
|
||
File.Delete(fileInfo.FullName);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
UnityEngine.Debug.LogError(ex);
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 等brotli之后,统计下资源包加brotli压缩后代码包是否超过了20M(小游戏代码分包总大小限制)
|
||
/// </summary>
|
||
private void checkNeedCopyDataPackage(bool brotliError)
|
||
{
|
||
// 如果brotli失败,使用CDN加载
|
||
if (brotliError) {
|
||
// brotli失败后,因为无法知道wasmcode大小,则得不到最终小游戏总包体大小。不能使用小游戏分包加载资源,还原成cdn的方式。
|
||
if (assetLoadType == 1) {
|
||
UnityEngine.Debug.LogWarning("brotli失败,无法检测文件大小,请上传资源文件到CDN");
|
||
assetLoadType = 0;
|
||
}
|
||
ShowNotification(new GUIContent("Brotli压缩失败,请到转出目录手动压缩!!!"));
|
||
}
|
||
if ((assetLoadType == 1))
|
||
{
|
||
#if UNITY_2020_1_OR_NEWER
|
||
var dataPath = Path.Combine(dst, webglDir, "Build", "webgl.data");
|
||
#else
|
||
var dataPath = Path.Combine(dst, webglDir, "Build", "webgl.data.unityweb");
|
||
#endif
|
||
var brcodePath = Path.Combine(dst, miniGameDir, "wasmcode", codeMd5 + ".webgl.wasm.code.unityweb.wasm.br");
|
||
var brcodeInfo = new FileInfo(brcodePath);
|
||
var brcodeSize = brcodeInfo.Length;
|
||
if (brcodeSize + int.Parse(dataFileSize) > 20971520)
|
||
{
|
||
ShowNotification(new GUIContent("资源文件过大,不适宜用代码分包加载"));
|
||
throw new Exception("资源文件过大,不适宜用代码分包加载");
|
||
} else
|
||
{
|
||
File.Copy(dataPath, Path.Combine(dst, miniGameDir, "data-package", dataMd5 + ".webgl.data.unityweb.bin.txt"), true);
|
||
}
|
||
}
|
||
var loadDataFromCdn = assetLoadType == 0;
|
||
Rule[] rules =
|
||
{
|
||
new Rule()
|
||
{
|
||
old="$DEPLOY_URL",
|
||
newStr= cdn
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$LOAD_DATA_FROM_SUBPACKAGE",
|
||
newStr = loadDataFromCdn ? "false" : "true"
|
||
}
|
||
};
|
||
string[] files = { "game.js", "game.json", "project.config.json" };
|
||
ReplaceFileContent(files, rules);
|
||
}
|
||
|
||
public int GenerateBinFile(bool isFromConvert = false)
|
||
{
|
||
UnityEngine.Debug.LogFormat("[Converter] Starting to genarate md5 and copy files");
|
||
|
||
#if UNITY_2020_1_OR_NEWER
|
||
var codePath = Path.Combine(dst, webglDir, "Build", "webgl.wasm");
|
||
#else
|
||
var codePath = Path.Combine(dst, webglDir, "Build", "webgl.wasm.code.unityweb");
|
||
#endif
|
||
codeMd5 = UnityUtil.BuildFileMd5(codePath);
|
||
|
||
#if UNITY_2020_1_OR_NEWER
|
||
var dataPath = Path.Combine(dst, webglDir, "Build", "webgl.data");
|
||
#else
|
||
var dataPath = Path.Combine(dst, webglDir, "Build", "webgl.data.unityweb");
|
||
#endif
|
||
dataMd5 = UnityUtil.BuildFileMd5(dataPath);
|
||
|
||
#if UNITY_2020_1_OR_NEWER
|
||
var symbolPath = Path.Combine(dst, webglDir, "Build", "webgl.symbols.json");
|
||
#else
|
||
var symbolPath = Path.Combine(dst, webglDir, "Build", "webgl.wasm.symbols.unityweb");
|
||
#endif
|
||
|
||
RemoveOldAssetPackage(Path.Combine(dst, webglDir));
|
||
RemoveOldAssetPackage(Path.Combine(dst, webglDir+"-min"));
|
||
|
||
File.Copy(dataPath, Path.Combine(dst, webglDir, dataMd5 + ".webgl.data.unityweb.bin.txt"), true);
|
||
|
||
CopyDirectory(Path.Combine(Application.dataPath, "WX-WASM-SDK", "wechat-default"), Path.Combine(dst, miniGameDir), true);
|
||
|
||
// FIX: 2021.2版本生成symbol有bug,导出时生成symbol报错,有symbol才copy
|
||
// 代码分包需要symbol文件以进行增量更新
|
||
if (File.Exists(symbolPath)) {
|
||
File.Copy(symbolPath, Path.Combine(dst, miniGameDir, "webgl.wasm.symbols.unityweb"), true);
|
||
}
|
||
|
||
var info = new FileInfo(dataPath);
|
||
dataFileSize = info.Length.ToString();
|
||
|
||
UnityEngine.Debug.LogFormat("[Converter] that to genarate md5 and copy files ended");
|
||
|
||
ModifyWeChatConfigs(isFromConvert);
|
||
|
||
ModifySDKFile();
|
||
|
||
ClearFriendRelationCode();
|
||
|
||
if (useAudioApi) {
|
||
CopyMusicDirectory(Application.dataPath, Path.Combine(dst, webglDir ,audioDir), true);
|
||
}
|
||
// 如果没有StreamingAssets目录,默认生成
|
||
if (!Directory.Exists(Path.Combine(dst, webglDir, "StreamingAssets"))) {
|
||
Directory.CreateDirectory(Path.Combine(dst, webglDir, "StreamingAssets"));
|
||
}
|
||
return Brotlib(codePath);
|
||
|
||
}
|
||
|
||
private void ModifySDKFile()
|
||
{
|
||
var config = UnityUtil.GetEditorConf();
|
||
string content = File.ReadAllText(SDKFilePath, Encoding.UTF8);
|
||
content = content.Replace("$unityVersion$", Application.unityVersion);
|
||
|
||
File.WriteAllText(Path.Combine(dst, miniGameDir, "unity-sdk", "index.js"), content, Encoding.UTF8);
|
||
|
||
content = File.ReadAllText(Path.Combine(Application.dataPath, "WX-WASM-SDK", "wechat-default", "unity-sdk", "storage.js"), Encoding.UTF8);
|
||
|
||
var PreLoadKeys = config.PlayerPrefsKeys.Count > 0 ? JsonMapper.ToJson(config.PlayerPrefsKeys) : "[]";
|
||
|
||
content = content.Replace("\"$PreLoadKeys\"", PreLoadKeys);
|
||
|
||
File.WriteAllText(Path.Combine(dst, miniGameDir, "unity-sdk", "storage.js"), content, Encoding.UTF8);
|
||
|
||
//修改纹理dxt
|
||
content = File.ReadAllText(Path.Combine(Application.dataPath, "WX-WASM-SDK", "wechat-default", "unity-sdk", "texture.js"), Encoding.UTF8);
|
||
|
||
content = content.Replace("\"$UseDXT5$\"", config.CompressTexture.useDXT5 ? "true" : "false");
|
||
|
||
File.WriteAllText(Path.Combine(dst, miniGameDir, "unity-sdk", "texture.js"), content, Encoding.UTF8);
|
||
|
||
}
|
||
|
||
class PreloadFile
|
||
{
|
||
public PreloadFile(string fn, string rp)
|
||
{
|
||
fileName = fn;
|
||
relativePath = rp;
|
||
}
|
||
public string fileName;
|
||
public string relativePath;
|
||
};
|
||
/// <summary>
|
||
/// 从webgl目录模糊搜索preloadfiles中的文件,作为预下载的列表
|
||
/// </summary>
|
||
private string GetPreloadList(string strPreloadfiles)
|
||
{
|
||
|
||
if (strPreloadfiles == "")
|
||
{
|
||
return "";
|
||
}
|
||
string preloadList = "";
|
||
var streamingAssetsPath = Path.Combine(dst, webglDir + "/StreamingAssets");
|
||
var fileNames = strPreloadfiles.Split(new char[] { ';' });
|
||
List<PreloadFile> preloadFiles = new List<PreloadFile>();
|
||
foreach(var fileName in fileNames)
|
||
{
|
||
if (fileName.Trim() == "") continue;
|
||
preloadFiles.Add(new PreloadFile(fileName, ""));
|
||
}
|
||
|
||
if (Directory.Exists(streamingAssetsPath))
|
||
{
|
||
foreach (string path in Directory.GetFiles(streamingAssetsPath, "*", SearchOption.AllDirectories))
|
||
{
|
||
FileInfo fileInfo = new FileInfo(path);
|
||
foreach (var preloadFile in preloadFiles)
|
||
{
|
||
if (fileInfo.Name.Contains(preloadFile.fileName))
|
||
{
|
||
// 相对于StreamingAssets的路径
|
||
var relativePath = path.Substring(streamingAssetsPath.Length + 1).Replace('\\', '/');
|
||
preloadFile.relativePath = relativePath;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
UnityEngine.Debug.LogError("没有找到StreamingAssets目录, 无法生成预下载列表");
|
||
}
|
||
foreach (var preloadFile in preloadFiles)
|
||
{
|
||
if (preloadFile.relativePath == "")
|
||
{
|
||
UnityEngine.Debug.LogError($"并非所有预下载的文件都被找到,剩余:{preloadFile.fileName}");
|
||
continue;
|
||
}
|
||
preloadList += ("\"" + preloadFile.relativePath + "\", \r");
|
||
}
|
||
return preloadList;
|
||
}
|
||
|
||
public string HandleLoadingImage()
|
||
{
|
||
var info = AssetDatabase.LoadAssetAtPath<Texture>(bgImageSrc);
|
||
var oldFilename = Path.GetFileName(defaultImgSrc);
|
||
var newFilename = Path.GetFileName(bgImageSrc);
|
||
if (bgImageSrc != defaultImgSrc)
|
||
{
|
||
// 图片宽高不能超过2048
|
||
if (info.width > 2048 || info.height > 2048)
|
||
{
|
||
throw new Exception("封面图宽高不可超过2048");
|
||
}
|
||
File.Delete(Path.Combine(dst, miniGameDir, "images", oldFilename));
|
||
File.Copy(bgImageSrc, Path.Combine(dst, miniGameDir, "images", newFilename), true);
|
||
return "images/" + Path.GetFileName(bgImageSrc);
|
||
} else
|
||
{
|
||
return "images/" + Path.GetFileName(defaultImgSrc);
|
||
}
|
||
}
|
||
|
||
public void ModifyWeChatConfigs(bool isFromConvert = false)
|
||
{
|
||
UnityEngine.Debug.LogFormat("[Converter] Starting to modify configs");
|
||
|
||
var config = UnityUtil.GetEditorConf();
|
||
|
||
var PRELOAD_LIST = GetPreloadList(preloadFiles);
|
||
var imgSrc = HandleLoadingImage();
|
||
|
||
var bundlePathIdentifierStr = GetArrayString(bundlePathIdentifier);
|
||
var excludeFileExtensionsStr = GetArrayString(bundleExcludeExtensions);
|
||
|
||
var screenOrientation = new List<string>(){"portrait", "landscape", "landscapeLeft", "landscapeRight"}[orientation];
|
||
|
||
Rule[] replaceArrayList =
|
||
{
|
||
new Rule()
|
||
{
|
||
old="$GAME_NAME",
|
||
newStr="webgl"
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$PROJECT_NAME",
|
||
newStr=projectName == "" ? "webgl" : projectName,
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$APP_ID",
|
||
newStr=appid
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$ORIENTATION",
|
||
newStr=screenOrientation
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$LOADING_VIDEO_URL",
|
||
newStr=videoUrl
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$CODE_MD5",
|
||
newStr=codeMd5
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$DATA_MD5",
|
||
newStr=dataMd5
|
||
},
|
||
// new Rule()
|
||
// {
|
||
// old="$DATA_FILE_SIZE",
|
||
// newStr=dataFileSize
|
||
// },
|
||
new Rule()
|
||
{
|
||
old="$STREAM_CDN",
|
||
newStr=streamCDN
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$AUDIO_PREFIX",
|
||
newStr=cdn + "/Assets"
|
||
},
|
||
|
||
new Rule()
|
||
{
|
||
old="\"$PRELOAD_LIST\"",
|
||
newStr=PRELOAD_LIST
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$BACKGROUND_IMAGE",
|
||
newStr=imgSrc
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$HIDE_AFTER_CALLMAIN",
|
||
newStr = hideAfterCallMain ? "true" : "false"
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$BUNDLE_HASH_LENGTH",
|
||
newStr=bundleHashLength.ToString()
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$BUNDLE_PATH_IDENTIFIER",
|
||
newStr=bundlePathIdentifierStr
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$EXCLUDE_FILE_EXTENSIONS",
|
||
newStr=excludeFileExtensionsStr
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$WEBGL_VERSION",
|
||
newStr=webgl2? "2" : "1"
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$UNITY_VERSION",
|
||
newStr=Application.unityVersion
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$PLUGIN_VERSION",
|
||
newStr=WXPluginVersion.pluginVersion
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$DATA_FILE_SUB_PREFIX",
|
||
newStr=dataFileSubPrefix
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$MAX_STORAGE_SIZE",
|
||
newStr=maxStorage.ToString()
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$DEFAULT_RELEASE_SIZE",
|
||
newStr=defaultReleaseSize.ToString()
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$TEXTURE_HASH_LENGTH",
|
||
newStr=texturesHashLength.ToString()
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$TEXTURES_PATH",
|
||
newStr=texturesPath
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$NEED_CACHE_TEXTURES",
|
||
newStr=needCacheTextures ? "true" : "false"
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$LOADING_BAR_WIDTH",
|
||
newStr=loadingBarWidth.ToString()
|
||
},
|
||
new Rule()
|
||
{
|
||
old="$NEED_CHECK_UPDATE",
|
||
newStr=needCheckUpdate ? "true" : "false"
|
||
}
|
||
};
|
||
|
||
List<Rule> replaceList = new List<Rule>(replaceArrayList);
|
||
List<string> files = new List<string> { "game.js", "game.json", "project.config.json", "unity-namespace.js" };
|
||
|
||
|
||
|
||
ReplaceFileContent(files.ToArray(), replaceList.ToArray());
|
||
|
||
|
||
|
||
|
||
UnityEngine.Debug.LogFormat("[Converter] that to modify configs ended");
|
||
|
||
|
||
|
||
}
|
||
/// <summary>
|
||
/// 对文件做内容替换
|
||
/// </summary>
|
||
/// <param name="files"></param>
|
||
/// <param name="replaceList"></param>
|
||
public void ReplaceFileContent(string[] files, Rule[] replaceList)
|
||
{
|
||
if (files.Length != 0 && replaceList.Length != 0)
|
||
{
|
||
for (int i = 0; i < files.Length; i++)
|
||
{
|
||
var filePath = Path.Combine(dst, miniGameDir, files[i]);
|
||
string text = File.ReadAllText(filePath, Encoding.UTF8);
|
||
for (int j = 0; j < replaceList.Length; j++)
|
||
{
|
||
var rule = replaceList[j];
|
||
text = text.Replace(rule.old, rule.newStr);
|
||
}
|
||
File.WriteAllText(filePath, text, new UTF8Encoding(false));
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 按;分隔字符串,将分隔后每一项作为字符串用,连接
|
||
/// eg: input "i1;i2;i3" => output: `"i1", "i2", "i3"`
|
||
/// </summary>
|
||
/// <param name="inp"></param>
|
||
public string GetArrayString(string inp) {
|
||
var result = "";
|
||
var iterms = new List<string>(inp.Split(new char[] {';'}));
|
||
iterms.ForEach((iterm) => {
|
||
if (!string.IsNullOrEmpty(iterm.Trim())) {
|
||
result += ("\"" + iterm.Trim() + "\", ");
|
||
}
|
||
});
|
||
if (!string.IsNullOrEmpty(result)) {
|
||
result = result.Substring(0, result.Length - 2);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
private int Brotlib(string filePath)
|
||
{
|
||
UnityEngine.Debug.LogFormat("[Converter] Starting to generate Brotlib file");
|
||
|
||
|
||
var exePath = "";
|
||
var path = "";
|
||
#if UNITY_EDITOR_OSX
|
||
exePath = Path.Combine(Application.dataPath, "WX-WASM-SDK/Editor/Brotli/macos/brotli");
|
||
#else
|
||
exePath = Path.Combine(Application.dataPath, "WX-WASM-SDK/Editor/Brotli/win_x86_64/brotli.exe");
|
||
#endif
|
||
var dstPath = Path.Combine(dst, miniGameDir, "wasmcode", codeMd5 + ".webgl.wasm.code.unityweb.wasm.br");
|
||
WeChatWASM.UnityUtil.RunCmd(exePath, string.Format($" --force --quality 11" +
|
||
$" --input {filePath}" +
|
||
$" --output {dstPath}"), path);
|
||
return 0;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 如果没有使用好友关系链的话,自动删掉无用代码
|
||
/// </summary>
|
||
private void ClearFriendRelationCode()
|
||
{
|
||
if (!useFriendRelation)
|
||
{
|
||
var filePath = Path.Combine(dst, miniGameDir, "game.json");
|
||
|
||
string content = File.ReadAllText(filePath, Encoding.UTF8);
|
||
content = content.Replace("\"openDataContext\": \"open-data\",", "");
|
||
File.WriteAllText(filePath, content);
|
||
|
||
string openDataDir = Path.Combine(dst, miniGameDir, "open-data");
|
||
|
||
UnityUtil.DelectDir(openDataDir);
|
||
|
||
Directory.Delete(openDataDir, true);
|
||
}
|
||
|
||
}
|
||
|
||
public static void DrawProObjectField<T>(
|
||
GUIContent label,
|
||
SerializedProperty value,
|
||
Type objType,
|
||
GUIStyle style,
|
||
bool allowSceneObjects,
|
||
Texture objIcon = null) where T : UnityEngine.Object
|
||
{
|
||
|
||
T tObj = value.objectReferenceValue as T;
|
||
|
||
if (objIcon == null)
|
||
{
|
||
objIcon = EditorGUIUtility.FindTexture("PrefabNormal Icon");
|
||
}
|
||
style.imagePosition = ImagePosition.ImageLeft;
|
||
|
||
int pickerID = 455454425;
|
||
|
||
if (tObj != null)
|
||
{
|
||
EditorGUILayout.LabelField(label,
|
||
new GUIContent(tObj.name, objIcon), style);
|
||
}
|
||
|
||
if (GUILayout.Button("Select"))
|
||
{
|
||
EditorGUIUtility.ShowObjectPicker<T>(
|
||
tObj, allowSceneObjects, "", pickerID);
|
||
|
||
}
|
||
if (Event.current.commandName == "ObjectSelectorUpdated")
|
||
{
|
||
if (EditorGUIUtility.GetObjectPickerControlID() == pickerID)
|
||
{
|
||
tObj = EditorGUIUtility.GetObjectPickerObject() as T;
|
||
value.objectReferenceValue = tObj;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
private void OnGUI()
|
||
{
|
||
var labelStyle = new GUIStyle(EditorStyles.boldLabel);
|
||
labelStyle.fontSize = 14;
|
||
|
||
labelStyle.margin.left = 20;
|
||
labelStyle.margin.top = 10;
|
||
labelStyle.margin.bottom = 10;
|
||
|
||
GUILayout.Label("基本设置", labelStyle);
|
||
|
||
var inputStyle = new GUIStyle(EditorStyles.textField);
|
||
inputStyle.fontSize = 14;
|
||
inputStyle.margin.left = 20;
|
||
inputStyle.margin.bottom = 10;
|
||
inputStyle.margin.right = 20;
|
||
|
||
var intPopupStyle = new GUIStyle(EditorStyles.popup);
|
||
intPopupStyle.fontSize = 14;
|
||
intPopupStyle.margin.left = 20;
|
||
intPopupStyle.margin.bottom = 15;
|
||
intPopupStyle.margin.right = 20;
|
||
|
||
appid = EditorGUILayout.TextField("游戏appid", appid, inputStyle);
|
||
cdn = EditorGUILayout.TextField("游戏资源CDN", cdn, inputStyle);
|
||
projectName = EditorGUILayout.TextField("小游戏项目名", projectName, inputStyle);
|
||
orientation = EditorGUILayout.IntPopup("游戏方向", orientation, new[] { "Portrait", "Landscape", "LandscapeLeft", "LandscapeRight" }, new[] { 0, 1, 2, 3 }, intPopupStyle);
|
||
var totalMemoryFieldDesc = new GUIContent("最大内存(MB)", "预留的初始内存值,需评估游戏最大内存峰值进行设置,消除内存自动增长带来的峰值尖刺。请查看GIT文档<优化Unity WebGL的内存>");
|
||
memorySize = EditorGUILayout.IntField(totalMemoryFieldDesc, memorySize, inputStyle);
|
||
|
||
GUILayout.Label("导出路径", labelStyle);
|
||
|
||
var choosePathButtonClicked = false;
|
||
var openTargetButtonClicked = false;
|
||
var resetButtonClicked = false;
|
||
|
||
if (dst == "")
|
||
{
|
||
GUIStyle pathButtonStyle = new GUIStyle(GUI.skin.button);
|
||
pathButtonStyle.fontSize = 12;
|
||
pathButtonStyle.margin.left = 20;
|
||
|
||
choosePathButtonClicked = GUILayout.Button("选择导出路径", pathButtonStyle, GUILayout.Height(30), GUILayout.Width(200));
|
||
}
|
||
else
|
||
{
|
||
|
||
int pathButtonHeight = 28;
|
||
GUIStyle pathLabelStyle = new GUIStyle(GUI.skin.textField);
|
||
pathLabelStyle.fontSize = 12;
|
||
pathLabelStyle.alignment = TextAnchor.MiddleLeft;
|
||
pathLabelStyle.margin.top = 6;
|
||
pathLabelStyle.margin.bottom = 6;
|
||
pathLabelStyle.margin.left = 20;
|
||
|
||
GUILayout.BeginHorizontal();
|
||
// 路径框
|
||
GUILayout.Label(dst, pathLabelStyle, GUILayout.Height(pathButtonHeight - 6), GUILayout.ExpandWidth(true), GUILayout.MaxWidth(EditorGUIUtility.currentViewWidth - 126));
|
||
openTargetButtonClicked = GUILayout.Button("打开", GUILayout.Height(pathButtonHeight), GUILayout.Width(40));
|
||
resetButtonClicked = GUILayout.Button("重选", GUILayout.Height(pathButtonHeight), GUILayout.Width(40));
|
||
GUILayout.EndHorizontal();
|
||
}
|
||
EditorGUILayout.Space();
|
||
|
||
GUILayout.Label("启动Loader设置", labelStyle);
|
||
EditorGUILayout.BeginHorizontal();
|
||
GUILayout.Space(20);
|
||
tex = (Texture)EditorGUILayout.ObjectField("启动背景图/视频封面", tex, typeof(Texture2D), false);
|
||
var currentBgSrc = AssetDatabase.GetAssetPath(tex);
|
||
TextureImporter texInfo = (TextureImporter)AssetImporter.GetAtPath(currentBgSrc);
|
||
if (!string.IsNullOrEmpty(currentBgSrc) && currentBgSrc != bgImageSrc)
|
||
{
|
||
bgImageSrc = currentBgSrc;
|
||
var config = UnityUtil.GetEditorConf();
|
||
config.ProjectConf.bgImageSrc = bgImageSrc;
|
||
EditorUtility.SetDirty(config);
|
||
AssetDatabase.SaveAssets();
|
||
}
|
||
GUILayout.Space(20);
|
||
EditorGUILayout.EndHorizontal();
|
||
|
||
videoUrl = EditorGUILayout.TextField("加载阶段视频url", videoUrl, inputStyle);
|
||
|
||
var optionsList = new List<GUIContent>();
|
||
optionsList.Add(new GUIContent("CDN"));
|
||
optionsList.Add(new GUIContent("小游戏分包"));
|
||
GUIContent assetLoadTypeLabel = new GUIContent("首包资源加载方式", "选择'CDN'通过传统CDN加载资源。选择'小游戏分包'通过小游戏代码分包加载资源。小游戏分包有总大小20M限制,若资源加代码总大小超过20M,会自动切换为传统CDN加载");
|
||
|
||
assetLoadType = EditorGUILayout.IntPopup(assetLoadTypeLabel, assetLoadType, optionsList.ToArray(), new[] { 0, 1 }, intPopupStyle);
|
||
|
||
// audioPrefix = EditorGUILayout.TextField("Assets目录对应CDN地址", audioPrefix, inputStyle);
|
||
|
||
// memorySize = EditorGUILayout.IntField("游戏内存大小(MB)", memorySize, inputStyle);
|
||
|
||
// EditorGUILayout.Space();
|
||
|
||
// GUILayout.Label("AssetBundle缓存配置", labelStyle);
|
||
|
||
// streamCDN = EditorGUILayout.TextField("Bundle包CDN地址", streamCDN, inputStyle);
|
||
// var bundlePathFieldDesc = new GUIContent("路径标识符(;分隔)", "下载路径中包含标识符可判定为下载Bundle,可自动缓存。默认值StreamingAssets");
|
||
// bundlePathIdentifier = EditorGUILayout.TextField(bundlePathFieldDesc, bundlePathIdentifier, inputStyle);
|
||
|
||
var bundleExcludeExtensionsFieldDesc = new GUIContent("不自动缓存文件类型(;分隔)", "当请求url包含资源'cdn+StreamingAssets'时会自动缓存,但StreamingAssets目录下不是所有文件都需缓存,此选项配置不需要自动缓存的文件拓展名。默认值json");
|
||
bundleExcludeExtensions = EditorGUILayout.TextField(bundleExcludeExtensionsFieldDesc, bundleExcludeExtensions, inputStyle);
|
||
|
||
var bundleHashLengthFieldDesc = new GUIContent("Bundle名中Hash长度", "自定义Bundle文件名中hash部分长度,默认值32,用于缓存控制。");
|
||
bundleHashLength = EditorGUILayout.IntField(bundleHashLengthFieldDesc, bundleHashLength, inputStyle);
|
||
|
||
EditorGUILayout.Space();
|
||
|
||
GUILayout.Label("预下载选项", labelStyle);
|
||
GUILayout.BeginHorizontal();
|
||
preloadFiles = EditorGUILayout.TextField("文件列表(;间隔,模糊匹配)", preloadFiles, inputStyle);
|
||
|
||
GUILayout.EndHorizontal();
|
||
|
||
EditorGUILayout.Space();
|
||
|
||
GUIStyle toggleStyle = new GUIStyle(GUI.skin.toggle);
|
||
toggleStyle.margin.left = 20;
|
||
toggleStyle.margin.right = 20;
|
||
|
||
GUILayout.Label("SDK功能选项", labelStyle);
|
||
GUILayout.BeginHorizontal();
|
||
useFriendRelation = GUILayout.Toggle(useFriendRelation, "使用好友关系链", toggleStyle);
|
||
useAudioApi = GUILayout.Toggle(useAudioApi, "使用微信音频API", toggleStyle);
|
||
GUILayout.EndHorizontal();
|
||
EditorGUILayout.Space();
|
||
|
||
|
||
|
||
|
||
EditorGUILayout.Space();
|
||
EditorGUILayout.Space();
|
||
|
||
GUILayout.Label("调试编译选项", labelStyle);
|
||
GUILayout.BeginHorizontal();
|
||
|
||
developBuild = GUILayout.Toggle(developBuild, "Development Build",toggleStyle);
|
||
autoProfile = GUILayout.Toggle(autoProfile, "Autoconnect Profiler", toggleStyle);
|
||
scriptOnly = GUILayout.Toggle(scriptOnly, "Scripts Only Build", toggleStyle);
|
||
|
||
GUILayout.EndHorizontal();
|
||
GUILayout.BeginHorizontal();
|
||
|
||
profilingFuncs = GUILayout.Toggle(profilingFuncs, "Profiling Funcs ", toggleStyle);
|
||
profilingMemory = GUILayout.Toggle(profilingMemory, "Profiling Memory ", toggleStyle);
|
||
|
||
|
||
var oldwebgl2 = webgl2;
|
||
webgl2 = GUILayout.Toggle(webgl2, "WebGL2.0(beta)", toggleStyle);
|
||
if (oldwebgl2 != webgl2) UpdateGraphicAPI();
|
||
GUILayout.EndHorizontal();
|
||
EditorGUILayout.Space();
|
||
|
||
deleteStreamingAssets = GUILayout.Toggle(deleteStreamingAssets, "ClearStreamingAssets", toggleStyle);
|
||
|
||
|
||
GUIStyle exportButtonStyle = new GUIStyle(GUI.skin.button);
|
||
exportButtonStyle.fontSize = 14;
|
||
exportButtonStyle.margin.left = 20;
|
||
exportButtonStyle.margin.top = 40;
|
||
|
||
EditorGUILayout.BeginHorizontal();
|
||
|
||
|
||
var isExportBtnPressed = GUILayout.Button("导出WEBGL并转换为小游戏(常用)", exportButtonStyle, GUILayout.Height(40), GUILayout.Width(EditorGUIUtility.currentViewWidth - 270));
|
||
|
||
var isConvertBtnPressed = GUILayout.Button("将WEBGL转为小游戏(不常用)", exportButtonStyle, GUILayout.Height(40), GUILayout.Width(210));
|
||
|
||
EditorGUILayout.EndHorizontal();
|
||
|
||
|
||
if (isExportBtnPressed)
|
||
{
|
||
|
||
DoExport(true);
|
||
|
||
}
|
||
|
||
if (isConvertBtnPressed)
|
||
{
|
||
DoExport(false);
|
||
}
|
||
|
||
if (choosePathButtonClicked)
|
||
{
|
||
// 弹出选目录窗口
|
||
var dstPath = EditorUtility.SaveFolderPanel("选择你的游戏导出目录", "", "");
|
||
|
||
if (dstPath != "")
|
||
{
|
||
dst = dstPath;
|
||
OnLostFocus();
|
||
}
|
||
|
||
|
||
}
|
||
|
||
if (openTargetButtonClicked)
|
||
{
|
||
UnityUtil.ShowInExplorer(dst);
|
||
}
|
||
if (resetButtonClicked)
|
||
{
|
||
dst = "";
|
||
}
|
||
|
||
|
||
EditorGUILayout.Space();
|
||
|
||
}
|
||
|
||
private void UpdateGraphicAPI()
|
||
{
|
||
PlayerSettings.SetUseDefaultGraphicsAPIs(BuildTarget.WebGL, false);
|
||
|
||
GraphicsDeviceType[] targets = new GraphicsDeviceType[] { };
|
||
if (webgl2)
|
||
{
|
||
PlayerSettings.SetGraphicsAPIs(BuildTarget.WebGL, new GraphicsDeviceType[] { GraphicsDeviceType.OpenGLES3 });
|
||
}
|
||
else
|
||
{
|
||
PlayerSettings.SetGraphicsAPIs(BuildTarget.WebGL, new GraphicsDeviceType[] { GraphicsDeviceType.OpenGLES2 });
|
||
}
|
||
}
|
||
|
||
// 可以调用这个来集成
|
||
public void DoExport(bool buildWebGL) {
|
||
|
||
OnLostFocus();
|
||
EditorUtility.SetDirty(config);
|
||
AssetDatabase.SaveAssets();
|
||
|
||
if (dst == "")
|
||
{
|
||
ShowNotification(new GUIContent("请先选择游戏导出路径"));
|
||
}
|
||
else
|
||
{
|
||
|
||
#if UNITY_EDITOR_OSX
|
||
// MacSetAuth();
|
||
#endif
|
||
//仅删除StreamingAssets目录
|
||
if (deleteStreamingAssets)
|
||
{
|
||
UnityUtil.DelectDir(Path.Combine(dst, webglDir + "/StreamingAssets"));
|
||
}
|
||
|
||
if (buildWebGL && Build() != 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
ConvertCode();
|
||
|
||
int res = GenerateBinFile();
|
||
if (res == 0)
|
||
{
|
||
checkNeedCopyDataPackage(false);
|
||
UnityEngine.Debug.LogFormat("[Converter] All done!");
|
||
ShowNotification(new GUIContent("转换完成"));
|
||
}
|
||
else
|
||
{
|
||
checkNeedCopyDataPackage(true);
|
||
}
|
||
|
||
// 如果是2021版本,官方symbols产生有BUG,这里需要用工具将embedded的函数名提取出来
|
||
#if UNITY_2021_2_OR_NEWER
|
||
var path = "Assets/WX-WASM-SDK/Editor/Node";
|
||
var nodePath = "node";
|
||
#if UNITY_EDITOR_OSX
|
||
nodePath = "/usr/local/bin/node";
|
||
#endif
|
||
WeChatWASM.UnityUtil.RunCmd(nodePath, string.Format($"--experimental-modules dump_wasm_symbol.mjs {dst}"), path);
|
||
UnityEngine.Debug.LogError($"Unity 2021版本使用Embeded Symbols, 代码包中含有函数名体积较大, 发布前<a href=\"https://github.com/wechat-miniprogram/minigame-unity-webgl-transform/blob/main/Design/WasmSplit.md\">使用代码分包工具</a>进行优化");
|
||
#endif
|
||
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
}
|