feat: support asset bundle
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace OCES.Editor
|
||||
{
|
||||
public static class AssetBundleBuilder
|
||||
{
|
||||
static string BuildBundle(string bundleName, string outputDir, BuildTarget buildTarget, params string[] sourceDirs)
|
||||
{
|
||||
// 1. 收集所有文件(递归)
|
||||
List<string> assetNames = new();
|
||||
List<string> addressableNames = new();
|
||||
|
||||
foreach (string dir in sourceDirs)
|
||||
{
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
Debug.LogWarning($"[AssetBundleBuilder] 目录不存在,跳过: {dir}");
|
||||
continue;
|
||||
}
|
||||
|
||||
string[] files = Directory.GetFiles(dir, "*.*", SearchOption.AllDirectories);
|
||||
foreach (string file in files)
|
||||
{
|
||||
if (file.EndsWith(".meta")) continue;
|
||||
if (file.EndsWith(".DS_Store")) continue;
|
||||
if (file.StartsWith("._")) continue;
|
||||
if (file.EndsWith(".pkf")) continue;
|
||||
|
||||
string assetPath = file.Replace("\\", "/");
|
||||
assetNames.Add(assetPath);
|
||||
|
||||
string relative = assetPath.Replace("Assets/Resources/", "");
|
||||
string withoutExt = Path.ChangeExtension(relative, null);
|
||||
addressableNames.Add(withoutExt);
|
||||
}
|
||||
}
|
||||
|
||||
if (assetNames.Count == 0)
|
||||
{
|
||||
return $"[AssetBundleBuilder] {bundleName}: 无文件";
|
||||
}
|
||||
Directory.CreateDirectory(outputDir);
|
||||
|
||||
// 2. 构建
|
||||
AssetBundleBuild build = new()
|
||||
{
|
||||
assetBundleName = bundleName + ".ab",
|
||||
assetNames = assetNames.ToArray(),
|
||||
addressableNames = addressableNames.ToArray()
|
||||
};
|
||||
|
||||
AssetBundleManifest manifest = BuildPipeline.BuildAssetBundles(
|
||||
outputDir,
|
||||
new[] { build },
|
||||
BuildAssetBundleOptions.None,
|
||||
buildTarget);
|
||||
|
||||
return !manifest ? $"[{bundleName}.ab] 构建失败"
|
||||
: $"[AssetBundleBuilder] {bundleName}.ab 构建完成,包含 {assetNames.Count} 个资源";
|
||||
|
||||
}
|
||||
|
||||
internal static string BuildBundles(
|
||||
bool buildAudio, string audioBundlePath,
|
||||
bool buildHaptic, string hapticBundlePath,
|
||||
BuildTarget buildTarget)
|
||||
{
|
||||
string log = "";
|
||||
|
||||
if (buildAudio)
|
||||
log += BuildBundleFromPath(audioBundlePath, buildTarget,
|
||||
"Assets/Resources/Audios",
|
||||
"Assets/Resources/AudioData") + "\n";
|
||||
|
||||
if (buildHaptic)
|
||||
log += BuildBundleFromPath(hapticBundlePath, buildTarget,
|
||||
"Assets/Resources/Haptics",
|
||||
"Assets/Resources/HapticData") + "\n";
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
return log.TrimEnd('\n');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据配置中的相对路径构建单个 Bundle。
|
||||
/// </summary>
|
||||
/// <param name="relativePath">配置中的路径,如 "Bundles/audios.ab"</param>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="sourceDirs"></param>
|
||||
public static string BuildBundleFromPath(
|
||||
string relativePath, BuildTarget target, params string[] sourceDirs)
|
||||
{
|
||||
// 解析路径 → 输出目录 + Bundle 名
|
||||
string fullPath = Path.Combine(Application.streamingAssetsPath, relativePath);
|
||||
string outputDir = Path.GetDirectoryName(fullPath);
|
||||
string bundleName = Path.GetFileNameWithoutExtension(fullPath);
|
||||
|
||||
return string.IsNullOrEmpty(bundleName)
|
||||
? $"[AssetBundleBuilder] 无效路径: {relativePath}"
|
||||
: BuildBundle(bundleName, outputDir, target, sourceDirs);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c370f95cedb246969a5831a5bda067c2
|
||||
timeCreated: 1778828259
|
||||
@@ -0,0 +1,131 @@
|
||||
using System.Linq;
|
||||
using OCES.Audio;
|
||||
using OCES.Haptic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace OCES.Editor
|
||||
{
|
||||
public class AssetBundleBuilderWindow : EditorWindow
|
||||
{
|
||||
bool m_buildAudio = true;
|
||||
bool m_buildHaptic = true;
|
||||
int m_targetIndex;
|
||||
string m_audioBundleSourcePath;
|
||||
string m_hapticBundleSourcePath;
|
||||
|
||||
string m_log = "";
|
||||
Vector2 m_scrollPos;
|
||||
|
||||
// Settings 资源路径
|
||||
const string k_audioSettingsPath = "Assets/Settings/AudioExtendSettings.asset";
|
||||
const string k_hapticSettingsPath = "Assets/Settings/HapticSettings.asset";
|
||||
|
||||
static readonly (BuildTarget target, string label)[] s_platforms =
|
||||
{
|
||||
(BuildTarget.Android, "Android"),
|
||||
(BuildTarget.iOS, "iOS"),
|
||||
(BuildTarget.StandaloneOSX, "macOS"),
|
||||
(BuildTarget.StandaloneWindows64, "Windows (x64)"),
|
||||
(BuildTarget.StandaloneLinux64, "Linux (x64)"),
|
||||
};
|
||||
|
||||
static readonly string[] s_platformLabels = s_platforms.Select(p => p.label).ToArray();
|
||||
|
||||
[MenuItem("Tools/OCES/Asset Bundle Builder")]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
AssetBundleBuilderWindow window = GetWindow<AssetBundleBuilderWindow>(
|
||||
false, "Bundle Builder", true);
|
||||
window.minSize = new Vector2(360, 400);
|
||||
window.Show();
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
// 默认选中当前 Player 平台
|
||||
BuildTarget current = EditorUserBuildSettings.activeBuildTarget;
|
||||
for (int i = 0; i < s_platforms.Length; i++)
|
||||
{
|
||||
if (s_platforms[i].target != current)
|
||||
continue;
|
||||
this.m_targetIndex = i;
|
||||
return;
|
||||
}
|
||||
// 兜底:Android
|
||||
this.m_targetIndex = 13;
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
GUILayout.Space(10);
|
||||
|
||||
// ── Bundle 选择 ──
|
||||
EditorGUILayout.LabelField("Bundles to Build", EditorStyles.boldLabel);
|
||||
this.m_buildAudio = EditorGUILayout.ToggleLeft("Audio Bundle (audios.ab)", this.m_buildAudio);
|
||||
this.m_buildHaptic = EditorGUILayout.ToggleLeft("Haptic Bundle (haptic.ab)", this.m_buildHaptic);
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
// ── 平台选择 ──
|
||||
EditorGUILayout.LabelField("Target Platform", EditorStyles.boldLabel);
|
||||
this.m_targetIndex = EditorGUILayout.Popup(this.m_targetIndex, s_platformLabels);
|
||||
|
||||
// ── 输出路径预览 ──
|
||||
AudioExtendSettings audioSettings =
|
||||
AssetDatabase.LoadAssetAtPath<AudioExtendSettings>(k_audioSettingsPath);
|
||||
HapticSettings hapticSettings =
|
||||
AssetDatabase.LoadAssetAtPath<HapticSettings>(k_hapticSettingsPath);
|
||||
|
||||
if (audioSettings && this.m_buildAudio)
|
||||
EditorGUILayout.LabelField(
|
||||
$" Audio → {Application.streamingAssetsPath}/{audioSettings.audioBundlePath}",
|
||||
EditorStyles.miniLabel);
|
||||
|
||||
if (hapticSettings && this.m_buildHaptic)
|
||||
EditorGUILayout.LabelField(
|
||||
$" Haptic → {Application.streamingAssetsPath}/{hapticSettings.hapticBundlePath}",
|
||||
EditorStyles.miniLabel);
|
||||
|
||||
if (!audioSettings && !hapticSettings)
|
||||
EditorGUILayout.HelpBox(
|
||||
$"未找到 Settings 资产。\n 请初始化对应系统。",
|
||||
MessageType.Warning);
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
// ── 构建按钮 ──
|
||||
bool canBuild = (this.m_buildAudio || this.m_buildHaptic)
|
||||
&& (audioSettings || !this.m_buildAudio)
|
||||
&& (hapticSettings || !this.m_buildHaptic);
|
||||
|
||||
EditorGUI.BeginDisabledGroup(!canBuild);
|
||||
if (GUILayout.Button("Build", GUILayout.Height(32)))
|
||||
{
|
||||
string result = AssetBundleBuilder.BuildBundles(this.m_buildAudio,
|
||||
audioSettings ? audioSettings.audioBundlePath : "", this.m_buildHaptic,
|
||||
hapticSettings != null ? hapticSettings.hapticBundlePath : "",
|
||||
s_platforms[this.m_targetIndex].target);
|
||||
this.m_log += result + "\n";
|
||||
}
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
// ── 日志区 ──
|
||||
EditorGUILayout.LabelField("Build Log", EditorStyles.boldLabel);
|
||||
this.m_scrollPos = EditorGUILayout.BeginScrollView(this.m_scrollPos,
|
||||
GUILayout.ExpandHeight(true));
|
||||
EditorGUILayout.TextArea(this.m_log,
|
||||
GUILayout.ExpandHeight(true));
|
||||
EditorGUILayout.EndScrollView();
|
||||
|
||||
// 底部清空日志按钮
|
||||
if (string.IsNullOrEmpty(this.m_log))
|
||||
return;
|
||||
GUILayout.Space(4);
|
||||
if (GUILayout.Button("Clear Log", GUILayout.Width(80)))
|
||||
this.m_log = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f327fedaa18441e2bf347cf46810592d
|
||||
timeCreated: 1778829708
|
||||
Reference in New Issue
Block a user