Support addressable location

支持可寻址资源定位
This commit is contained in:
hevinci
2022-04-28 17:23:31 +08:00
parent 775c724840
commit 2cb006f3d9
40 changed files with 799 additions and 235 deletions
@@ -8,6 +8,7 @@ namespace YooAsset
internal sealed class BundledSceneProvider : BundledProvider
{
public readonly LoadSceneMode SceneMode;
private readonly string _sceneName;
private readonly bool _activateOnLoad;
private readonly int _priority;
private AsyncOperation _asyncOp;
@@ -25,6 +26,7 @@ namespace YooAsset
: base(scenePath, null)
{
SceneMode = sceneMode;
_sceneName = System.IO.Path.GetFileNameWithoutExtension(scenePath);
_activateOnLoad = activateOnLoad;
_priority = priority;
}
@@ -68,7 +70,7 @@ namespace YooAsset
// 2. 加载场景
if (Status == EStatus.Loading)
{
_asyncOp = SceneManager.LoadSceneAsync(AssetName, SceneMode);
_asyncOp = SceneManager.LoadSceneAsync(_sceneName, SceneMode);
if (_asyncOp != null)
{
_asyncOp.allowSceneActivation = true;
@@ -78,7 +80,7 @@ namespace YooAsset
else
{
Status = EStatus.Fail;
LastError = $"Failed to load scene : {AssetName}";
LastError = $"Failed to load scene : {_sceneName}";
YooLogger.Error(LastError);
InvokeCompletion();
}
@@ -89,7 +91,7 @@ namespace YooAsset
{
if (_asyncOp.isDone)
{
SceneObject = SceneManager.GetSceneByName(AssetName);
SceneObject = SceneManager.GetSceneByName(_sceneName);
if (SceneObject.IsValid() && _activateOnLoad)
SceneManager.SetActiveScene(SceneObject);
@@ -5,6 +5,11 @@ namespace YooAsset
[Serializable]
internal class PatchAsset
{
/// <summary>
/// 可寻址地址
/// </summary>
public string Address;
/// <summary>
/// 资源路径
/// </summary>
@@ -12,6 +12,11 @@ namespace YooAsset
[Serializable]
internal class PatchManifest
{
/// <summary>
/// 启用可寻址资源定位
/// </summary>
public bool EnableAddressable;
/// <summary>
/// 资源版本号
/// </summary>
@@ -45,6 +50,12 @@ namespace YooAsset
[NonSerialized]
public readonly Dictionary<string, PatchAsset> Assets = new Dictionary<string, PatchAsset>();
/// <summary>
/// 可寻址地址映射集合
/// </summary>
[NonSerialized]
public readonly Dictionary<string, string> AddressDic = new Dictionary<string, string>();
/// <summary>
/// 获取内置资源标签列表
@@ -108,6 +119,22 @@ namespace YooAsset
}
}
/// <summary>
/// 可寻址地址转换为资源路径
/// </summary>
public string ConvertAddress(string address)
{
if (AddressDic.TryGetValue(address, out string assetPath))
{
return assetPath;
}
else
{
YooLogger.Warning($"Not found address in patch manifest : {address}");
return string.Empty;
}
}
/// <summary>
/// 序列化
@@ -155,6 +182,19 @@ namespace YooAsset
}
}
// Address
if (patchManifest.EnableAddressable)
{
foreach (var patchAsset in patchManifest.AssetList)
{
string address = patchAsset.Address;
if (patchManifest.AddressDic.ContainsKey(address))
throw new Exception($"Address have existed : {address}");
else
patchManifest.AddressDic.Add(address, patchAsset.AssetPath);
}
}
return patchManifest;
}
}
@@ -31,6 +31,10 @@ namespace YooAsset
BundleInfo bundleInfo = new BundleInfo(bundleName);
return bundleInfo;
}
string IBundleServices.ConvertAddress(string address)
{
throw new Exception($"Editor play mode not support addressable.");
}
string IBundleServices.GetBundleName(string assetPath)
{
return assetPath;
@@ -237,6 +237,10 @@ namespace YooAsset
return bundleInfo;
}
}
string IBundleServices.ConvertAddress(string address)
{
return LocalPatchManifest.ConvertAddress(address);
}
string IBundleServices.GetBundleName(string assetPath)
{
return LocalPatchManifest.GetBundleName(assetPath);
@@ -56,6 +56,10 @@ namespace YooAsset
return bundleInfo;
}
}
string IBundleServices.ConvertAddress(string address)
{
return AppPatchManifest.ConvertAddress(address);
}
string IBundleServices.GetBundleName(string assetPath)
{
return AppPatchManifest.GetBundleName(assetPath);
@@ -1,11 +0,0 @@
namespace YooAsset
{
public class AddressLocationServices : ILocationServices
{
public string ConvertLocationToAssetPath(YooAssets.EPlayMode playMode, string location)
{
throw new System.NotImplementedException("该功能暂未支持!");
}
}
}
@@ -1,105 +0,0 @@
using System.IO;
using UnityEngine;
namespace YooAsset
{
public class DefaultLocationServices : ILocationServices
{
private readonly string _resourceRoot;
public DefaultLocationServices(string resourceRoot)
{
if (string.IsNullOrEmpty(resourceRoot) == false)
_resourceRoot = PathHelper.GetRegularPath(resourceRoot);
}
public string ConvertLocationToAssetPath(YooAssets.EPlayMode playMode, string location)
{
#if UNITY_EDITOR
CheckLocation(location);
#endif
if (playMode == YooAssets.EPlayMode.EditorPlayMode)
{
string filePath = CombineAssetPath(_resourceRoot, location);
return FindDatabaseAssetPath(filePath);
}
else
{
return CombineAssetPath(_resourceRoot, location);
}
}
/// <summary>
/// 合并资源路径
/// </summary>
private static string CombineAssetPath(string root, string location)
{
if (string.IsNullOrEmpty(root))
return location;
else
return $"{root}/{location}";
}
/// <summary>
/// 获取AssetDatabase的加载路径
/// </summary>
private static string FindDatabaseAssetPath(string filePath)
{
#if UNITY_EDITOR
if (File.Exists(filePath))
return filePath;
// AssetDatabase加载资源需要提供文件后缀格式,然而资源定位地址并没有文件格式信息。
// 所以我们通过查找该文件所在文件夹内同名的首个文件来确定AssetDatabase的加载路径。
// 注意:AssetDatabase.FindAssets() 返回文件内包括递归文件夹内所有资源的GUID
string fileName = Path.GetFileName(filePath);
string directory = PathHelper.GetDirectory(filePath);
string[] guids = UnityEditor.AssetDatabase.FindAssets(string.Empty, new[] { directory });
for (int i = 0; i < guids.Length; i++)
{
string assetPath = UnityEditor.AssetDatabase.GUIDToAssetPath(guids[i]);
if (UnityEditor.AssetDatabase.IsValidFolder(assetPath))
continue;
string assetDirectory = PathHelper.GetDirectory(assetPath);
if (assetDirectory != directory)
continue;
string assetName = Path.GetFileNameWithoutExtension(assetPath);
if (assetName == fileName)
return assetPath;
}
// 没有找到同名的资源文件
YooLogger.Warning($"Not found asset : {filePath}");
return filePath;
#else
throw new System.NotImplementedException();
#endif
}
#if UNITY_EDITOR
private void CheckLocation(string location)
{
if (string.IsNullOrEmpty(location))
{
YooLogger.Error("location param is null or empty!");
}
else
{
// 检查路径末尾是否有空格
int index = location.LastIndexOf(" ");
if (index != -1)
{
if (location.Length == index + 1)
YooLogger.Warning($"Found blank character in location : \"{location}\"");
}
if (location.IndexOfAny(Path.GetInvalidPathChars()) >= 0)
YooLogger.Warning($"Found illegal character in location : \"{location}\"");
}
}
#endif
}
}
@@ -8,6 +8,11 @@ namespace YooAsset
/// </summary>
BundleInfo GetBundleInfo(string bundleName);
/// <summary>
/// 可寻址地址转换为资源路径
/// </summary>
string ConvertAddress(string address);
/// <summary>
/// 获取资源所属的资源包名称
/// </summary>
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6e400ee1e8b3556479bfa493ff7fe778
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,29 @@
namespace YooAsset
{
public class AddressLocationServices : ILocationServices
{
public AddressLocationServices()
{
#if UNITY_EDITOR
LocationServicesHelper.InitEditorPlayMode(true);
#endif
}
public string ConvertLocationToAssetPath(YooAssets.EPlayMode playMode, string location)
{
if (playMode == YooAssets.EPlayMode.EditorPlayMode)
{
#if UNITY_EDITOR
return LocationServicesHelper.ConvertLocationToAssetPath(location);
#else
throw new System.NotImplementedException();
#endif
}
else
{
return YooAssets.ConvertAddress(location);
}
}
}
}
@@ -0,0 +1,42 @@
namespace YooAsset
{
public class DefaultLocationServices : ILocationServices
{
private readonly string _resourceRoot;
public DefaultLocationServices(string resourceRoot)
{
if (string.IsNullOrEmpty(resourceRoot) == false)
_resourceRoot = PathHelper.GetRegularPath(resourceRoot);
#if UNITY_EDITOR
LocationServicesHelper.InitEditorPlayMode(false);
#endif
}
public string ConvertLocationToAssetPath(YooAssets.EPlayMode playMode, string location)
{
location = CombineAssetPath(_resourceRoot, location);
if (playMode == YooAssets.EPlayMode.EditorPlayMode)
{
#if UNITY_EDITOR
return LocationServicesHelper.ConvertLocationToAssetPath(location);
#else
throw new System.NotImplementedException();
#endif
}
else
{
return location;
}
}
private string CombineAssetPath(string root, string location)
{
if (string.IsNullOrEmpty(root))
return location;
else
return $"{root}/{location}";
}
}
}
@@ -0,0 +1,32 @@
#if UNITY_EDITOR
using System.Reflection;
namespace YooAsset
{
internal static class LocationServicesHelper
{
private static System.Type AssetBundleGrouperSettingHelperClassType;
public static void InitEditorPlayMode(bool enableAddressable)
{
AssetBundleGrouperSettingHelperClassType = Assembly.Load("YooAsset.Editor").GetType("YooAsset.Editor.AssetBundleGrouperSettingHelper");
InvokePublicStaticMethod(AssetBundleGrouperSettingHelperClassType, "InitEditorPlayMode", enableAddressable);
}
public static string ConvertLocationToAssetPath(string location)
{
return (string)InvokePublicStaticMethod(AssetBundleGrouperSettingHelperClassType, "ConvertLocationToAssetPath", location);
}
private static object InvokePublicStaticMethod(System.Type type, string method, params object[] parameters)
{
var methodInfo = type.GetMethod(method, BindingFlags.Public | BindingFlags.Static);
if (methodInfo == null)
{
UnityEngine.Debug.LogError($"{type.FullName} not found method : {method}");
return null;
}
return methodInfo.Invoke(null, parameters);
}
}
}
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b39dcdab07554ca4ab4ace5ca97aee78
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+8 -9
View File
@@ -377,18 +377,16 @@ namespace YooAsset
}
else if (_playMode == EPlayMode.OfflinePlayMode)
{
IBundleServices bundleServices = _offlinePlayModeImpl;
string bundleName = bundleServices.GetBundleName(assetPath);
BundleInfo bundleInfo = bundleServices.GetBundleInfo(bundleName);
string bundleName = _bundleServices.GetBundleName(assetPath);
BundleInfo bundleInfo = _bundleServices.GetBundleInfo(bundleName);
RawFileOperation operation = new OfflinePlayModeRawFileOperation(bundleInfo, copyPath);
OperationSystem.ProcessOperaiton(operation);
return operation;
}
else if (_playMode == EPlayMode.HostPlayMode)
{
IBundleServices bundleServices = _hostPlayModeImpl;
string bundleName = bundleServices.GetBundleName(assetPath);
BundleInfo bundleInfo = bundleServices.GetBundleInfo(bundleName);
string bundleName = _bundleServices.GetBundleName(assetPath);
BundleInfo bundleInfo = _bundleServices.GetBundleInfo(bundleName);
RawFileOperation operation = new HostPlayModeRawFileOperation(bundleInfo, copyPath);
OperationSystem.ProcessOperaiton(operation);
return operation;
@@ -650,9 +648,6 @@ namespace YooAsset
#endregion
#region 内部方法
/// <summary>
/// 更新资源系统
/// </summary>
internal static void InternalUpdate()
{
// 更新异步请求操作
@@ -675,6 +670,10 @@ namespace YooAsset
}
}
}
internal static string ConvertAddress(string address)
{
return _bundleServices.ConvertAddress(address);
}
#endregion
}
}