111
This commit is contained in:
@@ -6,83 +6,84 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEditor.Build.Pipeline;
|
using UnityEditor.Build.Pipeline;
|
||||||
|
|
||||||
public class BuildTool
|
namespace Tuan.GameFramework
|
||||||
{
|
{
|
||||||
[MenuItem("Tools/打包Preload")]
|
public class BuildTool
|
||||||
public static void BuildPreload()
|
|
||||||
{
|
{
|
||||||
CopyHotDll.CopyPreloadDll2Byte();
|
[MenuItem("Tools/打包Preload")]
|
||||||
ExecuteBuild("Preload",EBuildPipeline.ScriptableBuildPipeline, EditorUserBuildSettings.activeBuildTarget,EFileNameStyle.BundleName,EBuildinFileCopyOption.ClearAndCopyAll);
|
public static void BuildPreload()
|
||||||
Debug.Log($"打包Preload结束");
|
{
|
||||||
}
|
CopyHotDll.CopyPreloadDll2Byte();
|
||||||
[MenuItem("Tools/打包Main %G")]
|
ExecuteBuild("Preload", EBuildPipeline.ScriptableBuildPipeline, EditorUserBuildSettings.activeBuildTarget, EFileNameStyle.BundleName, EBuildinFileCopyOption.ClearAndCopyAll);
|
||||||
public static void BuildMain()
|
Debug.Log($"打包Preload结束");
|
||||||
{
|
}
|
||||||
CopyHotDll.CopyMainDll2Byte();
|
[MenuItem("Tools/打包Main %G")]
|
||||||
ExecuteBuild("Main", EBuildPipeline.ScriptableBuildPipeline, EditorUserBuildSettings.activeBuildTarget, EFileNameStyle.BundleName, EBuildinFileCopyOption.None);
|
public static void BuildMain()
|
||||||
Debug.Log($"打包Main结束");
|
{
|
||||||
}
|
CopyHotDll.CopyMainDll2Byte();
|
||||||
[MenuItem("Tools/全部打包")]
|
ExecuteBuild("Main", EBuildPipeline.ScriptableBuildPipeline, EditorUserBuildSettings.activeBuildTarget, EFileNameStyle.BundleName, EBuildinFileCopyOption.None);
|
||||||
public static void BuildAll()
|
Debug.Log($"打包Main结束");
|
||||||
{
|
}
|
||||||
BuildPreload();
|
[MenuItem("Tools/全部打包")]
|
||||||
BuildMain();
|
public static void BuildAll()
|
||||||
}
|
{
|
||||||
|
BuildPreload();
|
||||||
|
BuildMain();
|
||||||
|
}
|
||||||
|
|
||||||
public static void ExecuteBuild(string PackageName, EBuildPipeline BuildPipeline, BuildTarget BuildTarget, EFileNameStyle fileNameStyle, EBuildinFileCopyOption buildinFileCopyOption)
|
public static void ExecuteBuild(string PackageName, EBuildPipeline BuildPipeline, BuildTarget BuildTarget, EFileNameStyle fileNameStyle, EBuildinFileCopyOption buildinFileCopyOption)
|
||||||
{
|
{
|
||||||
var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(PackageName, BuildPipeline.ToString());
|
var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(PackageName, BuildPipeline.ToString());
|
||||||
var compressOption = AssetBundleBuilderSetting.GetPackageCompressOption(PackageName, BuildPipeline.ToString());
|
var compressOption = AssetBundleBuilderSetting.GetPackageCompressOption(PackageName, BuildPipeline.ToString());
|
||||||
var clearBuildCache = AssetBundleBuilderSetting.GetPackageClearBuildCache(PackageName, BuildPipeline.ToString());
|
var clearBuildCache = AssetBundleBuilderSetting.GetPackageClearBuildCache(PackageName, BuildPipeline.ToString());
|
||||||
var useAssetDependencyDB = AssetBundleBuilderSetting.GetPackageUseAssetDependencyDB(PackageName, BuildPipeline.ToString());
|
var useAssetDependencyDB = AssetBundleBuilderSetting.GetPackageUseAssetDependencyDB(PackageName, BuildPipeline.ToString());
|
||||||
var builtinShaderBundleName = GetBuiltinShaderBundleName(PackageName);
|
var builtinShaderBundleName = GetBuiltinShaderBundleName(PackageName);
|
||||||
|
|
||||||
ScriptableBuildParameters buildParameters = new ScriptableBuildParameters();
|
ScriptableBuildParameters buildParameters = new ScriptableBuildParameters();
|
||||||
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
|
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
|
||||||
buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
|
buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
|
||||||
buildParameters.BuildPipeline = BuildPipeline.ToString();
|
buildParameters.BuildPipeline = BuildPipeline.ToString();
|
||||||
buildParameters.BuildBundleType = (int)EBuildBundleType.AssetBundle;
|
buildParameters.BuildBundleType = (int)EBuildBundleType.AssetBundle;
|
||||||
buildParameters.BuildTarget = BuildTarget;
|
buildParameters.BuildTarget = BuildTarget;
|
||||||
buildParameters.PackageName = PackageName;
|
buildParameters.PackageName = PackageName;
|
||||||
buildParameters.PackageVersion = GetPackageVersion();
|
buildParameters.PackageVersion = GetPackageVersion();
|
||||||
buildParameters.EnableSharePackRule = true;
|
buildParameters.EnableSharePackRule = true;
|
||||||
buildParameters.VerifyBuildingResult = true;
|
buildParameters.VerifyBuildingResult = true;
|
||||||
buildParameters.FileNameStyle = fileNameStyle;
|
buildParameters.FileNameStyle = fileNameStyle;
|
||||||
buildParameters.BuildinFileCopyOption = buildinFileCopyOption;
|
buildParameters.BuildinFileCopyOption = buildinFileCopyOption;
|
||||||
buildParameters.BuildinFileCopyParams = buildinFileCopyParams;
|
buildParameters.BuildinFileCopyParams = buildinFileCopyParams;
|
||||||
buildParameters.CompressOption = compressOption;
|
buildParameters.CompressOption = compressOption;
|
||||||
buildParameters.ClearBuildCacheFiles = clearBuildCache;
|
buildParameters.ClearBuildCacheFiles = clearBuildCache;
|
||||||
buildParameters.UseAssetDependencyDB = useAssetDependencyDB;
|
buildParameters.UseAssetDependencyDB = useAssetDependencyDB;
|
||||||
buildParameters.BuiltinShadersBundleName = builtinShaderBundleName;
|
buildParameters.BuiltinShadersBundleName = builtinShaderBundleName;
|
||||||
buildParameters.EncryptionServices = CreateEncryptionInstance(PackageName, BuildPipeline);
|
buildParameters.EncryptionServices = CreateEncryptionInstance(PackageName, BuildPipeline);
|
||||||
|
|
||||||
ScriptableBuildPipeline pipeline = new ScriptableBuildPipeline();
|
ScriptableBuildPipeline pipeline = new ScriptableBuildPipeline();
|
||||||
var buildResult = pipeline.Run(buildParameters, true);
|
var buildResult = pipeline.Run(buildParameters, true);
|
||||||
if (buildResult.Success)
|
if (buildResult.Success)
|
||||||
EditorUtility.RevealInFinder(buildResult.OutputPackageDirectory);
|
EditorUtility.RevealInFinder(buildResult.OutputPackageDirectory);
|
||||||
|
}
|
||||||
|
public static string GetPackageVersion()
|
||||||
|
{
|
||||||
|
int totalMinutes = DateTime.Now.Hour * 60 + DateTime.Now.Minute;
|
||||||
|
return DateTime.Now.ToString("yyyy-MM-dd") + "-" + totalMinutes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetBuiltinShaderBundleName(string PackageName)
|
||||||
|
{
|
||||||
|
var uniqueBundleName = AssetBundleCollectorSettingData.Setting.UniqueBundleName;
|
||||||
|
var packRuleResult = DefaultPackRule.CreateShadersPackRuleResult();
|
||||||
|
return packRuleResult.GetBundleName(PackageName, uniqueBundleName);
|
||||||
|
}
|
||||||
|
public static IEncryptionServices CreateEncryptionInstance(string PackageName, EBuildPipeline BuildPipeline)
|
||||||
|
{
|
||||||
|
var encyptionClassName = AssetBundleBuilderSetting.GetPackageEncyptionServicesClassName(PackageName, BuildPipeline.ToString());
|
||||||
|
var encryptionClassTypes = EditorTools.GetAssignableTypes(typeof(IEncryptionServices));
|
||||||
|
var classType = encryptionClassTypes.Find(x => x.FullName.Equals(encyptionClassName));
|
||||||
|
if (classType != null)
|
||||||
|
return (IEncryptionServices)Activator.CreateInstance(classType);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public static string GetPackageVersion()
|
}
|
||||||
{
|
|
||||||
int totalMinutes = DateTime.Now.Hour * 60 + DateTime.Now.Minute;
|
|
||||||
return DateTime.Now.ToString("yyyy-MM-dd") + "-" + totalMinutes;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetBuiltinShaderBundleName(string PackageName)
|
|
||||||
{
|
|
||||||
var uniqueBundleName = AssetBundleCollectorSettingData.Setting.UniqueBundleName;
|
|
||||||
var packRuleResult = DefaultPackRule.CreateShadersPackRuleResult();
|
|
||||||
return packRuleResult.GetBundleName(PackageName, uniqueBundleName);
|
|
||||||
}
|
|
||||||
public static IEncryptionServices CreateEncryptionInstance(string PackageName, EBuildPipeline BuildPipeline)
|
|
||||||
{
|
|
||||||
var encyptionClassName = AssetBundleBuilderSetting.GetPackageEncyptionServicesClassName(PackageName, BuildPipeline.ToString());
|
|
||||||
var encryptionClassTypes = EditorTools.GetAssignableTypes(typeof(IEncryptionServices));
|
|
||||||
var classType = encryptionClassTypes.Find(x => x.FullName.Equals(encyptionClassName));
|
|
||||||
if (classType != null)
|
|
||||||
return (IEncryptionServices)Activator.CreateInstance(classType);
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -2,58 +2,60 @@ using UnityEditor;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Tuan.GameFramework
|
||||||
public class CopyHotDll
|
|
||||||
{
|
{
|
||||||
[MenuItem("Tools/更新生成PreloadDll")]
|
public class CopyHotDll
|
||||||
public static void CopyPreloadDll2Byte()
|
|
||||||
{
|
{
|
||||||
HybridCLR.Editor.Commands.CompileDllCommand.CompileDllActiveBuildTarget();
|
[MenuItem("Tools/更新生成PreloadDll")]
|
||||||
string sourceDir = $"{Application.dataPath.Replace("/Assets", "")}/HybridCLRData/HotUpdateDlls/{UnityEditor.EditorUserBuildSettings.activeBuildTarget}/GameScripts.Preload.dll";
|
public static void CopyPreloadDll2Byte()
|
||||||
string destDir = $"{Application.dataPath}/GameRes/Preload/HotUpdateDll/GameScripts.Preload.bytes";
|
|
||||||
if (File.Exists(destDir))
|
|
||||||
{
|
{
|
||||||
File.Delete(destDir);
|
HybridCLR.Editor.Commands.CompileDllCommand.CompileDllActiveBuildTarget();
|
||||||
}
|
string sourceDir = $"{Application.dataPath.Replace("/Assets", "")}/HybridCLRData/HotUpdateDlls/{UnityEditor.EditorUserBuildSettings.activeBuildTarget}/GameScripts.Preload.dll";
|
||||||
File.Copy(sourceDir, destDir);
|
string destDir = $"{Application.dataPath}/GameRes/Preload/HotUpdateDll/GameScripts.Preload.bytes";
|
||||||
AssetDatabase.Refresh();
|
if (File.Exists(destDir))
|
||||||
Debug.Log($"copy {sourceDir} to {destDir}");
|
|
||||||
}
|
|
||||||
[MenuItem("Tools/更新生成MainDll")]
|
|
||||||
public static void CopyMainDll2Byte()
|
|
||||||
{
|
|
||||||
HybridCLR.Editor.Commands.CompileDllCommand.CompileDllActiveBuildTarget();
|
|
||||||
string sourceDir = $"{Application.dataPath.Replace("/Assets", "")}/HybridCLRData/HotUpdateDlls/{UnityEditor.EditorUserBuildSettings.activeBuildTarget}/GameScripts.Main.dll";
|
|
||||||
string destDir = $"{Application.dataPath}/GameRes/Main/HotUpdateDll/GameScripts.Main.bytes";
|
|
||||||
if (File.Exists(destDir))
|
|
||||||
{
|
|
||||||
File.Delete(destDir);
|
|
||||||
}
|
|
||||||
File.Copy(sourceDir, destDir);
|
|
||||||
AssetDatabase.Refresh();
|
|
||||||
Debug.Log($"copy {sourceDir} to {destDir}");
|
|
||||||
}
|
|
||||||
[MenuItem("Tools/更新生成补充数据源")]
|
|
||||||
public static void CopyDepDll2Byte()
|
|
||||||
{
|
|
||||||
HybridCLR.Editor.Commands.CompileDllCommand.CompileDllActiveBuildTarget();
|
|
||||||
string sourceDir = $"{Application.dataPath.Replace("/Assets", "")}/HybridCLRData/AssembliesPostIl2CppStrip/{UnityEditor.EditorUserBuildSettings.activeBuildTarget}/";
|
|
||||||
string destDir = $"{Application.dataPath}/GameRes/Main/HotUpdateDll/";
|
|
||||||
foreach (string dll in HotDllLoader.Inst.DepDlls)
|
|
||||||
{
|
|
||||||
string sourcePath = $"{sourceDir}/{dll}";
|
|
||||||
string destPath = $"{destDir}/{dll}.bytes";
|
|
||||||
if (File.Exists(sourcePath))
|
|
||||||
{
|
{
|
||||||
if (File.Exists(destPath))
|
File.Delete(destDir);
|
||||||
{
|
|
||||||
File.Delete(destPath);
|
|
||||||
}
|
|
||||||
File.Copy(sourcePath, destPath);
|
|
||||||
AssetDatabase.Refresh();
|
|
||||||
Debug.Log($"copy {sourcePath} to {destPath}");
|
|
||||||
}
|
}
|
||||||
|
File.Copy(sourceDir, destDir);
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
Debug.Log($"copy {sourceDir} to {destDir}");
|
||||||
|
}
|
||||||
|
[MenuItem("Tools/更新生成MainDll")]
|
||||||
|
public static void CopyMainDll2Byte()
|
||||||
|
{
|
||||||
|
HybridCLR.Editor.Commands.CompileDllCommand.CompileDllActiveBuildTarget();
|
||||||
|
string sourceDir = $"{Application.dataPath.Replace("/Assets", "")}/HybridCLRData/HotUpdateDlls/{UnityEditor.EditorUserBuildSettings.activeBuildTarget}/GameScripts.Main.dll";
|
||||||
|
string destDir = $"{Application.dataPath}/GameRes/Main/HotUpdateDll/GameScripts.Main.bytes";
|
||||||
|
if (File.Exists(destDir))
|
||||||
|
{
|
||||||
|
File.Delete(destDir);
|
||||||
|
}
|
||||||
|
File.Copy(sourceDir, destDir);
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
Debug.Log($"copy {sourceDir} to {destDir}");
|
||||||
|
}
|
||||||
|
[MenuItem("Tools/更新生成补充数据源")]
|
||||||
|
public static void CopyDepDll2Byte()
|
||||||
|
{
|
||||||
|
HybridCLR.Editor.Commands.CompileDllCommand.CompileDllActiveBuildTarget();
|
||||||
|
string sourceDir = $"{Application.dataPath.Replace("/Assets", "")}/HybridCLRData/AssembliesPostIl2CppStrip/{UnityEditor.EditorUserBuildSettings.activeBuildTarget}/";
|
||||||
|
string destDir = $"{Application.dataPath}/GameRes/Main/HotUpdateDll/";
|
||||||
|
foreach (string dll in HotDllLoader.Inst.DepDlls)
|
||||||
|
{
|
||||||
|
string sourcePath = $"{sourceDir}/{dll}";
|
||||||
|
string destPath = $"{destDir}/{dll}.bytes";
|
||||||
|
if (File.Exists(sourcePath))
|
||||||
|
{
|
||||||
|
if (File.Exists(destPath))
|
||||||
|
{
|
||||||
|
File.Delete(destPath);
|
||||||
|
}
|
||||||
|
File.Copy(sourcePath, destPath);
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
Debug.Log($"copy {sourcePath} to {destPath}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Debug.Log("copy over");
|
||||||
}
|
}
|
||||||
Debug.Log("copy over");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
15
Assets/GameFramework/Runtime/Asset.cs
Normal file
15
Assets/GameFramework/Runtime/Asset.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
using YooAsset;
|
||||||
|
|
||||||
|
namespace Tuan.GameFramework
|
||||||
|
{
|
||||||
|
public class Asset : MonoBehaviour
|
||||||
|
{
|
||||||
|
async UniTask LoadAsync(string name)
|
||||||
|
{
|
||||||
|
AssetHandle handle = YooAssets.LoadAssetAsync(name);
|
||||||
|
await handle.ToUniTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Assets/GameFramework/Runtime/Asset.cs.meta
Normal file
2
Assets/GameFramework/Runtime/Asset.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d9170e9f660395d47b0f02466e5fd091
|
||||||
@@ -2,34 +2,37 @@ using Cysharp.Threading.Tasks;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using YooAsset;
|
using YooAsset;
|
||||||
|
|
||||||
public class Boot : MonoBehaviour
|
namespace Tuan.GameFramework
|
||||||
{
|
{
|
||||||
public Camera MainCamera;
|
public class Boot : MonoBehaviour
|
||||||
public EPlayMode PlayMode = EPlayMode.EditorSimulateMode;
|
|
||||||
void Awake()
|
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR
|
public Camera MainCamera;
|
||||||
//PlayerPrefs.DeleteAll();
|
public EPlayMode PlayMode = EPlayMode.EditorSimulateMode;
|
||||||
#endif
|
void Awake()
|
||||||
Application.targetFrameRate = 60;
|
|
||||||
Application.runInBackground = true;
|
|
||||||
DontDestroyOnLoad(MainCamera);
|
|
||||||
}
|
|
||||||
async void Start()
|
|
||||||
{
|
|
||||||
bool updateSuccess = await PatchManager.Inst.StartOperation(PlayMode);
|
|
||||||
if (updateSuccess)
|
|
||||||
await EnterGame();
|
|
||||||
}
|
|
||||||
private async UniTask EnterGame()
|
|
||||||
{
|
|
||||||
Debug.Log("EnterGame");
|
|
||||||
var assetHandle = YooAssets.TryGetPackage("Main").LoadSceneAsync("Test");
|
|
||||||
await assetHandle.ToUniTask();
|
|
||||||
if (assetHandle.Status == EOperationStatus.Succeed)
|
|
||||||
{
|
{
|
||||||
assetHandle.ActivateScene();
|
#if UNITY_EDITOR
|
||||||
PatchEvent.ClosePatchWindow();
|
//PlayerPrefs.DeleteAll();
|
||||||
|
#endif
|
||||||
|
Application.targetFrameRate = 60;
|
||||||
|
Application.runInBackground = true;
|
||||||
|
DontDestroyOnLoad(MainCamera);
|
||||||
|
}
|
||||||
|
async void Start()
|
||||||
|
{
|
||||||
|
bool updateSuccess = await PatchManager.Inst.StartOperation(PlayMode);
|
||||||
|
if (updateSuccess)
|
||||||
|
await EnterGame();
|
||||||
|
}
|
||||||
|
private async UniTask EnterGame()
|
||||||
|
{
|
||||||
|
Debug.Log("EnterGame");
|
||||||
|
var assetHandle = YooAssets.TryGetPackage("Main").LoadSceneAsync("Test");
|
||||||
|
await assetHandle.ToUniTask();
|
||||||
|
if (assetHandle.Status == EOperationStatus.Succeed)
|
||||||
|
{
|
||||||
|
assetHandle.ActivateScene();
|
||||||
|
PatchEvent.ClosePatchWindow();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,87 +2,90 @@ using System.Collections.Generic;
|
|||||||
using System;
|
using System;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public static class EventBus
|
namespace Tuan.GameFramework
|
||||||
{
|
{
|
||||||
|
public static class EventBus
|
||||||
private static readonly Dictionary<Type, object> _eventHandlers = new Dictionary<Type, object>();
|
|
||||||
private static readonly object _lock = new object();
|
|
||||||
|
|
||||||
public static void Register<TEvent>(IEventHandler<TEvent> handler) where TEvent : IEvent
|
|
||||||
{
|
{
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
Type eventType = typeof(TEvent);
|
|
||||||
if (!_eventHandlers.ContainsKey(eventType))
|
|
||||||
{
|
|
||||||
_eventHandlers[eventType] = new List<IEventHandler<TEvent>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
var handlers = _eventHandlers[eventType] as List<IEventHandler<TEvent>>;
|
private static readonly Dictionary<Type, object> _eventHandlers = new Dictionary<Type, object>();
|
||||||
if (handler != null && !handlers.Contains(handler))
|
private static readonly object _lock = new object();
|
||||||
{
|
|
||||||
handlers.Add(handler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Unregister<TEvent>(IEventHandler<TEvent> handler) where TEvent : IEvent
|
public static void Register<TEvent>(IEventHandler<TEvent> handler) where TEvent : IEvent
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
{
|
||||||
Type eventType = typeof(TEvent);
|
lock (_lock)
|
||||||
if (_eventHandlers.ContainsKey(eventType))
|
|
||||||
{
|
{
|
||||||
|
Type eventType = typeof(TEvent);
|
||||||
|
if (!_eventHandlers.ContainsKey(eventType))
|
||||||
|
{
|
||||||
|
_eventHandlers[eventType] = new List<IEventHandler<TEvent>>();
|
||||||
|
}
|
||||||
|
|
||||||
var handlers = _eventHandlers[eventType] as List<IEventHandler<TEvent>>;
|
var handlers = _eventHandlers[eventType] as List<IEventHandler<TEvent>>;
|
||||||
handlers?.Remove(handler);
|
if (handler != null && !handlers.Contains(handler))
|
||||||
|
|
||||||
if (handlers != null && handlers.Count == 0)
|
|
||||||
{
|
{
|
||||||
_eventHandlers.Remove(eventType);
|
handlers.Add(handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static void Publish<TEvent>(TEvent eventData) where TEvent : IEvent
|
public static void Unregister<TEvent>(IEventHandler<TEvent> handler) where TEvent : IEvent
|
||||||
{
|
|
||||||
List<IEventHandler<TEvent>> handlersToInvoke = null;
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
{
|
||||||
Type eventType = typeof(TEvent);
|
lock (_lock)
|
||||||
if (_eventHandlers.ContainsKey(eventType))
|
|
||||||
{
|
{
|
||||||
var handlers = _eventHandlers[eventType] as List<IEventHandler<TEvent>>;
|
Type eventType = typeof(TEvent);
|
||||||
if (handlers != null && handlers.Count > 0)
|
if (_eventHandlers.ContainsKey(eventType))
|
||||||
{
|
{
|
||||||
handlersToInvoke = new List<IEventHandler<TEvent>>(handlers);
|
var handlers = _eventHandlers[eventType] as List<IEventHandler<TEvent>>;
|
||||||
|
handlers?.Remove(handler);
|
||||||
|
|
||||||
|
if (handlers != null && handlers.Count == 0)
|
||||||
|
{
|
||||||
|
_eventHandlers.Remove(eventType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在锁外执行事件处理,避免死锁
|
public static void Publish<TEvent>(TEvent eventData) where TEvent : IEvent
|
||||||
if (handlersToInvoke != null)
|
|
||||||
{
|
{
|
||||||
foreach (var handler in handlersToInvoke)
|
List<IEventHandler<TEvent>> handlersToInvoke = null;
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
{
|
{
|
||||||
try
|
Type eventType = typeof(TEvent);
|
||||||
|
if (_eventHandlers.ContainsKey(eventType))
|
||||||
{
|
{
|
||||||
handler?.HandleEvent(eventData);
|
var handlers = _eventHandlers[eventType] as List<IEventHandler<TEvent>>;
|
||||||
|
if (handlers != null && handlers.Count > 0)
|
||||||
|
{
|
||||||
|
handlersToInvoke = new List<IEventHandler<TEvent>>(handlers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
}
|
||||||
|
|
||||||
|
// 在锁外执行事件处理,避免死锁
|
||||||
|
if (handlersToInvoke != null)
|
||||||
|
{
|
||||||
|
foreach (var handler in handlersToInvoke)
|
||||||
{
|
{
|
||||||
Debug.LogError($"Event handling error in {handler.GetType().Name}: {e}");
|
try
|
||||||
|
{
|
||||||
|
handler?.HandleEvent(eventData);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Event handling error in {handler.GetType().Name}: {e}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static void Clear()
|
public static void Clear()
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
{
|
||||||
_eventHandlers.Clear();
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_eventHandlers.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,27 +1,30 @@
|
|||||||
public interface IEvent { }
|
namespace Tuan.GameFramework
|
||||||
|
|
||||||
public interface IEventHandler<TEvent> where TEvent : IEvent
|
|
||||||
{
|
{
|
||||||
void HandleEvent(TEvent eventData);
|
public interface IEvent { }
|
||||||
}
|
|
||||||
|
|
||||||
public struct ApplicationFocusEvent : IEvent
|
public interface IEventHandler<TEvent> where TEvent : IEvent
|
||||||
{
|
|
||||||
public bool HasFocus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct SceneLoadEvent : IEvent
|
|
||||||
{
|
|
||||||
public string SceneName;
|
|
||||||
public float Progress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class EventHandler<TEvent> : IEventHandler<TEvent> where TEvent : IEvent
|
|
||||||
{
|
|
||||||
public void HandleEvent(TEvent eventData)
|
|
||||||
{
|
{
|
||||||
OnEvent(eventData);
|
void HandleEvent(TEvent eventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void OnEvent(TEvent eventData);
|
public struct ApplicationFocusEvent : IEvent
|
||||||
}
|
{
|
||||||
|
public bool HasFocus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct SceneLoadEvent : IEvent
|
||||||
|
{
|
||||||
|
public string SceneName;
|
||||||
|
public float Progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class EventHandler<TEvent> : IEventHandler<TEvent> where TEvent : IEvent
|
||||||
|
{
|
||||||
|
public void HandleEvent(TEvent eventData)
|
||||||
|
{
|
||||||
|
OnEvent(eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void OnEvent(TEvent eventData);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,8 @@
|
|||||||
"GUID:e34a5702dd353724aa315fb8011f08c3",
|
"GUID:e34a5702dd353724aa315fb8011f08c3",
|
||||||
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
||||||
"GUID:3fe1a3e70da50184f9897101cad7e4f2",
|
"GUID:3fe1a3e70da50184f9897101cad7e4f2",
|
||||||
"GUID:13ba8ce62aa80c74598530029cb2d649"
|
"GUID:13ba8ce62aa80c74598530029cb2d649",
|
||||||
|
"GUID:928f8a513cd12e84cb0d3c0a21a84e2f"
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class GameManager : Singleton<GameManager>
|
namespace Tuan.GameFramework
|
||||||
{
|
{
|
||||||
|
public class GameManager : Singleton<GameManager>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class MainUICanvas : SingletonMono<MainUICanvas>
|
namespace Tuan.GameFramework
|
||||||
{
|
{
|
||||||
public GameObject InitBg;
|
public class MainUICanvas : SingletonMono<MainUICanvas>
|
||||||
public RectTransform Top;
|
|
||||||
public RectTransform Medium;
|
|
||||||
public RectTransform Bottom;
|
|
||||||
public Camera UICamera;
|
|
||||||
private void Awake()
|
|
||||||
{
|
{
|
||||||
DontDestroyOnLoad(gameObject);
|
public GameObject InitBg;
|
||||||
DontDestroyOnLoad(UICamera);
|
public RectTransform Top;
|
||||||
|
public RectTransform Medium;
|
||||||
|
public RectTransform Bottom;
|
||||||
|
public Camera UICamera;
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
DontDestroyOnLoad(gameObject);
|
||||||
|
DontDestroyOnLoad(UICamera);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,84 +3,87 @@ using UnityEngine.UI;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
public class MessageBox : MonoBehaviour
|
namespace Tuan.GameFramework
|
||||||
{
|
{
|
||||||
[SerializeField] private GameObject panel;
|
public class MessageBox : MonoBehaviour
|
||||||
[SerializeField] private Text titleText;
|
|
||||||
[SerializeField] private Text contentText;
|
|
||||||
[SerializeField] private Transform buttonsParent;
|
|
||||||
[SerializeField] private GameObject buttonPrefab;
|
|
||||||
|
|
||||||
private static readonly List<MessageBox> hiddenMessageBoxes = new List<MessageBox>();
|
|
||||||
private readonly List<Button> createdButtons = new List<Button>();
|
|
||||||
|
|
||||||
public static MessageBox Show()
|
|
||||||
{
|
{
|
||||||
|
[SerializeField] private GameObject panel;
|
||||||
|
[SerializeField] private Text titleText;
|
||||||
|
[SerializeField] private Text contentText;
|
||||||
|
[SerializeField] private Transform buttonsParent;
|
||||||
|
[SerializeField] private GameObject buttonPrefab;
|
||||||
|
|
||||||
if (hiddenMessageBoxes.Count > 0)
|
private static readonly List<MessageBox> hiddenMessageBoxes = new List<MessageBox>();
|
||||||
|
private readonly List<Button> createdButtons = new List<Button>();
|
||||||
|
|
||||||
|
public static MessageBox Show()
|
||||||
{
|
{
|
||||||
MessageBox box = hiddenMessageBoxes[0];
|
|
||||||
hiddenMessageBoxes.RemoveAt(0);
|
if (hiddenMessageBoxes.Count > 0)
|
||||||
box.gameObject.SetActive(true);
|
{
|
||||||
box.panel.SetActive(true);
|
MessageBox box = hiddenMessageBoxes[0];
|
||||||
return box;
|
hiddenMessageBoxes.RemoveAt(0);
|
||||||
|
box.gameObject.SetActive(true);
|
||||||
|
box.panel.SetActive(true);
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
var prefab = Resources.Load<GameObject>("MessageBox");
|
||||||
|
if (!prefab)
|
||||||
|
{
|
||||||
|
Debug.LogError("MessageBox prefab not found in Resources");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var go = Instantiate(prefab, MainUICanvas.Inst.Top);
|
||||||
|
go.name = "MessageBox";
|
||||||
|
var messageBox = go.GetComponent<MessageBox>();
|
||||||
|
return messageBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
var prefab = Resources.Load<GameObject>("MessageBox");
|
public void Hide()
|
||||||
if (!prefab)
|
|
||||||
{
|
{
|
||||||
Debug.LogError("MessageBox prefab not found in Resources");
|
panel.SetActive(false);
|
||||||
return null;
|
ClearButtons();
|
||||||
|
gameObject.SetActive(false);
|
||||||
|
hiddenMessageBoxes.Add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
var go = Instantiate(prefab, MainUICanvas.Inst.Top);
|
private void ClearButtons()
|
||||||
go.name = "MessageBox";
|
|
||||||
var messageBox = go.GetComponent<MessageBox>();
|
|
||||||
return messageBox;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Hide()
|
|
||||||
{
|
|
||||||
panel.SetActive(false);
|
|
||||||
ClearButtons();
|
|
||||||
gameObject.SetActive(false);
|
|
||||||
hiddenMessageBoxes.Add(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ClearButtons()
|
|
||||||
{
|
|
||||||
foreach (var button in createdButtons)
|
|
||||||
{
|
{
|
||||||
if (button != null) Destroy(button.gameObject);
|
foreach (var button in createdButtons)
|
||||||
|
{
|
||||||
|
if (button != null) Destroy(button.gameObject);
|
||||||
|
}
|
||||||
|
createdButtons.Clear();
|
||||||
}
|
}
|
||||||
createdButtons.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageBox SetTitle(string title)
|
public MessageBox SetTitle(string title)
|
||||||
{
|
|
||||||
titleText.text = title;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageBox SetContent(string content)
|
|
||||||
{
|
|
||||||
contentText.text = content;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageBox AddButton(string text, Action<MessageBox> onClick = null)
|
|
||||||
{
|
|
||||||
var button = Instantiate(buttonPrefab, buttonsParent).GetComponent<Button>();
|
|
||||||
button.GetComponentInChildren<Text>().text = text;
|
|
||||||
|
|
||||||
button.onClick.AddListener(() =>
|
|
||||||
{
|
{
|
||||||
onClick?.Invoke(this);
|
titleText.text = title;
|
||||||
Hide();
|
return this;
|
||||||
});
|
}
|
||||||
|
|
||||||
createdButtons.Add(button);
|
public MessageBox SetContent(string content)
|
||||||
button.gameObject.SetActive(true);
|
{
|
||||||
return this;
|
contentText.text = content;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageBox AddButton(string text, Action<MessageBox> onClick = null)
|
||||||
|
{
|
||||||
|
var button = Instantiate(buttonPrefab, buttonsParent).GetComponent<Button>();
|
||||||
|
button.GetComponentInChildren<Text>().text = text;
|
||||||
|
|
||||||
|
button.onClick.AddListener(() =>
|
||||||
|
{
|
||||||
|
onClick?.Invoke(this);
|
||||||
|
Hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
createdButtons.Add(button);
|
||||||
|
button.gameObject.SetActive(true);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
46
Assets/GameFramework/Runtime/Patch/HotDllLoader.cs
Normal file
46
Assets/GameFramework/Runtime/Patch/HotDllLoader.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using HybridCLR;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
using YooAsset;
|
||||||
|
|
||||||
|
namespace Tuan.GameFramework
|
||||||
|
{
|
||||||
|
public class HotDllLoader : Singleton<HotDllLoader>
|
||||||
|
{
|
||||||
|
public List<string> DepDlls = new List<string>()
|
||||||
|
{
|
||||||
|
"mscorlib.dll",
|
||||||
|
"System.dll",
|
||||||
|
"System.Core.dll",
|
||||||
|
};
|
||||||
|
public async UniTask LoadDll(ResourcePackage package, string dll)
|
||||||
|
{
|
||||||
|
if (package.GetAssetInfo(dll).Error == string.Empty)
|
||||||
|
{
|
||||||
|
AssetHandle handle = package.LoadAssetAsync<TextAsset>(dll);
|
||||||
|
await handle.ToUniTask();
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
Assembly hotUpdateAss = System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == dll.Replace(".dll", ""));
|
||||||
|
#else
|
||||||
|
Assembly hotUpdateAss = Assembly.Load((handle.AssetObject as TextAsset).bytes);
|
||||||
|
#endif
|
||||||
|
Debug.Log($"加载{dll}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public async UniTask LoadDepDll(ResourcePackage package)
|
||||||
|
{
|
||||||
|
foreach (string dll in DepDlls)
|
||||||
|
{
|
||||||
|
if (package.GetAssetInfo(dll).Error == string.Empty)
|
||||||
|
{
|
||||||
|
AssetHandle handle = package.LoadAssetAsync<TextAsset>(dll);
|
||||||
|
await handle.ToUniTask();
|
||||||
|
RuntimeApi.LoadMetadataForAOTAssembly((handle.AssetObject as TextAsset).bytes, HomologousImageMode.SuperSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
65
Assets/GameFramework/Runtime/Patch/MainOperation.cs
Normal file
65
Assets/GameFramework/Runtime/Patch/MainOperation.cs
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using YooAsset;
|
||||||
|
|
||||||
|
namespace Tuan.GameFramework
|
||||||
|
{
|
||||||
|
public class MainOperation
|
||||||
|
{
|
||||||
|
PatchOperationData data;
|
||||||
|
PatchOperation operation;
|
||||||
|
bool autoDownload;
|
||||||
|
public MainOperation(EPlayMode playMode, bool autoDownload = false)
|
||||||
|
{
|
||||||
|
data = new PatchOperationData();
|
||||||
|
data.packageName = "Main";
|
||||||
|
data.playMode = playMode;
|
||||||
|
data.useBuildinFileSystem = false;
|
||||||
|
data.downloadingMaxNum = 10;
|
||||||
|
data.failedTryAgain = 3;
|
||||||
|
data.downloadUpdate = OnDownloadUpdate;
|
||||||
|
data.downloadFinish = OnDownloadFinish;
|
||||||
|
data.downloadError = OnDownloadError;
|
||||||
|
|
||||||
|
operation = new PatchOperation(data);
|
||||||
|
this.autoDownload = autoDownload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async UniTask Execute()
|
||||||
|
{
|
||||||
|
PatchEvent.UpdateProgress(0f);
|
||||||
|
if (!await operation.InitializePackage()) return;
|
||||||
|
if (!await operation.RequestPackageVersion()) return;
|
||||||
|
if (!await operation.UpdatePackageManifest()) return;
|
||||||
|
if (operation.CreateDownloader())
|
||||||
|
{
|
||||||
|
if (autoDownload)
|
||||||
|
{
|
||||||
|
if (!await operation.DownloadPackageFiles()) return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!await operation.CheckDownloadOrSkip()) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!await operation.ClearCacheBundle()) return;
|
||||||
|
operation.SaveVersionToCache();
|
||||||
|
YooAssets.SetDefaultPackage(operation.package);
|
||||||
|
}
|
||||||
|
private void OnDownloadUpdate(DownloadUpdateData downloadUpdateData)
|
||||||
|
{
|
||||||
|
float progress = (float)downloadUpdateData.CurrentDownloadBytes / downloadUpdateData.TotalDownloadBytes;
|
||||||
|
string sizeText = $"{operation.FormatFileSize(downloadUpdateData.CurrentDownloadBytes)} / {operation.FormatFileSize(downloadUpdateData.TotalDownloadBytes)}";
|
||||||
|
PatchEvent.UpdateProgress(progress);
|
||||||
|
PatchEvent.UpdateDownloadSize(sizeText);
|
||||||
|
PatchEvent.UpdateStatus($"{data.packageName} 资源下载中...");
|
||||||
|
}
|
||||||
|
private void OnDownloadFinish(DownloaderFinishData downloaderFinishData)
|
||||||
|
{
|
||||||
|
PatchEvent.UpdateStatus("下载完成");
|
||||||
|
}
|
||||||
|
private void OnDownloadError(DownloadErrorData downloadErrorData)
|
||||||
|
{
|
||||||
|
PatchEvent.UpdateStatus($"下载失败:{downloadErrorData.FileName}\n{downloadErrorData.ErrorInfo}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
Assets/GameFramework/Runtime/Patch/PatchEvent.cs
Normal file
31
Assets/GameFramework/Runtime/Patch/PatchEvent.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Tuan.GameFramework
|
||||||
|
{
|
||||||
|
public static class PatchEvent
|
||||||
|
{
|
||||||
|
public static event Action<string> OnStatusUpdate;
|
||||||
|
public static event Action<float> OnProgressUpdate;
|
||||||
|
public static event Action<string> OnDownloadSizeUpdate;
|
||||||
|
public static event Action OnClosePatchWindow;
|
||||||
|
|
||||||
|
public static void UpdateStatus(string status)
|
||||||
|
{
|
||||||
|
OnStatusUpdate?.Invoke(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UpdateProgress(float progress)
|
||||||
|
{
|
||||||
|
OnProgressUpdate?.Invoke(progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UpdateDownloadSize(string sizeText)
|
||||||
|
{
|
||||||
|
OnDownloadSizeUpdate?.Invoke(sizeText);
|
||||||
|
}
|
||||||
|
public static void ClosePatchWindow()
|
||||||
|
{
|
||||||
|
OnClosePatchWindow?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
Assets/GameFramework/Runtime/Patch/PatchManager.cs
Normal file
22
Assets/GameFramework/Runtime/Patch/PatchManager.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using YooAsset;
|
||||||
|
|
||||||
|
namespace Tuan.GameFramework
|
||||||
|
{
|
||||||
|
public class PatchManager : Singleton<PatchManager>
|
||||||
|
{
|
||||||
|
public async UniTask<bool> StartOperation(EPlayMode playMode)
|
||||||
|
{
|
||||||
|
YooAssets.Initialize();
|
||||||
|
PreloadOperation _preloadOperation = new PreloadOperation(playMode);
|
||||||
|
await _preloadOperation.Execute();
|
||||||
|
|
||||||
|
MainOperation _mainOperation = new MainOperation(playMode);
|
||||||
|
await _mainOperation.Execute();
|
||||||
|
await HotDllLoader.Inst.LoadDepDll(YooAssets.GetPackage("Main"));
|
||||||
|
await HotDllLoader.Inst.LoadDll(YooAssets.GetPackage("Main"), "GameScripts.Main");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
362
Assets/GameFramework/Runtime/Patch/PatchOperation.cs
Normal file
362
Assets/GameFramework/Runtime/Patch/PatchOperation.cs
Normal file
@@ -0,0 +1,362 @@
|
|||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
using YooAsset;
|
||||||
|
using static YooAsset.DownloaderOperation;
|
||||||
|
|
||||||
|
namespace Tuan.GameFramework
|
||||||
|
{
|
||||||
|
public class PatchOperationData
|
||||||
|
{
|
||||||
|
public string packageName;
|
||||||
|
public EPlayMode playMode;
|
||||||
|
public bool useBuildinFileSystem;
|
||||||
|
public DownloadError downloadError;
|
||||||
|
public DownloaderFinish downloadFinish;
|
||||||
|
public DownloadUpdate downloadUpdate;
|
||||||
|
public int downloadingMaxNum = 10;
|
||||||
|
public int failedTryAgain = 3;
|
||||||
|
}
|
||||||
|
public class PatchOperation
|
||||||
|
{
|
||||||
|
public PatchOperationData data;
|
||||||
|
public ResourcePackage package;
|
||||||
|
public ResourceDownloaderOperation downloader;
|
||||||
|
public string packageVersion;
|
||||||
|
public string PkgVersionKey;
|
||||||
|
public PatchOperation(PatchOperationData data)
|
||||||
|
{
|
||||||
|
this.data = data;
|
||||||
|
PkgVersionKey = $"{Application.productName}_{data.packageName}";
|
||||||
|
#if !UNITY_EDITOR
|
||||||
|
PkgVersionKey = $"Editor_{Application.productName}_{data.packageName}";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#region 初始化相关
|
||||||
|
public async UniTask<bool> InitializePackage()
|
||||||
|
{
|
||||||
|
package = YooAssets.TryGetPackage(data.packageName);
|
||||||
|
if (package == null)
|
||||||
|
package = YooAssets.CreatePackage(data.packageName);
|
||||||
|
|
||||||
|
InitializationOperation initializationOperation = null;
|
||||||
|
switch (data.playMode)
|
||||||
|
{
|
||||||
|
case EPlayMode.EditorSimulateMode:
|
||||||
|
initializationOperation = InitializeEditorMode(package);
|
||||||
|
break;
|
||||||
|
case EPlayMode.OfflinePlayMode:
|
||||||
|
initializationOperation = InitializeOfflineMode(package);
|
||||||
|
break;
|
||||||
|
case EPlayMode.HostPlayMode:
|
||||||
|
initializationOperation = InitializeHostMode(package);
|
||||||
|
break;
|
||||||
|
case EPlayMode.WebPlayMode:
|
||||||
|
initializationOperation = InitializeWebPlayMode(package);
|
||||||
|
break;
|
||||||
|
case EPlayMode.CustomPlayMode:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
await initializationOperation.ToUniTask();
|
||||||
|
if (initializationOperation.Status != EOperationStatus.Succeed)
|
||||||
|
{
|
||||||
|
MessageBox.Show()
|
||||||
|
.SetTitle($"{data.packageName}初始化")
|
||||||
|
.SetContent($"{initializationOperation.Error}")
|
||||||
|
.AddButton("退出", (box) => { Application.Quit(); });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PatchEvent.UpdateStatus($"初始化成功{data.packageName}");
|
||||||
|
Debug.Log($"初始化成功{data.packageName}");
|
||||||
|
}
|
||||||
|
return initializationOperation.Status == EOperationStatus.Succeed;
|
||||||
|
}
|
||||||
|
private InitializationOperation InitializeEditorMode(ResourcePackage package)
|
||||||
|
{
|
||||||
|
var buildResult = EditorSimulateModeHelper.SimulateBuild(data.packageName);
|
||||||
|
var packageRoot = buildResult.PackageRootDirectory;
|
||||||
|
var createParameters = new EditorSimulateModeParameters();
|
||||||
|
createParameters.EditorFileSystemParameters = FileSystemParameters.CreateDefaultEditorFileSystemParameters(packageRoot);
|
||||||
|
return package.InitializeAsync(createParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
private InitializationOperation InitializeOfflineMode(ResourcePackage package)
|
||||||
|
{
|
||||||
|
var createParameters = new OfflinePlayModeParameters();
|
||||||
|
createParameters.BuildinFileSystemParameters = FileSystemParameters.CreateDefaultBuildinFileSystemParameters();
|
||||||
|
return package.InitializeAsync(createParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
private InitializationOperation InitializeHostMode(ResourcePackage package)
|
||||||
|
{
|
||||||
|
FileSystemParameters buildinFileSystemParams = null;
|
||||||
|
if (data.useBuildinFileSystem)
|
||||||
|
{
|
||||||
|
// 注意:设置参数COPY_BUILDIN_PACKAGE_MANIFEST,可以初始化的时候拷贝内置清单到沙盒目录
|
||||||
|
buildinFileSystemParams = FileSystemParameters.CreateDefaultBuildinFileSystemParameters();
|
||||||
|
buildinFileSystemParams.AddParameter(FileSystemParametersDefine.COPY_BUILDIN_PACKAGE_MANIFEST, true);
|
||||||
|
}
|
||||||
|
string defaultHostServer = GetHostServerURL();
|
||||||
|
string fallbackHostServer = GetHostServerURL();
|
||||||
|
IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
|
||||||
|
// 注意:设置参数INSTALL_CLEAR_MODE,可以解决覆盖安装的时候将拷贝的内置清单文件清理的问题。
|
||||||
|
var cacheFileSystemParams = FileSystemParameters.CreateDefaultCacheFileSystemParameters(remoteServices);
|
||||||
|
cacheFileSystemParams.AddParameter(FileSystemParametersDefine.INSTALL_CLEAR_MODE, EOverwriteInstallClearMode.ClearAllManifestFiles);
|
||||||
|
|
||||||
|
var createParameters = new HostPlayModeParameters();
|
||||||
|
createParameters.BuildinFileSystemParameters = buildinFileSystemParams;
|
||||||
|
createParameters.CacheFileSystemParameters = cacheFileSystemParams;
|
||||||
|
return package.InitializeAsync(createParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
private InitializationOperation InitializeWebPlayMode(ResourcePackage package)
|
||||||
|
{
|
||||||
|
#if UNITY_WEBGL && WEIXINMINIGAME && !UNITY_EDITOR
|
||||||
|
var createParameters = new WebPlayModeParameters();
|
||||||
|
string defaultHostServer = GetHostServerURL();
|
||||||
|
string fallbackHostServer = GetHostServerURL();
|
||||||
|
string packageRoot = $"{WeChatWASM.WX.env.USER_DATA_PATH}/__GAME_FILE_CACHE"; //注意:如果有子目录,请修改此处!
|
||||||
|
IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
|
||||||
|
createParameters.WebServerFileSystemParameters = WechatFileSystemCreater.CreateFileSystemParameters(packageRoot, remoteServices);
|
||||||
|
return package.InitializeAsync(createParameters);
|
||||||
|
#else
|
||||||
|
var createParameters = new WebPlayModeParameters();
|
||||||
|
createParameters.WebServerFileSystemParameters = FileSystemParameters.CreateDefaultWebServerFileSystemParameters();
|
||||||
|
return package.InitializeAsync(createParameters);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
private string GetHostServerURL()
|
||||||
|
{
|
||||||
|
string hostServerIP = $"https://home.gtuantuan.online:9444/{Application.productName}";
|
||||||
|
string appVersion = "v1";
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.Android)
|
||||||
|
// return $"{hostServerIP}/CDN/Android/{packageName}/{appVersion}";
|
||||||
|
return $"{hostServerIP}/CDN/PC/{data.packageName}/{appVersion}";
|
||||||
|
else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.iOS)
|
||||||
|
return $"{hostServerIP}/CDN/IPhone/{data.packageName}/{appVersion}";
|
||||||
|
else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.WebGL)
|
||||||
|
return $"{hostServerIP}/CDN/WebGL/{data.packageName}/{appVersion}";
|
||||||
|
else
|
||||||
|
return $"{hostServerIP}/CDN/PC/{data.packageName}/{appVersion}";
|
||||||
|
#else
|
||||||
|
if (Application.platform == RuntimePlatform.Android)
|
||||||
|
return $"{hostServerIP}/CDN/Android/{data.packageName}/{appVersion}";
|
||||||
|
else if (Application.platform == RuntimePlatform.IPhonePlayer)
|
||||||
|
return $"{hostServerIP}/CDN/IPhone/{data.packageName}/{appVersion}";
|
||||||
|
else if (Application.platform == RuntimePlatform.WebGLPlayer)
|
||||||
|
return $"{hostServerIP}/CDN/WebGL/{data.packageName}/{appVersion}";
|
||||||
|
else
|
||||||
|
return $"{hostServerIP}/CDN/PC/{data.packageName}/{appVersion}";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
private class RemoteServices : IRemoteServices
|
||||||
|
{
|
||||||
|
private readonly string _defaultHostServer;
|
||||||
|
private readonly string _fallbackHostServer;
|
||||||
|
|
||||||
|
public RemoteServices(string defaultHostServer, string fallbackHostServer)
|
||||||
|
{
|
||||||
|
_defaultHostServer = defaultHostServer;
|
||||||
|
_fallbackHostServer = fallbackHostServer;
|
||||||
|
}
|
||||||
|
string IRemoteServices.GetRemoteMainURL(string fileName)
|
||||||
|
{
|
||||||
|
return $"{_defaultHostServer}/{fileName}";
|
||||||
|
}
|
||||||
|
string IRemoteServices.GetRemoteFallbackURL(string fileName)
|
||||||
|
{
|
||||||
|
return $"{_fallbackHostServer}/{fileName}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region 版本和资源清单相关
|
||||||
|
public async UniTask<bool> RequestPackageVersion(bool showBox = true)
|
||||||
|
{
|
||||||
|
var operation = package.RequestPackageVersionAsync(true, 5);
|
||||||
|
await operation.ToUniTask();
|
||||||
|
if (operation.Status != EOperationStatus.Succeed)
|
||||||
|
{
|
||||||
|
if (showBox)
|
||||||
|
{
|
||||||
|
if (await CheckUseLocalVersion(operation))
|
||||||
|
{
|
||||||
|
string cachedVersion = GetCachedPackageVersion();
|
||||||
|
if (!string.IsNullOrEmpty(cachedVersion))
|
||||||
|
{
|
||||||
|
packageVersion = cachedVersion;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
packageVersion = operation.PackageVersion;
|
||||||
|
PatchEvent.UpdateStatus($"获取版本成功{data.packageName}");
|
||||||
|
Debug.Log($"获取版本成功{data.packageName}:{packageVersion}");
|
||||||
|
}
|
||||||
|
return operation.Status == EOperationStatus.Succeed;
|
||||||
|
}
|
||||||
|
public async UniTask<bool> CheckUseLocalVersion(RequestPackageVersionOperation operation)
|
||||||
|
{
|
||||||
|
var completionSource = new UniTaskCompletionSource<bool>();
|
||||||
|
MessageBox.Show()
|
||||||
|
.SetTitle($"{data.packageName}请求版本")
|
||||||
|
.SetContent($"{operation.Error}")
|
||||||
|
.AddButton("继续", (box) =>
|
||||||
|
{
|
||||||
|
completionSource.TrySetResult(true);
|
||||||
|
})
|
||||||
|
.AddButton("退出", (box) =>
|
||||||
|
{
|
||||||
|
completionSource.TrySetResult(false);
|
||||||
|
Application.Quit();
|
||||||
|
});
|
||||||
|
bool shouldContinue = await completionSource.Task;
|
||||||
|
return shouldContinue;
|
||||||
|
}
|
||||||
|
public async Task<string> GetBuildinPackageVersion()
|
||||||
|
{
|
||||||
|
var operation = new GetBuildinPackageVersionOperation(data.packageName);
|
||||||
|
YooAssets.StartOperation(operation);
|
||||||
|
await operation;
|
||||||
|
if (operation.Status == EOperationStatus.Succeed)
|
||||||
|
{
|
||||||
|
return operation.PackageVersion;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string GetCachedPackageVersion()
|
||||||
|
{
|
||||||
|
if (PlayerPrefs.HasKey(PkgVersionKey))
|
||||||
|
{
|
||||||
|
return PlayerPrefs.GetString(PkgVersionKey);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveVersionToCache()
|
||||||
|
{
|
||||||
|
PlayerPrefs.SetString(PkgVersionKey, packageVersion);
|
||||||
|
PlayerPrefs.Save();
|
||||||
|
PatchEvent.UpdateStatus($"更新完成{data.packageName}");
|
||||||
|
Debug.Log($"更新{data.packageName}完成,版本号{packageVersion}");
|
||||||
|
|
||||||
|
}
|
||||||
|
public async UniTask<bool> UpdatePackageManifest(bool showBox = true)
|
||||||
|
{
|
||||||
|
var operation = package.UpdatePackageManifestAsync(packageVersion, 10);
|
||||||
|
await operation.ToUniTask();
|
||||||
|
if (operation.Status != EOperationStatus.Succeed)
|
||||||
|
{
|
||||||
|
if (showBox)
|
||||||
|
{
|
||||||
|
MessageBox.Show()
|
||||||
|
.SetTitle($"{data.packageName}更新清单")
|
||||||
|
.SetContent($"{operation.Error}")
|
||||||
|
.AddButton("退出", (box) => { Application.Quit(); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PatchEvent.UpdateStatus($"获取资源清单成功{data.packageName}");
|
||||||
|
Debug.Log($"获取资源清单成功{data.packageName}");
|
||||||
|
}
|
||||||
|
return operation.Status == EOperationStatus.Succeed;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region 下载相关
|
||||||
|
public bool CreateDownloader()
|
||||||
|
{
|
||||||
|
downloader = package.CreateResourceDownloader(data.downloadingMaxNum, data.failedTryAgain);
|
||||||
|
downloader.DownloadErrorCallback = data.downloadError;
|
||||||
|
downloader.DownloadFinishCallback = data.downloadFinish;
|
||||||
|
downloader.DownloadUpdateCallback = data.downloadUpdate;
|
||||||
|
if (downloader.TotalDownloadCount == 0) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public async UniTask<bool> CheckDownloadOrSkip()
|
||||||
|
{
|
||||||
|
var completionSource = new UniTaskCompletionSource<bool>();
|
||||||
|
MessageBox.Show()
|
||||||
|
.SetTitle($"{data.packageName}发现更新")
|
||||||
|
.SetContent($"发现资源更新\n{GetCachedPackageVersion()}=>{packageVersion}: {FormatFileSize(downloader.TotalDownloadBytes)}")
|
||||||
|
.AddButton("下载", async (box) =>
|
||||||
|
{
|
||||||
|
bool success = await DownloadPackageFiles();
|
||||||
|
completionSource.TrySetResult(success);
|
||||||
|
})
|
||||||
|
.AddButton("跳过", async (box) =>
|
||||||
|
{
|
||||||
|
downloader.CancelDownload();
|
||||||
|
packageVersion = GetCachedPackageVersion();
|
||||||
|
await UpdatePackageManifest();
|
||||||
|
completionSource.TrySetResult(true);
|
||||||
|
})
|
||||||
|
.AddButton("退出", (box) =>
|
||||||
|
{
|
||||||
|
downloader.CancelDownload();
|
||||||
|
completionSource.TrySetResult(false);
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
UnityEditor.EditorApplication.isPlaying = false;
|
||||||
|
#else
|
||||||
|
Application.Quit();
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
bool shouldContinue = await completionSource.Task;
|
||||||
|
return shouldContinue;
|
||||||
|
}
|
||||||
|
public async UniTask<bool> DownloadPackageFiles(bool showBox = true)
|
||||||
|
{
|
||||||
|
if (downloader.TotalDownloadCount == 0)
|
||||||
|
return true;
|
||||||
|
Debug.Log($"{data.packageName} DownloadPackageFiles {downloader.TotalDownloadCount}");
|
||||||
|
downloader.BeginDownload();
|
||||||
|
await downloader.ToUniTask();
|
||||||
|
if (downloader.Status != EOperationStatus.Succeed)
|
||||||
|
{
|
||||||
|
if (showBox)
|
||||||
|
{
|
||||||
|
MessageBox.Show()
|
||||||
|
.SetTitle($"{data.packageName}下载文件")
|
||||||
|
.SetContent($"{downloader.Error}")
|
||||||
|
.AddButton("退出", (box) => { Application.Quit(); });
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return downloader.Status == EOperationStatus.Succeed;
|
||||||
|
}
|
||||||
|
public async UniTask<bool> ClearCacheBundle(bool showBox = true)
|
||||||
|
{
|
||||||
|
var operation = package.ClearCacheFilesAsync(EFileClearMode.ClearUnusedBundleFiles);
|
||||||
|
await operation.ToUniTask();
|
||||||
|
if (operation.Status != EOperationStatus.Succeed)
|
||||||
|
{
|
||||||
|
if (showBox)
|
||||||
|
{
|
||||||
|
MessageBox.Show()
|
||||||
|
.SetTitle($"{data.packageName}清除缓存")
|
||||||
|
.SetContent($"{operation.Error}")
|
||||||
|
.AddButton("退出", (box) => { Application.Quit(); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return operation.Status == EOperationStatus.Succeed;
|
||||||
|
}
|
||||||
|
public string FormatFileSize(long size)
|
||||||
|
{
|
||||||
|
if (size < 1024 * 1024)
|
||||||
|
return $"{(size / 1024f):F1}KB";
|
||||||
|
else
|
||||||
|
return $"{size / 1024f / 1024f:F1}MB";
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
91
Assets/GameFramework/Runtime/Patch/PreloadOperation.cs
Normal file
91
Assets/GameFramework/Runtime/Patch/PreloadOperation.cs
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
using YooAsset;
|
||||||
|
|
||||||
|
namespace Tuan.GameFramework
|
||||||
|
{
|
||||||
|
public class PreloadOperation
|
||||||
|
{
|
||||||
|
PatchOperationData data;
|
||||||
|
PatchOperation operation;
|
||||||
|
public PreloadOperation(EPlayMode playMode)
|
||||||
|
{
|
||||||
|
data = new PatchOperationData();
|
||||||
|
data.packageName = "Preload";
|
||||||
|
data.playMode = playMode;
|
||||||
|
data.useBuildinFileSystem = true;
|
||||||
|
data.downloadingMaxNum = 10;
|
||||||
|
data.failedTryAgain = 3;
|
||||||
|
|
||||||
|
operation = new PatchOperation(data);
|
||||||
|
}
|
||||||
|
public async UniTask Execute()
|
||||||
|
{
|
||||||
|
#if !UNITY_EDITOR
|
||||||
|
CheckIsOffline();
|
||||||
|
#endif
|
||||||
|
if (!await operation.InitializePackage()) return;
|
||||||
|
var version = await GetBestPackageVersion();
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
if (!await operation.RequestPackageVersion()) return;
|
||||||
|
version = operation.packageVersion;
|
||||||
|
#endif
|
||||||
|
//获取版本失败
|
||||||
|
if (version == null)
|
||||||
|
{
|
||||||
|
MessageBox.Show()
|
||||||
|
.SetTitle($"{operation.data.packageName}获取版本")
|
||||||
|
.SetContent("获取版本失败")
|
||||||
|
.AddButton("退出", (box) => { Application.Quit(); });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
operation.packageVersion = version;
|
||||||
|
if (!await operation.UpdatePackageManifest()) return;
|
||||||
|
await HotDllLoader.Inst.LoadDll(YooAssets.GetPackage("Preload"), "GameScripts.Preload");
|
||||||
|
await LoadAndShowPatchWindow();
|
||||||
|
MainUICanvas.Inst.InitBg.SetActive(false);
|
||||||
|
_ = UpdatePreloadPackage();
|
||||||
|
}
|
||||||
|
void CheckIsOffline()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(operation.GetCachedPackageVersion()))
|
||||||
|
{
|
||||||
|
operation.data.playMode = EPlayMode.OfflinePlayMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async Task<string> GetBestPackageVersion()
|
||||||
|
{
|
||||||
|
string cachedVersion = operation.GetCachedPackageVersion();
|
||||||
|
if (!string.IsNullOrEmpty(cachedVersion))
|
||||||
|
{
|
||||||
|
return cachedVersion;
|
||||||
|
}
|
||||||
|
string buildinVersion = await operation.GetBuildinPackageVersion();
|
||||||
|
if (!string.IsNullOrEmpty(buildinVersion))
|
||||||
|
{
|
||||||
|
return buildinVersion;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
private async UniTask LoadAndShowPatchWindow()
|
||||||
|
{
|
||||||
|
var assetHandle = operation.package.LoadAssetAsync<GameObject>("PatchWindow");
|
||||||
|
await assetHandle.ToUniTask();
|
||||||
|
if (assetHandle.Status == EOperationStatus.Succeed)
|
||||||
|
GameObject.Instantiate(assetHandle.AssetObject, MainUICanvas.Inst.Medium);
|
||||||
|
Debug.Log("创建热更信息界面");
|
||||||
|
}
|
||||||
|
private async UniTask UpdatePreloadPackage()
|
||||||
|
{
|
||||||
|
if (!await operation.RequestPackageVersion(false)) return;
|
||||||
|
if (!await operation.UpdatePackageManifest(false)) return;
|
||||||
|
if (operation.CreateDownloader())
|
||||||
|
{
|
||||||
|
if (!await operation.DownloadPackageFiles()) return;
|
||||||
|
}
|
||||||
|
if (!await operation.ClearCacheBundle()) return;
|
||||||
|
operation.SaveVersionToCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
using Cysharp.Threading.Tasks;
|
|
||||||
using HybridCLR;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using UnityEngine;
|
|
||||||
using YooAsset;
|
|
||||||
|
|
||||||
public class HotDllLoader : Singleton<HotDllLoader>
|
|
||||||
{
|
|
||||||
public List<string> DepDlls = new List<string>()
|
|
||||||
{
|
|
||||||
"mscorlib.dll",
|
|
||||||
"System.dll",
|
|
||||||
"System.Core.dll",
|
|
||||||
};
|
|
||||||
public async UniTask LoadDll(ResourcePackage package, string dll)
|
|
||||||
{
|
|
||||||
if (package.GetAssetInfo(dll).Error == string.Empty)
|
|
||||||
{
|
|
||||||
AssetHandle handle = package.LoadAssetAsync<TextAsset>(dll);
|
|
||||||
await handle.ToUniTask();
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
Assembly hotUpdateAss = System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == dll.Replace(".dll", ""));
|
|
||||||
#else
|
|
||||||
Assembly hotUpdateAss = Assembly.Load((handle.AssetObject as TextAsset).bytes);
|
|
||||||
#endif
|
|
||||||
Debug.Log($"加载{dll}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public async UniTask LoadDepDll(ResourcePackage package)
|
|
||||||
{
|
|
||||||
foreach (string dll in DepDlls)
|
|
||||||
{
|
|
||||||
if (package.GetAssetInfo(dll).Error == string.Empty)
|
|
||||||
{
|
|
||||||
AssetHandle handle = package.LoadAssetAsync<TextAsset>(dll);
|
|
||||||
await handle.ToUniTask();
|
|
||||||
RuntimeApi.LoadMetadataForAOTAssembly((handle.AssetObject as TextAsset).bytes, HomologousImageMode.SuperSet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
using Cysharp.Threading.Tasks;
|
|
||||||
using YooAsset;
|
|
||||||
|
|
||||||
public class MainOperation
|
|
||||||
{
|
|
||||||
PatchOperationData data;
|
|
||||||
PatchOperation operation;
|
|
||||||
bool autoDownload;
|
|
||||||
public MainOperation(EPlayMode playMode, bool autoDownload = false)
|
|
||||||
{
|
|
||||||
data = new PatchOperationData();
|
|
||||||
data.packageName = "Main";
|
|
||||||
data.playMode = playMode;
|
|
||||||
data.useBuildinFileSystem = false;
|
|
||||||
data.downloadingMaxNum = 10;
|
|
||||||
data.failedTryAgain = 3;
|
|
||||||
data.downloadUpdate = OnDownloadUpdate;
|
|
||||||
data.downloadFinish = OnDownloadFinish;
|
|
||||||
data.downloadError = OnDownloadError;
|
|
||||||
|
|
||||||
operation = new PatchOperation(data);
|
|
||||||
this.autoDownload = autoDownload;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async UniTask Execute()
|
|
||||||
{
|
|
||||||
PatchEvent.UpdateProgress(0f);
|
|
||||||
if (!await operation.InitializePackage()) return;
|
|
||||||
if (!await operation.RequestPackageVersion()) return;
|
|
||||||
if (!await operation.UpdatePackageManifest()) return;
|
|
||||||
if (operation.CreateDownloader())
|
|
||||||
{
|
|
||||||
if (autoDownload)
|
|
||||||
{
|
|
||||||
if (!await operation.DownloadPackageFiles()) return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!await operation.CheckDownloadOrSkip()) return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!await operation.ClearCacheBundle()) return;
|
|
||||||
operation.SaveVersionToCache();
|
|
||||||
YooAssets.SetDefaultPackage(operation.package);
|
|
||||||
}
|
|
||||||
private void OnDownloadUpdate(DownloadUpdateData downloadUpdateData)
|
|
||||||
{
|
|
||||||
float progress = (float)downloadUpdateData.CurrentDownloadBytes / downloadUpdateData.TotalDownloadBytes;
|
|
||||||
string sizeText = $"{operation.FormatFileSize(downloadUpdateData.CurrentDownloadBytes)} / {operation.FormatFileSize(downloadUpdateData.TotalDownloadBytes)}";
|
|
||||||
PatchEvent.UpdateProgress(progress);
|
|
||||||
PatchEvent.UpdateDownloadSize(sizeText);
|
|
||||||
PatchEvent.UpdateStatus($"{data.packageName} 资源下载中...");
|
|
||||||
}
|
|
||||||
private void OnDownloadFinish(DownloaderFinishData downloaderFinishData)
|
|
||||||
{
|
|
||||||
PatchEvent.UpdateStatus("下载完成");
|
|
||||||
}
|
|
||||||
private void OnDownloadError(DownloadErrorData downloadErrorData)
|
|
||||||
{
|
|
||||||
PatchEvent.UpdateStatus($"下载失败:{downloadErrorData.FileName}\n{downloadErrorData.ErrorInfo}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
public static class PatchEvent
|
|
||||||
{
|
|
||||||
public static event Action<string> OnStatusUpdate;
|
|
||||||
public static event Action<float> OnProgressUpdate;
|
|
||||||
public static event Action<string> OnDownloadSizeUpdate;
|
|
||||||
public static event Action OnClosePatchWindow;
|
|
||||||
|
|
||||||
public static void UpdateStatus(string status)
|
|
||||||
{
|
|
||||||
OnStatusUpdate?.Invoke(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void UpdateProgress(float progress)
|
|
||||||
{
|
|
||||||
OnProgressUpdate?.Invoke(progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void UpdateDownloadSize(string sizeText)
|
|
||||||
{
|
|
||||||
OnDownloadSizeUpdate?.Invoke(sizeText);
|
|
||||||
}
|
|
||||||
public static void ClosePatchWindow()
|
|
||||||
{
|
|
||||||
OnClosePatchWindow?.Invoke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
using Cysharp.Threading.Tasks;
|
|
||||||
using YooAsset;
|
|
||||||
public class PatchManager : Singleton<PatchManager>
|
|
||||||
{
|
|
||||||
public async UniTask<bool> StartOperation(EPlayMode playMode)
|
|
||||||
{
|
|
||||||
YooAssets.Initialize();
|
|
||||||
PreloadOperation _preloadOperation = new PreloadOperation(playMode);
|
|
||||||
await _preloadOperation.Execute();
|
|
||||||
|
|
||||||
MainOperation _mainOperation = new MainOperation(playMode);
|
|
||||||
await _mainOperation.Execute();
|
|
||||||
await HotDllLoader.Inst.LoadDepDll(YooAssets.GetPackage("Main"));
|
|
||||||
await HotDllLoader.Inst.LoadDll(YooAssets.GetPackage("Main"), "GameScripts.Main");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,358 +0,0 @@
|
|||||||
using Cysharp.Threading.Tasks;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
|
||||||
using YooAsset;
|
|
||||||
using static YooAsset.DownloaderOperation;
|
|
||||||
public class PatchOperationData
|
|
||||||
{
|
|
||||||
public string packageName;
|
|
||||||
public EPlayMode playMode;
|
|
||||||
public bool useBuildinFileSystem;
|
|
||||||
public DownloadError downloadError;
|
|
||||||
public DownloaderFinish downloadFinish;
|
|
||||||
public DownloadUpdate downloadUpdate;
|
|
||||||
public int downloadingMaxNum = 10;
|
|
||||||
public int failedTryAgain = 3;
|
|
||||||
}
|
|
||||||
public class PatchOperation
|
|
||||||
{
|
|
||||||
public PatchOperationData data;
|
|
||||||
public ResourcePackage package;
|
|
||||||
public ResourceDownloaderOperation downloader;
|
|
||||||
public string packageVersion;
|
|
||||||
public string PkgVersionKey;
|
|
||||||
public PatchOperation(PatchOperationData data)
|
|
||||||
{
|
|
||||||
this.data = data;
|
|
||||||
PkgVersionKey = $"{Application.productName}_{data.packageName}";
|
|
||||||
#if !UNITY_EDITOR
|
|
||||||
PkgVersionKey = $"Editor_{Application.productName}_{data.packageName}";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#region 初始化相关
|
|
||||||
public async UniTask<bool> InitializePackage()
|
|
||||||
{
|
|
||||||
package = YooAssets.TryGetPackage(data.packageName);
|
|
||||||
if (package == null)
|
|
||||||
package = YooAssets.CreatePackage(data.packageName);
|
|
||||||
|
|
||||||
InitializationOperation initializationOperation = null;
|
|
||||||
switch (data.playMode)
|
|
||||||
{
|
|
||||||
case EPlayMode.EditorSimulateMode:
|
|
||||||
initializationOperation = InitializeEditorMode(package);
|
|
||||||
break;
|
|
||||||
case EPlayMode.OfflinePlayMode:
|
|
||||||
initializationOperation = InitializeOfflineMode(package);
|
|
||||||
break;
|
|
||||||
case EPlayMode.HostPlayMode:
|
|
||||||
initializationOperation = InitializeHostMode(package);
|
|
||||||
break;
|
|
||||||
case EPlayMode.WebPlayMode:
|
|
||||||
initializationOperation = InitializeWebPlayMode(package);
|
|
||||||
break;
|
|
||||||
case EPlayMode.CustomPlayMode:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
await initializationOperation.ToUniTask();
|
|
||||||
if (initializationOperation.Status != EOperationStatus.Succeed)
|
|
||||||
{
|
|
||||||
MessageBox.Show()
|
|
||||||
.SetTitle($"{data.packageName}初始化")
|
|
||||||
.SetContent($"{initializationOperation.Error}")
|
|
||||||
.AddButton("退出", (box) => { Application.Quit(); });
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PatchEvent.UpdateStatus($"初始化成功{data.packageName}");
|
|
||||||
Debug.Log($"初始化成功{data.packageName}");
|
|
||||||
}
|
|
||||||
return initializationOperation.Status == EOperationStatus.Succeed;
|
|
||||||
}
|
|
||||||
private InitializationOperation InitializeEditorMode(ResourcePackage package)
|
|
||||||
{
|
|
||||||
var buildResult = EditorSimulateModeHelper.SimulateBuild(data.packageName);
|
|
||||||
var packageRoot = buildResult.PackageRootDirectory;
|
|
||||||
var createParameters = new EditorSimulateModeParameters();
|
|
||||||
createParameters.EditorFileSystemParameters = FileSystemParameters.CreateDefaultEditorFileSystemParameters(packageRoot);
|
|
||||||
return package.InitializeAsync(createParameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
private InitializationOperation InitializeOfflineMode(ResourcePackage package)
|
|
||||||
{
|
|
||||||
var createParameters = new OfflinePlayModeParameters();
|
|
||||||
createParameters.BuildinFileSystemParameters = FileSystemParameters.CreateDefaultBuildinFileSystemParameters();
|
|
||||||
return package.InitializeAsync(createParameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
private InitializationOperation InitializeHostMode(ResourcePackage package)
|
|
||||||
{
|
|
||||||
FileSystemParameters buildinFileSystemParams = null;
|
|
||||||
if (data.useBuildinFileSystem)
|
|
||||||
{
|
|
||||||
// 注意:设置参数COPY_BUILDIN_PACKAGE_MANIFEST,可以初始化的时候拷贝内置清单到沙盒目录
|
|
||||||
buildinFileSystemParams = FileSystemParameters.CreateDefaultBuildinFileSystemParameters();
|
|
||||||
buildinFileSystemParams.AddParameter(FileSystemParametersDefine.COPY_BUILDIN_PACKAGE_MANIFEST, true);
|
|
||||||
}
|
|
||||||
string defaultHostServer = GetHostServerURL();
|
|
||||||
string fallbackHostServer = GetHostServerURL();
|
|
||||||
IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
|
|
||||||
// 注意:设置参数INSTALL_CLEAR_MODE,可以解决覆盖安装的时候将拷贝的内置清单文件清理的问题。
|
|
||||||
var cacheFileSystemParams = FileSystemParameters.CreateDefaultCacheFileSystemParameters(remoteServices);
|
|
||||||
cacheFileSystemParams.AddParameter(FileSystemParametersDefine.INSTALL_CLEAR_MODE, EOverwriteInstallClearMode.ClearAllManifestFiles);
|
|
||||||
|
|
||||||
var createParameters = new HostPlayModeParameters();
|
|
||||||
createParameters.BuildinFileSystemParameters = buildinFileSystemParams;
|
|
||||||
createParameters.CacheFileSystemParameters = cacheFileSystemParams;
|
|
||||||
return package.InitializeAsync(createParameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
private InitializationOperation InitializeWebPlayMode(ResourcePackage package)
|
|
||||||
{
|
|
||||||
#if UNITY_WEBGL && WEIXINMINIGAME && !UNITY_EDITOR
|
|
||||||
var createParameters = new WebPlayModeParameters();
|
|
||||||
string defaultHostServer = GetHostServerURL();
|
|
||||||
string fallbackHostServer = GetHostServerURL();
|
|
||||||
string packageRoot = $"{WeChatWASM.WX.env.USER_DATA_PATH}/__GAME_FILE_CACHE"; //注意:如果有子目录,请修改此处!
|
|
||||||
IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
|
|
||||||
createParameters.WebServerFileSystemParameters = WechatFileSystemCreater.CreateFileSystemParameters(packageRoot, remoteServices);
|
|
||||||
return package.InitializeAsync(createParameters);
|
|
||||||
#else
|
|
||||||
var createParameters = new WebPlayModeParameters();
|
|
||||||
createParameters.WebServerFileSystemParameters = FileSystemParameters.CreateDefaultWebServerFileSystemParameters();
|
|
||||||
return package.InitializeAsync(createParameters);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
private string GetHostServerURL()
|
|
||||||
{
|
|
||||||
string hostServerIP = $"https://home.gtuantuan.online:9444/{Application.productName}";
|
|
||||||
string appVersion = "v1";
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.Android)
|
|
||||||
// return $"{hostServerIP}/CDN/Android/{packageName}/{appVersion}";
|
|
||||||
return $"{hostServerIP}/CDN/PC/{data.packageName}/{appVersion}";
|
|
||||||
else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.iOS)
|
|
||||||
return $"{hostServerIP}/CDN/IPhone/{data.packageName}/{appVersion}";
|
|
||||||
else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.WebGL)
|
|
||||||
return $"{hostServerIP}/CDN/WebGL/{data.packageName}/{appVersion}";
|
|
||||||
else
|
|
||||||
return $"{hostServerIP}/CDN/PC/{data.packageName}/{appVersion}";
|
|
||||||
#else
|
|
||||||
if (Application.platform == RuntimePlatform.Android)
|
|
||||||
return $"{hostServerIP}/CDN/Android/{data.packageName}/{appVersion}";
|
|
||||||
else if (Application.platform == RuntimePlatform.IPhonePlayer)
|
|
||||||
return $"{hostServerIP}/CDN/IPhone/{data.packageName}/{appVersion}";
|
|
||||||
else if (Application.platform == RuntimePlatform.WebGLPlayer)
|
|
||||||
return $"{hostServerIP}/CDN/WebGL/{data.packageName}/{appVersion}";
|
|
||||||
else
|
|
||||||
return $"{hostServerIP}/CDN/PC/{data.packageName}/{appVersion}";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
private class RemoteServices : IRemoteServices
|
|
||||||
{
|
|
||||||
private readonly string _defaultHostServer;
|
|
||||||
private readonly string _fallbackHostServer;
|
|
||||||
|
|
||||||
public RemoteServices(string defaultHostServer, string fallbackHostServer)
|
|
||||||
{
|
|
||||||
_defaultHostServer = defaultHostServer;
|
|
||||||
_fallbackHostServer = fallbackHostServer;
|
|
||||||
}
|
|
||||||
string IRemoteServices.GetRemoteMainURL(string fileName)
|
|
||||||
{
|
|
||||||
return $"{_defaultHostServer}/{fileName}";
|
|
||||||
}
|
|
||||||
string IRemoteServices.GetRemoteFallbackURL(string fileName)
|
|
||||||
{
|
|
||||||
return $"{_fallbackHostServer}/{fileName}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
#region 版本和资源清单相关
|
|
||||||
public async UniTask<bool> RequestPackageVersion(bool showBox = true)
|
|
||||||
{
|
|
||||||
var operation = package.RequestPackageVersionAsync(true, 5);
|
|
||||||
await operation.ToUniTask();
|
|
||||||
if (operation.Status != EOperationStatus.Succeed)
|
|
||||||
{
|
|
||||||
if (showBox)
|
|
||||||
{
|
|
||||||
if(await CheckUseLocalVersion(operation))
|
|
||||||
{
|
|
||||||
string cachedVersion = GetCachedPackageVersion();
|
|
||||||
if (!string.IsNullOrEmpty(cachedVersion))
|
|
||||||
{
|
|
||||||
packageVersion = cachedVersion;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
packageVersion = operation.PackageVersion;
|
|
||||||
PatchEvent.UpdateStatus($"获取版本成功{data.packageName}");
|
|
||||||
Debug.Log($"获取版本成功{data.packageName}:{packageVersion}");
|
|
||||||
}
|
|
||||||
return operation.Status == EOperationStatus.Succeed;
|
|
||||||
}
|
|
||||||
public async UniTask<bool> CheckUseLocalVersion(RequestPackageVersionOperation operation)
|
|
||||||
{
|
|
||||||
var completionSource = new UniTaskCompletionSource<bool>();
|
|
||||||
MessageBox.Show()
|
|
||||||
.SetTitle($"{data.packageName}请求版本")
|
|
||||||
.SetContent($"{operation.Error}")
|
|
||||||
.AddButton("继续", (box) =>
|
|
||||||
{
|
|
||||||
completionSource.TrySetResult(true);
|
|
||||||
})
|
|
||||||
.AddButton("退出", (box) =>
|
|
||||||
{
|
|
||||||
completionSource.TrySetResult(false);
|
|
||||||
Application.Quit();
|
|
||||||
});
|
|
||||||
bool shouldContinue = await completionSource.Task;
|
|
||||||
return shouldContinue;
|
|
||||||
}
|
|
||||||
public async Task<string> GetBuildinPackageVersion()
|
|
||||||
{
|
|
||||||
var operation = new GetBuildinPackageVersionOperation(data.packageName);
|
|
||||||
YooAssets.StartOperation(operation);
|
|
||||||
await operation;
|
|
||||||
if (operation.Status == EOperationStatus.Succeed)
|
|
||||||
{
|
|
||||||
return operation.PackageVersion;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public string GetCachedPackageVersion()
|
|
||||||
{
|
|
||||||
if (PlayerPrefs.HasKey(PkgVersionKey))
|
|
||||||
{
|
|
||||||
return PlayerPrefs.GetString(PkgVersionKey);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SaveVersionToCache()
|
|
||||||
{
|
|
||||||
PlayerPrefs.SetString(PkgVersionKey, packageVersion);
|
|
||||||
PlayerPrefs.Save();
|
|
||||||
PatchEvent.UpdateStatus($"更新完成{data.packageName}");
|
|
||||||
Debug.Log($"更新{data.packageName}完成,版本号{packageVersion}");
|
|
||||||
|
|
||||||
}
|
|
||||||
public async UniTask<bool> UpdatePackageManifest(bool showBox = true)
|
|
||||||
{
|
|
||||||
var operation = package.UpdatePackageManifestAsync(packageVersion,10);
|
|
||||||
await operation.ToUniTask();
|
|
||||||
if (operation.Status != EOperationStatus.Succeed)
|
|
||||||
{
|
|
||||||
if (showBox)
|
|
||||||
{
|
|
||||||
MessageBox.Show()
|
|
||||||
.SetTitle($"{data.packageName}更新清单")
|
|
||||||
.SetContent($"{operation.Error}")
|
|
||||||
.AddButton("退出", (box) => { Application.Quit(); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PatchEvent.UpdateStatus($"获取资源清单成功{data.packageName}");
|
|
||||||
Debug.Log($"获取资源清单成功{data.packageName}");
|
|
||||||
}
|
|
||||||
return operation.Status == EOperationStatus.Succeed;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
#region 下载相关
|
|
||||||
public bool CreateDownloader()
|
|
||||||
{
|
|
||||||
downloader = package.CreateResourceDownloader(data.downloadingMaxNum, data.failedTryAgain);
|
|
||||||
downloader.DownloadErrorCallback = data.downloadError;
|
|
||||||
downloader.DownloadFinishCallback = data.downloadFinish;
|
|
||||||
downloader.DownloadUpdateCallback = data.downloadUpdate;
|
|
||||||
if (downloader.TotalDownloadCount == 0) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public async UniTask<bool> CheckDownloadOrSkip()
|
|
||||||
{
|
|
||||||
var completionSource = new UniTaskCompletionSource<bool>();
|
|
||||||
MessageBox.Show()
|
|
||||||
.SetTitle($"{data.packageName}发现更新")
|
|
||||||
.SetContent($"发现资源更新\n{GetCachedPackageVersion()}=>{packageVersion}: {FormatFileSize(downloader.TotalDownloadBytes)}")
|
|
||||||
.AddButton("下载", async (box) =>
|
|
||||||
{
|
|
||||||
bool success = await DownloadPackageFiles();
|
|
||||||
completionSource.TrySetResult(success);
|
|
||||||
})
|
|
||||||
.AddButton("跳过", async (box) =>
|
|
||||||
{
|
|
||||||
downloader.CancelDownload();
|
|
||||||
packageVersion = GetCachedPackageVersion();
|
|
||||||
await UpdatePackageManifest();
|
|
||||||
completionSource.TrySetResult(true);
|
|
||||||
})
|
|
||||||
.AddButton("退出", (box) =>
|
|
||||||
{
|
|
||||||
downloader.CancelDownload();
|
|
||||||
completionSource.TrySetResult(false);
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
UnityEditor.EditorApplication.isPlaying = false;
|
|
||||||
#else
|
|
||||||
Application.Quit();
|
|
||||||
#endif
|
|
||||||
});
|
|
||||||
bool shouldContinue = await completionSource.Task;
|
|
||||||
return shouldContinue;
|
|
||||||
}
|
|
||||||
public async UniTask<bool> DownloadPackageFiles(bool showBox = true)
|
|
||||||
{
|
|
||||||
if (downloader.TotalDownloadCount == 0)
|
|
||||||
return true;
|
|
||||||
Debug.Log($"{data.packageName} DownloadPackageFiles {downloader.TotalDownloadCount}");
|
|
||||||
downloader.BeginDownload();
|
|
||||||
await downloader.ToUniTask();
|
|
||||||
if (downloader.Status != EOperationStatus.Succeed)
|
|
||||||
{
|
|
||||||
if (showBox)
|
|
||||||
{
|
|
||||||
MessageBox.Show()
|
|
||||||
.SetTitle($"{data.packageName}下载文件")
|
|
||||||
.SetContent($"{downloader.Error}")
|
|
||||||
.AddButton("退出", (box) => { Application.Quit(); });
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return downloader.Status == EOperationStatus.Succeed;
|
|
||||||
}
|
|
||||||
public async UniTask<bool> ClearCacheBundle(bool showBox = true)
|
|
||||||
{
|
|
||||||
var operation = package.ClearCacheFilesAsync(EFileClearMode.ClearUnusedBundleFiles);
|
|
||||||
await operation.ToUniTask();
|
|
||||||
if (operation.Status != EOperationStatus.Succeed)
|
|
||||||
{
|
|
||||||
if (showBox)
|
|
||||||
{
|
|
||||||
MessageBox.Show()
|
|
||||||
.SetTitle($"{data.packageName}清除缓存")
|
|
||||||
.SetContent($"{operation.Error}")
|
|
||||||
.AddButton("退出", (box) => { Application.Quit(); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return operation.Status == EOperationStatus.Succeed;
|
|
||||||
}
|
|
||||||
public string FormatFileSize(long size)
|
|
||||||
{
|
|
||||||
if (size < 1024 * 1024)
|
|
||||||
return $"{(size / 1024f):F1}KB";
|
|
||||||
else
|
|
||||||
return $"{size / 1024f / 1024f:F1}MB";
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
using Cysharp.Threading.Tasks;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
|
||||||
using YooAsset;
|
|
||||||
|
|
||||||
public class PreloadOperation
|
|
||||||
{
|
|
||||||
PatchOperationData data;
|
|
||||||
PatchOperation operation;
|
|
||||||
public PreloadOperation(EPlayMode playMode)
|
|
||||||
{
|
|
||||||
data = new PatchOperationData();
|
|
||||||
data.packageName = "Preload";
|
|
||||||
data.playMode = playMode;
|
|
||||||
data.useBuildinFileSystem = true;
|
|
||||||
data.downloadingMaxNum = 10;
|
|
||||||
data.failedTryAgain = 3;
|
|
||||||
|
|
||||||
operation = new PatchOperation(data);
|
|
||||||
}
|
|
||||||
public async UniTask Execute()
|
|
||||||
{
|
|
||||||
#if !UNITY_EDITOR
|
|
||||||
CheckIsOffline();
|
|
||||||
#endif
|
|
||||||
if (!await operation.InitializePackage()) return;
|
|
||||||
var version = await GetBestPackageVersion();
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
if (!await operation.RequestPackageVersion()) return;
|
|
||||||
version = operation.packageVersion;
|
|
||||||
#endif
|
|
||||||
//获取版本失败
|
|
||||||
if (version == null)
|
|
||||||
{
|
|
||||||
MessageBox.Show()
|
|
||||||
.SetTitle($"{operation.data.packageName}获取版本")
|
|
||||||
.SetContent("获取版本失败")
|
|
||||||
.AddButton("退出", (box) => { Application.Quit(); });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
operation.packageVersion = version;
|
|
||||||
if (!await operation.UpdatePackageManifest()) return;
|
|
||||||
await HotDllLoader.Inst.LoadDll(YooAssets.GetPackage("Preload"), "GameScripts.Preload");
|
|
||||||
await LoadAndShowPatchWindow();
|
|
||||||
MainUICanvas.Inst.InitBg.SetActive(false);
|
|
||||||
_ = UpdatePreloadPackage();
|
|
||||||
}
|
|
||||||
void CheckIsOffline()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(operation.GetCachedPackageVersion()))
|
|
||||||
{
|
|
||||||
operation.data.playMode = EPlayMode.OfflinePlayMode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async Task<string> GetBestPackageVersion()
|
|
||||||
{
|
|
||||||
string cachedVersion = operation.GetCachedPackageVersion();
|
|
||||||
if (!string.IsNullOrEmpty(cachedVersion))
|
|
||||||
{
|
|
||||||
return cachedVersion;
|
|
||||||
}
|
|
||||||
string buildinVersion = await operation.GetBuildinPackageVersion();
|
|
||||||
if (!string.IsNullOrEmpty(buildinVersion))
|
|
||||||
{
|
|
||||||
return buildinVersion;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
private async UniTask LoadAndShowPatchWindow()
|
|
||||||
{
|
|
||||||
var assetHandle = operation.package.LoadAssetAsync<GameObject>("PatchWindow");
|
|
||||||
await assetHandle.ToUniTask();
|
|
||||||
if (assetHandle.Status == EOperationStatus.Succeed)
|
|
||||||
GameObject.Instantiate(assetHandle.AssetObject, MainUICanvas.Inst.Medium);
|
|
||||||
Debug.Log("创建热更信息界面");
|
|
||||||
}
|
|
||||||
private async UniTask UpdatePreloadPackage()
|
|
||||||
{
|
|
||||||
if (!await operation.RequestPackageVersion(false)) return;
|
|
||||||
if (!await operation.UpdatePackageManifest(false)) return;
|
|
||||||
if (operation.CreateDownloader())
|
|
||||||
{
|
|
||||||
if (!await operation.DownloadPackageFiles()) return;
|
|
||||||
}
|
|
||||||
if (!await operation.ClearCacheBundle()) return;
|
|
||||||
operation.SaveVersionToCache();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +1,25 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class Singleton<T> where T:class,new()
|
namespace Tuan.GameFramework
|
||||||
{
|
{
|
||||||
static T _inst;
|
public class Singleton<T> where T : class, new()
|
||||||
static readonly object _lock = new object();
|
|
||||||
public static T Inst
|
|
||||||
{
|
{
|
||||||
get
|
static T _inst;
|
||||||
|
static readonly object _lock = new object();
|
||||||
|
public static T Inst
|
||||||
{
|
{
|
||||||
lock (_lock)
|
get
|
||||||
{
|
{
|
||||||
if(_inst == null)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
_inst = new T();
|
if (_inst == null)
|
||||||
Debug.Log($"[Singleton] 创建 {typeof(T).Name} 实例");
|
{
|
||||||
|
_inst = new T();
|
||||||
|
Debug.Log($"[Singleton] 创建 {typeof(T).Name} 实例");
|
||||||
|
}
|
||||||
|
return _inst;
|
||||||
}
|
}
|
||||||
return _inst;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,28 +1,31 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class SingletonMono<T> : MonoBehaviour where T : MonoBehaviour
|
namespace Tuan.GameFramework
|
||||||
{
|
{
|
||||||
private static T _instance;
|
public class SingletonMono<T> : MonoBehaviour where T : MonoBehaviour
|
||||||
private static readonly object _lock = new object();
|
|
||||||
public static T Inst
|
|
||||||
{
|
{
|
||||||
get
|
private static T _instance;
|
||||||
|
private static readonly object _lock = new object();
|
||||||
|
public static T Inst
|
||||||
{
|
{
|
||||||
lock (_lock)
|
get
|
||||||
{
|
{
|
||||||
if (_instance == null)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
_instance = FindAnyObjectByType<T>();
|
|
||||||
|
|
||||||
if (_instance == null)
|
if (_instance == null)
|
||||||
{
|
{
|
||||||
GameObject singletonObject = new GameObject(typeof(T).Name);
|
_instance = FindAnyObjectByType<T>();
|
||||||
DontDestroyOnLoad(singletonObject);
|
|
||||||
_instance = singletonObject.AddComponent<T>();
|
if (_instance == null)
|
||||||
Debug.Log($"实例化{singletonObject.name}");
|
{
|
||||||
|
GameObject singletonObject = new GameObject(typeof(T).Name);
|
||||||
|
DontDestroyOnLoad(singletonObject);
|
||||||
|
_instance = singletonObject.AddComponent<T>();
|
||||||
|
Debug.Log($"实例化{singletonObject.name}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return _instance;
|
||||||
}
|
}
|
||||||
return _instance;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 361581cda23892243b32bc232eada060
|
guid: b97f97e936caa3243b69996ed03e9a7b
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
79
Assets/GameRes/Main/InputActions/PlayerActions.inputactions
Normal file
79
Assets/GameRes/Main/InputActions/PlayerActions.inputactions
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"name": "PlayerActions",
|
||||||
|
"maps": [
|
||||||
|
{
|
||||||
|
"name": "Player",
|
||||||
|
"id": "8838403e-77e7-4938-931c-e7b6dd8da490",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"name": "Move",
|
||||||
|
"type": "Value",
|
||||||
|
"id": "16e058d1-98bd-4788-8905-cbbfe02198e1",
|
||||||
|
"expectedControlType": "Vector2",
|
||||||
|
"processors": "",
|
||||||
|
"interactions": "",
|
||||||
|
"initialStateCheck": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bindings": [
|
||||||
|
{
|
||||||
|
"name": "WASD",
|
||||||
|
"id": "969f48c2-0733-4928-b753-b138a70296af",
|
||||||
|
"path": "2DVector",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "",
|
||||||
|
"action": "Move",
|
||||||
|
"isComposite": true,
|
||||||
|
"isPartOfComposite": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "up",
|
||||||
|
"id": "72c4179b-427a-4077-9aa4-5b13b797cc0b",
|
||||||
|
"path": "<Keyboard>/w",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "",
|
||||||
|
"action": "Move",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "down",
|
||||||
|
"id": "9a0c2556-7cde-48d5-b5e0-f02b4c3198d2",
|
||||||
|
"path": "<Keyboard>/s",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "",
|
||||||
|
"action": "Move",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "left",
|
||||||
|
"id": "5e78290e-53bd-43f3-98fd-86caef589cdf",
|
||||||
|
"path": "<Keyboard>/a",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "",
|
||||||
|
"action": "Move",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "right",
|
||||||
|
"id": "8770c0d9-f0a5-4e93-b4e0-e30272211973",
|
||||||
|
"path": "<Keyboard>/d",
|
||||||
|
"interactions": "",
|
||||||
|
"processors": "",
|
||||||
|
"groups": "",
|
||||||
|
"action": "Move",
|
||||||
|
"isComposite": false,
|
||||||
|
"isPartOfComposite": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"controlSchemes": []
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1af8d28e241e7634b985b9ffe793d1bf
|
||||||
|
ScriptedImporter:
|
||||||
|
internalIDToNameTable: []
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
script: {fileID: 11500000, guid: 8404be70184654265930450def6a9037, type: 3}
|
||||||
|
generateWrapperCode: 0
|
||||||
|
wrapperCodePath:
|
||||||
|
wrapperClassName:
|
||||||
|
wrapperCodeNamespace:
|
||||||
@@ -8,7 +8,8 @@
|
|||||||
"GUID:6055be8ebefd69e48b49212b09b47b2f",
|
"GUID:6055be8ebefd69e48b49212b09b47b2f",
|
||||||
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
||||||
"GUID:e34a5702dd353724aa315fb8011f08c3",
|
"GUID:e34a5702dd353724aa315fb8011f08c3",
|
||||||
"GUID:75469ad4d38634e559750d17036d5f7c"
|
"GUID:75469ad4d38634e559750d17036d5f7c",
|
||||||
|
"GUID:928f8a513cd12e84cb0d3c0a21a84e2f"
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
|
|||||||
@@ -1,29 +1,27 @@
|
|||||||
using Cysharp.Threading.Tasks;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.NetworkInformation;
|
|
||||||
using System.Threading;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Networking;
|
using Cysharp.Threading.Tasks;
|
||||||
using YooAsset;
|
using Tuan.GameFramework;
|
||||||
|
using Tuan.GameScripts.Preload;
|
||||||
|
|
||||||
public class GameStart : MonoBehaviour
|
namespace Tuan.GameScripts.Main
|
||||||
{
|
{
|
||||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
public class GameStart : MonoBehaviour
|
||||||
async void Start()
|
|
||||||
{
|
{
|
||||||
Debug.Log("GameStart");
|
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||||
GamePreload.Inst.Test("call by GameStart");
|
async void Start()
|
||||||
_=FrameSplittingTest(1);
|
|
||||||
await UIManager.Inst.ShowUIAsync<SimpleR3Test>("test1", MainUICanvas.Inst.Medium);
|
|
||||||
}
|
|
||||||
async UniTask FrameSplittingTest(int delayFrame)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 100; i++)
|
|
||||||
{
|
{
|
||||||
Debug.Log(i);
|
Debug.Log("GameStart");
|
||||||
await UniTask.DelayFrame(delayFrame);
|
GamePreload.Inst.Test("call by GameStart");
|
||||||
|
// _ = FrameSplittingTest(1);
|
||||||
|
await UIManager.Inst.ShowUIAsync<SimpleR3Test>("test1", MainUICanvas.Inst.Medium);
|
||||||
|
}
|
||||||
|
async UniTask FrameSplittingTest(int delayFrame)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
Debug.Log(i);
|
||||||
|
await UniTask.DelayFrame(delayFrame);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,26 +1,43 @@
|
|||||||
using static UnityEngine.InputSystem.InputAction;
|
using static UnityEngine.InputSystem.InputAction;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using R3;
|
using UnityEngine.InputSystem;
|
||||||
|
using YooAsset;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
public class ThirdCharacterController : MonoBehaviour
|
namespace Tuan.GameScripts.Main
|
||||||
{
|
{
|
||||||
public CharacterController characterController;
|
public class ThirdCharacterController : MonoBehaviour
|
||||||
public Animator animator;
|
|
||||||
public Transform forward;
|
|
||||||
public Transform model;
|
|
||||||
|
|
||||||
public float moveSpeed = 5f;
|
|
||||||
public float turnSpeed = 10f;
|
|
||||||
public float jumpSpeed = 8f;
|
|
||||||
public float gravity = 20f;
|
|
||||||
public float minCameraDistance = 2f;
|
|
||||||
public float maxCameraDistance = 10f;
|
|
||||||
public float cameraZoomSpeed = 0.1f;
|
|
||||||
|
|
||||||
Vector2 moveInput;
|
|
||||||
|
|
||||||
public void OnMove(CallbackContext context)
|
|
||||||
{
|
{
|
||||||
moveInput = context.ReadValue<Vector2>();
|
public CharacterController characterController;
|
||||||
|
public Animator animator;
|
||||||
|
public Transform forward;
|
||||||
|
public Transform model;
|
||||||
|
|
||||||
|
public float moveSpeed = 5f;
|
||||||
|
public float turnSpeed = 10f;
|
||||||
|
public float jumpSpeed = 8f;
|
||||||
|
public float gravity = 20f;
|
||||||
|
public float minCameraDistance = 2f;
|
||||||
|
public float maxCameraDistance = 10f;
|
||||||
|
public float cameraZoomSpeed = 0.1f;
|
||||||
|
|
||||||
|
InputActionAsset playerActions;
|
||||||
|
Vector2 moveInput;
|
||||||
|
|
||||||
|
async void Awake()
|
||||||
|
{
|
||||||
|
await LoadInputActonAsset();
|
||||||
|
}
|
||||||
|
async UniTask LoadInputActonAsset()
|
||||||
|
{
|
||||||
|
AssetHandle handle = YooAssets.LoadAssetAsync<InputActionAsset>("PlayerActions");
|
||||||
|
await handle.ToUniTask();
|
||||||
|
playerActions = handle.AssetObject as InputActionAsset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnMove(CallbackContext context)
|
||||||
|
{
|
||||||
|
moveInput = context.ReadValue<Vector2>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
using R3;
|
using R3;
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
public class SimpleR3Test : UIBase
|
namespace Tuan.GameScripts.Main
|
||||||
{
|
{
|
||||||
public SerializableReactiveProperty<float> value = new(0);
|
public class SimpleR3Test : UIBase
|
||||||
|
|
||||||
public InputField inputField;
|
|
||||||
public Scrollbar scrollbar;
|
|
||||||
|
|
||||||
public override void OnCreate()
|
|
||||||
{
|
{
|
||||||
value.BindToScrollbar(scrollbar).AddTo(this);
|
public SerializableReactiveProperty<float> value = new(0);
|
||||||
value.BindToInputField(inputField).AddTo(this);
|
|
||||||
|
public InputField inputField;
|
||||||
|
public Scrollbar scrollbar;
|
||||||
|
|
||||||
|
public override void OnCreate()
|
||||||
|
{
|
||||||
|
value.BindToScrollbar(scrollbar).AddTo(this);
|
||||||
|
value.BindToInputField(inputField).AddTo(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,38 +1,41 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class UIBase : MonoBehaviour
|
namespace Tuan.GameScripts.Main
|
||||||
{
|
{
|
||||||
public RectTransform rectTransform
|
public class UIBase : MonoBehaviour
|
||||||
{
|
{
|
||||||
get
|
public RectTransform rectTransform
|
||||||
{
|
{
|
||||||
if (_rectTransform == null)
|
get
|
||||||
_rectTransform = GetComponent<RectTransform>();
|
{
|
||||||
return _rectTransform;
|
if (_rectTransform == null)
|
||||||
|
_rectTransform = GetComponent<RectTransform>();
|
||||||
|
return _rectTransform;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RectTransform _rectTransform;
|
||||||
|
public UIBase parent;
|
||||||
|
public virtual void OnCreate() { }
|
||||||
|
public virtual void OnShow() { }
|
||||||
|
public virtual void OnHide() { }
|
||||||
|
|
||||||
|
public void SetFull()
|
||||||
|
{
|
||||||
|
rectTransform.anchorMin = Vector2.zero;
|
||||||
|
rectTransform.anchorMax = Vector2.one;
|
||||||
|
rectTransform.offsetMin = Vector2.zero;
|
||||||
|
rectTransform.offsetMax = Vector2.zero;
|
||||||
|
rectTransform.sizeDelta = Vector2.zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetParent(RectTransform ui, bool isFull = false)
|
||||||
|
{
|
||||||
|
rectTransform.SetParent(ui);
|
||||||
|
rectTransform.localScale = Vector3.one;
|
||||||
|
rectTransform.localPosition = Vector3.zero;
|
||||||
|
rectTransform.localRotation = Quaternion.identity;
|
||||||
|
if (isFull)
|
||||||
|
SetFull();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RectTransform _rectTransform;
|
|
||||||
public UIBase parent;
|
|
||||||
public virtual void OnCreate() { }
|
|
||||||
public virtual void OnShow() { }
|
|
||||||
public virtual void OnHide() { }
|
|
||||||
|
|
||||||
public void SetFull()
|
|
||||||
{
|
|
||||||
rectTransform.anchorMin = Vector2.zero;
|
|
||||||
rectTransform.anchorMax = Vector2.one;
|
|
||||||
rectTransform.offsetMin = Vector2.zero;
|
|
||||||
rectTransform.offsetMax = Vector2.zero;
|
|
||||||
rectTransform.sizeDelta = Vector2.zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetParent(RectTransform ui, bool isFull = false)
|
|
||||||
{
|
|
||||||
rectTransform.SetParent(ui);
|
|
||||||
rectTransform.localScale = Vector3.one;
|
|
||||||
rectTransform.localPosition = Vector3.zero;
|
|
||||||
rectTransform.localRotation = Quaternion.identity;
|
|
||||||
if (isFull)
|
|
||||||
SetFull();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,156 +1,160 @@
|
|||||||
using Cysharp.Threading.Tasks;
|
using Cysharp.Threading.Tasks;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using Tuan.GameFramework;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using YooAsset;
|
using YooAsset;
|
||||||
|
|
||||||
public class UIManager : Singleton<UIManager>
|
namespace Tuan.GameScripts.Main
|
||||||
{
|
{
|
||||||
Dictionary<string, UIBase> openedUIs = new Dictionary<string, UIBase>();
|
public class UIManager : Singleton<UIManager>
|
||||||
Dictionary<string, AssetHandle> assetHandles = new Dictionary<string, AssetHandle>();
|
{
|
||||||
Stack<UIBase> uiStack = new Stack<UIBase>();
|
Dictionary<string, UIBase> openedUIs = new Dictionary<string, UIBase>();
|
||||||
|
Dictionary<string, AssetHandle> assetHandles = new Dictionary<string, AssetHandle>();
|
||||||
|
Stack<UIBase> uiStack = new Stack<UIBase>();
|
||||||
|
|
||||||
public T ShowUI<T>(string uiName, RectTransform parent = null, bool isFull = false) where T : UIBase
|
public T ShowUI<T>(string uiName, RectTransform parent = null, bool isFull = false) where T : UIBase
|
||||||
{
|
|
||||||
T ui = null;
|
|
||||||
string uiType = typeof(T).Name;
|
|
||||||
if (!openedUIs.ContainsKey(uiName))
|
|
||||||
{
|
{
|
||||||
GameObject uiPrefab = LoadUI(uiType);
|
T ui = null;
|
||||||
ui = CreateUI<T>(uiPrefab, uiName, parent, isFull);
|
string uiType = typeof(T).Name;
|
||||||
openedUIs[uiName] = ui;
|
if (!openedUIs.ContainsKey(uiName))
|
||||||
uiStack.Push(ui);
|
{
|
||||||
|
GameObject uiPrefab = LoadUI(uiType);
|
||||||
|
ui = CreateUI<T>(uiPrefab, uiName, parent, isFull);
|
||||||
|
openedUIs[uiName] = ui;
|
||||||
|
uiStack.Push(ui);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui = openedUIs[uiName] as T;
|
||||||
|
}
|
||||||
|
Debug.Log($"ShowUI====>name:{uiName} type:{typeof(T).Name}");
|
||||||
|
ui.OnShow();
|
||||||
|
return ui;
|
||||||
}
|
}
|
||||||
else
|
public async UniTask<T> ShowUIAsync<T>(string uiName, RectTransform parent = null, bool isFull = false) where T : UIBase
|
||||||
{
|
{
|
||||||
ui = openedUIs[uiName] as T;
|
T ui = null;
|
||||||
|
string uiType = typeof(T).Name;
|
||||||
|
if (!openedUIs.ContainsKey(uiName))
|
||||||
|
{
|
||||||
|
GameObject uiPrefab = await LoadUIAsync(uiType);
|
||||||
|
ui = CreateUI<T>(uiPrefab, uiName, parent, isFull);
|
||||||
|
openedUIs[uiName] = ui;
|
||||||
|
uiStack.Push(ui);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui = openedUIs[uiName] as T;
|
||||||
|
}
|
||||||
|
Debug.Log($"ShowUIAsync====>name:{uiName} type:{typeof(T).Name}");
|
||||||
|
ui.OnShow();
|
||||||
|
return ui;
|
||||||
}
|
}
|
||||||
Debug.Log($"ShowUI====>name:{uiName} type:{typeof(T).Name}");
|
T CreateUI<T>(GameObject uiPrefab, string uiName, RectTransform parent = null, bool isFull = false) where T : UIBase
|
||||||
ui.OnShow();
|
|
||||||
return ui;
|
|
||||||
}
|
|
||||||
public async UniTask<T> ShowUIAsync<T>(string uiName, RectTransform parent = null, bool isFull = false) where T : UIBase
|
|
||||||
{
|
|
||||||
T ui = null;
|
|
||||||
string uiType = typeof(T).Name;
|
|
||||||
if (!openedUIs.ContainsKey(uiName))
|
|
||||||
{
|
{
|
||||||
GameObject uiPrefab = await LoadUIAsync(uiType);
|
GameObject uiObj = GameObject.Instantiate(uiPrefab);
|
||||||
ui = CreateUI<T>(uiPrefab, uiName, parent, isFull);
|
uiObj.name = uiName;
|
||||||
openedUIs[uiName] = ui;
|
T ui = uiObj.GetComponent<T>();
|
||||||
uiStack.Push(ui);
|
ui.OnCreate();
|
||||||
|
if (parent) ui.SetParent(parent, isFull);
|
||||||
|
Debug.Log($"CreateUI====>name:{uiName} type:{typeof(T).Name}");
|
||||||
|
return ui;
|
||||||
}
|
}
|
||||||
else
|
GameObject LoadUI(string uiType)
|
||||||
{
|
{
|
||||||
ui = openedUIs[uiName] as T;
|
if (!assetHandles.ContainsKey(uiType))
|
||||||
|
{
|
||||||
|
AssetHandle uiHandle = YooAssets.LoadAssetSync<GameObject>(uiType);
|
||||||
|
assetHandles.Add(uiType, uiHandle);
|
||||||
|
return (GameObject)uiHandle.AssetObject;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AssetHandle uiHandle = assetHandles[uiType];
|
||||||
|
return (GameObject)uiHandle.AssetObject;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Debug.Log($"ShowUIAsync====>name:{uiName} type:{typeof(T).Name}");
|
async UniTask<GameObject> LoadUIAsync(string uiType)
|
||||||
ui.OnShow();
|
|
||||||
return ui;
|
|
||||||
}
|
|
||||||
T CreateUI<T>(GameObject uiPrefab, string uiName, RectTransform parent = null, bool isFull = false) where T : UIBase
|
|
||||||
{
|
|
||||||
GameObject uiObj = GameObject.Instantiate(uiPrefab);
|
|
||||||
uiObj.name = uiName;
|
|
||||||
T ui = uiObj.GetComponent<T>();
|
|
||||||
ui.OnCreate();
|
|
||||||
if (parent) ui.SetParent(parent, isFull);
|
|
||||||
Debug.Log($"CreateUI====>name:{uiName} type:{typeof(T).Name}");
|
|
||||||
return ui;
|
|
||||||
}
|
|
||||||
GameObject LoadUI(string uiType)
|
|
||||||
{
|
|
||||||
if (!assetHandles.ContainsKey(uiType))
|
|
||||||
{
|
{
|
||||||
AssetHandle uiHandle = YooAssets.LoadAssetSync<GameObject>(uiType);
|
if (!assetHandles.ContainsKey(uiType))
|
||||||
assetHandles.Add(uiType, uiHandle);
|
{
|
||||||
return (GameObject)uiHandle.AssetObject;
|
AssetHandle uiHandle = YooAssets.LoadAssetAsync<GameObject>(uiType);
|
||||||
|
await uiHandle.ToUniTask();
|
||||||
|
assetHandles.Add(uiType, uiHandle);
|
||||||
|
return (GameObject)uiHandle.AssetObject;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AssetHandle uiHandle = assetHandles[uiType];
|
||||||
|
return (GameObject)uiHandle.AssetObject;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
AssetHandle uiHandle = assetHandles[uiType];
|
|
||||||
return (GameObject)uiHandle.AssetObject;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async UniTask<GameObject> LoadUIAsync(string uiType)
|
|
||||||
{
|
|
||||||
if (!assetHandles.ContainsKey(uiType))
|
|
||||||
{
|
|
||||||
AssetHandle uiHandle = YooAssets.LoadAssetAsync<GameObject>(uiType);
|
|
||||||
await uiHandle.ToUniTask();
|
|
||||||
assetHandles.Add(uiType, uiHandle);
|
|
||||||
return (GameObject)uiHandle.AssetObject;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AssetHandle uiHandle = assetHandles[uiType];
|
|
||||||
return (GameObject)uiHandle.AssetObject;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region 用于测试没挂载UIBase的
|
#region 用于测试没挂载UIBase的
|
||||||
Dictionary<string, GameObject> testOpenedUIs = new Dictionary<string, GameObject>();
|
Dictionary<string, GameObject> testOpenedUIs = new Dictionary<string, GameObject>();
|
||||||
Stack<GameObject> testUIStack = new Stack<GameObject>();
|
Stack<GameObject> testUIStack = new Stack<GameObject>();
|
||||||
public GameObject TestShowUI(string path, string uiName, RectTransform parent = null, bool isFull = false)
|
public GameObject TestShowUI(string path, string uiName, RectTransform parent = null, bool isFull = false)
|
||||||
{
|
|
||||||
GameObject ui = null;
|
|
||||||
if (!testOpenedUIs.ContainsKey(uiName))
|
|
||||||
{
|
{
|
||||||
GameObject uiPrefab = LoadUI(path);
|
GameObject ui = null;
|
||||||
ui = TestCreateUI(uiPrefab, uiName, parent, isFull);
|
if (!testOpenedUIs.ContainsKey(uiName))
|
||||||
testOpenedUIs[uiName] = ui;
|
{
|
||||||
testUIStack.Push(ui);
|
GameObject uiPrefab = LoadUI(path);
|
||||||
|
ui = TestCreateUI(uiPrefab, uiName, parent, isFull);
|
||||||
|
testOpenedUIs[uiName] = ui;
|
||||||
|
testUIStack.Push(ui);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui = testOpenedUIs[uiName];
|
||||||
|
}
|
||||||
|
Debug.Log($"TestShowUI====>name:{uiName}");
|
||||||
|
return ui;
|
||||||
}
|
}
|
||||||
else
|
public async UniTask<GameObject> TestShowUIAsync(string path, string uiName, RectTransform parent = null, bool isFull = false)
|
||||||
{
|
{
|
||||||
ui = testOpenedUIs[uiName];
|
GameObject ui = null;
|
||||||
|
if (!testOpenedUIs.ContainsKey(uiName))
|
||||||
|
{
|
||||||
|
GameObject uiPrefab = await LoadUIAsync(path);
|
||||||
|
ui = TestCreateUI(uiPrefab, uiName, parent, isFull);
|
||||||
|
testOpenedUIs[uiName] = ui;
|
||||||
|
testUIStack.Push(ui);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui = testOpenedUIs[uiName];
|
||||||
|
}
|
||||||
|
Debug.Log($"TestShowUI====>name:{uiName}");
|
||||||
|
return ui;
|
||||||
}
|
}
|
||||||
Debug.Log($"TestShowUI====>name:{uiName}");
|
GameObject TestCreateUI(GameObject uiPrefab, string uiName, RectTransform parent = null, bool isFull = false)
|
||||||
return ui;
|
|
||||||
}
|
|
||||||
public async UniTask< GameObject> TestShowUIAsync(string path, string uiName, RectTransform parent = null, bool isFull = false)
|
|
||||||
{
|
|
||||||
GameObject ui = null;
|
|
||||||
if (!testOpenedUIs.ContainsKey(uiName))
|
|
||||||
{
|
{
|
||||||
GameObject uiPrefab = await LoadUIAsync(path);
|
GameObject uiObj = GameObject.Instantiate(uiPrefab);
|
||||||
ui = TestCreateUI(uiPrefab, uiName, parent, isFull);
|
uiObj.name = uiName;
|
||||||
testOpenedUIs[uiName] = ui;
|
RectTransform ui = uiObj.GetComponent<RectTransform>();
|
||||||
testUIStack.Push(ui);
|
if (parent) TestSetParent(ui, parent, isFull);
|
||||||
|
Debug.Log($"TestCreateUI====>name:{uiName}");
|
||||||
|
return uiObj;
|
||||||
}
|
}
|
||||||
else
|
void TestSetFull(RectTransform rectTransform)
|
||||||
{
|
{
|
||||||
ui = testOpenedUIs[uiName];
|
rectTransform.anchorMin = Vector2.zero;
|
||||||
|
rectTransform.anchorMax = Vector2.one;
|
||||||
|
rectTransform.offsetMin = Vector2.zero;
|
||||||
|
rectTransform.offsetMax = Vector2.zero;
|
||||||
|
rectTransform.sizeDelta = Vector2.zero;
|
||||||
}
|
}
|
||||||
Debug.Log($"TestShowUI====>name:{uiName}");
|
|
||||||
return ui;
|
|
||||||
}
|
|
||||||
GameObject TestCreateUI(GameObject uiPrefab, string uiName, RectTransform parent = null, bool isFull = false)
|
|
||||||
{
|
|
||||||
GameObject uiObj = GameObject.Instantiate(uiPrefab);
|
|
||||||
uiObj.name = uiName;
|
|
||||||
RectTransform ui = uiObj.GetComponent<RectTransform>();
|
|
||||||
if (parent) TestSetParent(ui, parent, isFull);
|
|
||||||
Debug.Log($"TestCreateUI====>name:{uiName}");
|
|
||||||
return uiObj;
|
|
||||||
}
|
|
||||||
void TestSetFull(RectTransform rectTransform)
|
|
||||||
{
|
|
||||||
rectTransform.anchorMin = Vector2.zero;
|
|
||||||
rectTransform.anchorMax = Vector2.one;
|
|
||||||
rectTransform.offsetMin = Vector2.zero;
|
|
||||||
rectTransform.offsetMax = Vector2.zero;
|
|
||||||
rectTransform.sizeDelta = Vector2.zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestSetParent(RectTransform ui, RectTransform parent, bool isFull = false)
|
void TestSetParent(RectTransform ui, RectTransform parent, bool isFull = false)
|
||||||
{
|
{
|
||||||
ui.SetParent(parent);
|
ui.SetParent(parent);
|
||||||
ui.localScale = Vector3.one;
|
ui.localScale = Vector3.one;
|
||||||
ui.localPosition = Vector3.zero;
|
ui.localPosition = Vector3.zero;
|
||||||
ui.localRotation = Quaternion.identity;
|
ui.localRotation = Quaternion.identity;
|
||||||
if (isFull)
|
if (isFull)
|
||||||
TestSetFull(ui);
|
TestSetFull(ui);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
#endregion
|
}
|
||||||
}
|
|
||||||
@@ -4,7 +4,7 @@ using TMPro;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
namespace R3
|
namespace Tuan.GameScripts.Main
|
||||||
{
|
{
|
||||||
public static class UnityUIBindings
|
public static class UnityUIBindings
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Tuan.GameFramework;
|
||||||
|
|
||||||
public class GamePreload : Singleton<GamePreload>
|
namespace Tuan.GameScripts.Preload
|
||||||
{
|
{
|
||||||
public void Test(string msg)
|
public class GamePreload : Singleton<GamePreload>
|
||||||
{
|
{
|
||||||
Debug.Log($"GamePreload.Test:{msg}");
|
public void Test(string msg)
|
||||||
|
{
|
||||||
|
Debug.Log($"GamePreload.Test:{msg}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,47 +1,51 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityEngine.Video;
|
using UnityEngine.Video;
|
||||||
|
using Tuan.GameFramework;
|
||||||
|
|
||||||
public class PatchWindow : MonoBehaviour
|
namespace Tuan.GameScripts.Preload
|
||||||
{
|
{
|
||||||
public Text statusText;
|
public class PatchWindow : MonoBehaviour
|
||||||
public Slider progressBar;
|
|
||||||
public Text downloadSizeText;
|
|
||||||
public VideoPlayer video;
|
|
||||||
private void Awake()
|
|
||||||
{
|
{
|
||||||
video.targetCamera = MainUICanvas.Inst.UICamera;
|
public Text statusText;
|
||||||
PatchEvent.OnStatusUpdate += OnStatusUpdate;
|
public Slider progressBar;
|
||||||
PatchEvent.OnProgressUpdate += OnProgressUpdate;
|
public Text downloadSizeText;
|
||||||
PatchEvent.OnDownloadSizeUpdate += OnDownloadSizeUpdate;
|
public VideoPlayer video;
|
||||||
PatchEvent.OnClosePatchWindow += OnClosePatchWindow;
|
private void Awake()
|
||||||
}
|
{
|
||||||
private void OnDestroy()
|
video.targetCamera = MainUICanvas.Inst.UICamera;
|
||||||
{
|
PatchEvent.OnStatusUpdate += OnStatusUpdate;
|
||||||
PatchEvent.OnStatusUpdate -= OnStatusUpdate;
|
PatchEvent.OnProgressUpdate += OnProgressUpdate;
|
||||||
PatchEvent.OnProgressUpdate -= OnProgressUpdate;
|
PatchEvent.OnDownloadSizeUpdate += OnDownloadSizeUpdate;
|
||||||
PatchEvent.OnDownloadSizeUpdate -= OnDownloadSizeUpdate;
|
PatchEvent.OnClosePatchWindow += OnClosePatchWindow;
|
||||||
}
|
}
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
PatchEvent.OnStatusUpdate -= OnStatusUpdate;
|
||||||
|
PatchEvent.OnProgressUpdate -= OnProgressUpdate;
|
||||||
|
PatchEvent.OnDownloadSizeUpdate -= OnDownloadSizeUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnStatusUpdate(string status)
|
private void OnStatusUpdate(string status)
|
||||||
{
|
{
|
||||||
if (statusText != null)
|
if (statusText != null)
|
||||||
statusText.text = status;
|
statusText.text = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnProgressUpdate(float progress)
|
private void OnProgressUpdate(float progress)
|
||||||
{
|
{
|
||||||
if (progressBar != null)
|
if (progressBar != null)
|
||||||
progressBar.value = progress;
|
progressBar.value = progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDownloadSizeUpdate(string sizeText)
|
private void OnDownloadSizeUpdate(string sizeText)
|
||||||
{
|
{
|
||||||
if (downloadSizeText != null)
|
if (downloadSizeText != null)
|
||||||
downloadSizeText.text = sizeText;
|
downloadSizeText.text = sizeText;
|
||||||
|
}
|
||||||
|
private void OnClosePatchWindow()
|
||||||
|
{
|
||||||
|
gameObject.SetActive(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private void OnClosePatchWindow()
|
}
|
||||||
{
|
|
||||||
gameObject.SetActive(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -19,5 +19,8 @@
|
|||||||
<Group GroupActiveRule="EnableGroup" GroupName="UI" GroupDesc="" AssetTags="">
|
<Group GroupActiveRule="EnableGroup" GroupName="UI" GroupDesc="" AssetTags="">
|
||||||
<Collector CollectPath="Assets/GameRes/Main/UI" CollectGUID="92ee981811aa81945b9aefad990f18ec" CollectType="MainAssetCollector" AddressRule="AddressByFileName" PackRule="PackDirectory" FilterRule="CollectAll" UserData="" AssetTags="" />
|
<Collector CollectPath="Assets/GameRes/Main/UI" CollectGUID="92ee981811aa81945b9aefad990f18ec" CollectType="MainAssetCollector" AddressRule="AddressByFileName" PackRule="PackDirectory" FilterRule="CollectAll" UserData="" AssetTags="" />
|
||||||
</Group>
|
</Group>
|
||||||
|
<Group GroupActiveRule="EnableGroup" GroupName="InputActions" GroupDesc="" AssetTags="">
|
||||||
|
<Collector CollectPath="Assets/GameRes/Main/InputActions" CollectGUID="b97f97e936caa3243b69996ed03e9a7b" CollectType="MainAssetCollector" AddressRule="AddressByFileName" PackRule="PackSeparately" FilterRule="CollectAll" UserData="" AssetTags="" />
|
||||||
|
</Group>
|
||||||
</Package>
|
</Package>
|
||||||
</root>
|
</root>
|
||||||
@@ -99,3 +99,16 @@ MonoBehaviour:
|
|||||||
FilterRuleName: CollectAll
|
FilterRuleName: CollectAll
|
||||||
AssetTags:
|
AssetTags:
|
||||||
UserData:
|
UserData:
|
||||||
|
- GroupName: InputActions
|
||||||
|
GroupDesc:
|
||||||
|
AssetTags:
|
||||||
|
ActiveRuleName: EnableGroup
|
||||||
|
Collectors:
|
||||||
|
- CollectPath: Assets/GameRes/Main/InputActions
|
||||||
|
CollectorGUID: b97f97e936caa3243b69996ed03e9a7b
|
||||||
|
CollectorType: 0
|
||||||
|
AddressRuleName: AddressByFileName
|
||||||
|
PackRuleName: PackSeparately
|
||||||
|
FilterRuleName: CollectAll
|
||||||
|
AssetTags:
|
||||||
|
UserData:
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"version": 1,
|
||||||
"name": "InputSystem_Actions",
|
"name": "InputSystem_Actions",
|
||||||
"maps": [
|
"maps": [
|
||||||
{
|
{
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 8a55ef7d1bba14cc982b478d482c4461
|
guid: 9f1a339e4d0a6b444a9e489b81103fe3
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 2cceff5ec1f84bd0a6a9b4ed7719527c
|
guid: 4118f9f3fcb736649a2ca8beab5d745c
|
||||||
timeCreated: 1651978895
|
timeCreated: 1651978895
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: e1c9a3a6de2246bf88547a6b59b99b9f
|
guid: 6c792e3f64e1fe144b0e2d0909295415
|
||||||
timeCreated: 1650851321
|
timeCreated: 1650851321
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 1278a46ce459c5a46b4eaeda148684ef
|
guid: 928f8a513cd12e84cb0d3c0a21a84e2f
|
||||||
AssemblyDefinitionImporter:
|
AssemblyDefinitionImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
@@ -3,4 +3,5 @@
|
|||||||
[assembly: InternalsVisibleTo("UniTask.Linq")]
|
[assembly: InternalsVisibleTo("UniTask.Linq")]
|
||||||
[assembly: InternalsVisibleTo("UniTask.Addressables")]
|
[assembly: InternalsVisibleTo("UniTask.Addressables")]
|
||||||
[assembly: InternalsVisibleTo("UniTask.DOTween")]
|
[assembly: InternalsVisibleTo("UniTask.DOTween")]
|
||||||
[assembly: InternalsVisibleTo("UniTask.TextMeshPro")]
|
[assembly: InternalsVisibleTo("UniTask.TextMeshPro")]
|
||||||
|
[assembly: InternalsVisibleTo("UniTask.YooAsset")]
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 47 KiB |
@@ -1,153 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: d90b9b066363f08419ff51004479d5b7
|
|
||||||
TextureImporter:
|
|
||||||
internalIDToNameTable: []
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 13
|
|
||||||
mipmaps:
|
|
||||||
mipMapMode: 0
|
|
||||||
enableMipMap: 1
|
|
||||||
sRGBTexture: 1
|
|
||||||
linearTexture: 0
|
|
||||||
fadeOut: 0
|
|
||||||
borderMipMap: 0
|
|
||||||
mipMapsPreserveCoverage: 0
|
|
||||||
alphaTestReferenceValue: 0.5
|
|
||||||
mipMapFadeDistanceStart: 1
|
|
||||||
mipMapFadeDistanceEnd: 3
|
|
||||||
bumpmap:
|
|
||||||
convertToNormalMap: 0
|
|
||||||
externalNormalMap: 0
|
|
||||||
heightScale: 0.25
|
|
||||||
normalMapFilter: 0
|
|
||||||
flipGreenChannel: 0
|
|
||||||
isReadable: 0
|
|
||||||
streamingMipmaps: 0
|
|
||||||
streamingMipmapsPriority: 0
|
|
||||||
vTOnly: 0
|
|
||||||
ignoreMipmapLimit: 0
|
|
||||||
grayScaleToAlpha: 0
|
|
||||||
generateCubemap: 6
|
|
||||||
cubemapConvolution: 0
|
|
||||||
seamlessCubemap: 0
|
|
||||||
textureFormat: 1
|
|
||||||
maxTextureSize: 2048
|
|
||||||
textureSettings:
|
|
||||||
serializedVersion: 2
|
|
||||||
filterMode: 1
|
|
||||||
aniso: 1
|
|
||||||
mipBias: 0
|
|
||||||
wrapU: 0
|
|
||||||
wrapV: 0
|
|
||||||
wrapW: 0
|
|
||||||
nPOTScale: 1
|
|
||||||
lightmap: 0
|
|
||||||
compressionQuality: 50
|
|
||||||
spriteMode: 0
|
|
||||||
spriteExtrude: 1
|
|
||||||
spriteMeshType: 1
|
|
||||||
alignment: 0
|
|
||||||
spritePivot: {x: 0.5, y: 0.5}
|
|
||||||
spritePixelsToUnits: 100
|
|
||||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
spriteGenerateFallbackPhysicsShape: 1
|
|
||||||
alphaUsage: 1
|
|
||||||
alphaIsTransparency: 0
|
|
||||||
spriteTessellationDetail: -1
|
|
||||||
textureType: 0
|
|
||||||
textureShape: 1
|
|
||||||
singleChannelComponent: 0
|
|
||||||
flipbookRows: 1
|
|
||||||
flipbookColumns: 1
|
|
||||||
maxTextureSizeSet: 0
|
|
||||||
compressionQualitySet: 0
|
|
||||||
textureFormatSet: 0
|
|
||||||
ignorePngGamma: 0
|
|
||||||
applyGammaDecoding: 0
|
|
||||||
swizzle: 50462976
|
|
||||||
cookieLightType: 0
|
|
||||||
platformSettings:
|
|
||||||
- serializedVersion: 3
|
|
||||||
buildTarget: DefaultTexturePlatform
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
ignorePlatformSupport: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
- serializedVersion: 3
|
|
||||||
buildTarget: Standalone
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
ignorePlatformSupport: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
- serializedVersion: 3
|
|
||||||
buildTarget: iPhone
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
ignorePlatformSupport: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
- serializedVersion: 3
|
|
||||||
buildTarget: WebGL
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
ignorePlatformSupport: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
- serializedVersion: 3
|
|
||||||
buildTarget: Android
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
ignorePlatformSupport: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
spriteSheet:
|
|
||||||
serializedVersion: 2
|
|
||||||
sprites: []
|
|
||||||
outline: []
|
|
||||||
physicsShape: []
|
|
||||||
bones: []
|
|
||||||
spriteID:
|
|
||||||
internalID: 0
|
|
||||||
vertices: []
|
|
||||||
indices:
|
|
||||||
edges: []
|
|
||||||
weights: []
|
|
||||||
secondaryTextures: []
|
|
||||||
nameFileIdTable: {}
|
|
||||||
mipmapLimitGroupName:
|
|
||||||
pSDRemoveMatte: 0
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
# UniTask 扩展
|
|
||||||
|
|
||||||
### 代码示例
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
using System;
|
|
||||||
using UnityEngine;
|
|
||||||
using YooAsset;
|
|
||||||
using Cysharp.Threading.Tasks;
|
|
||||||
|
|
||||||
public class TestTask : MonoBehaviour
|
|
||||||
{
|
|
||||||
private async void Start()
|
|
||||||
{
|
|
||||||
var assetHandle = YooAssets.LoadAssetAsync<GameObject>("UIHome");
|
|
||||||
await assetHandle.ToUniTask();
|
|
||||||
Debug.Log($"{assetHandle.Status}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 使用教程A
|
|
||||||
|
|
||||||
1. 下载 [UniTask](https://github.com/Cysharp/UniTask) 源码并导入到工程内。
|
|
||||||
|
|
||||||
2. 修改UniTask源码
|
|
||||||
|
|
||||||
UniTask/Runtime/_InternalVisibleTo.cs
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
[assembly: InternalsVisibleTo("UniTask.Linq")]
|
|
||||||
[assembly: InternalsVisibleTo("UniTask.Addressables")]
|
|
||||||
[assembly: InternalsVisibleTo("UniTask.DOTween")]
|
|
||||||
[assembly: InternalsVisibleTo("UniTask.TextMeshPro")]
|
|
||||||
[assembly: InternalsVisibleTo("UniTask.YooAsset")] //增加此行代码
|
|
||||||
```
|
|
||||||
|
|
||||||
3. 拷贝YOO提供的扩展脚本到工程内。
|
|
||||||
|
|
||||||
YooAssets/Samples/UniTask Sample/UniTask目录
|
|
||||||
|
|
||||||
4. 添加引擎里的宏定义(在宏定义未生效的情况下)
|
|
||||||
|
|
||||||
Project Settings --> Player --> Scripting Define Symbols
|
|
||||||
|
|
||||||
```
|
|
||||||
UNITASK_YOOASSET_SUPPORT
|
|
||||||
```
|
|
||||||
|
|
||||||
5. 重启Unity引擎
|
|
||||||
|
|
||||||
重新打开工程后用上面的代码示例验证,看下是否有编译错误!
|
|
||||||
|
|
||||||
### 使用教程B
|
|
||||||
|
|
||||||
1. 通过Package导入UniTask插件
|
|
||||||
|
|
||||||
2. 拷贝YOO提供的扩展脚本到工程内。
|
|
||||||
|
|
||||||
YooAssets/Samples/UniTask Sample/UniTask目录
|
|
||||||
|
|
||||||
YooAssets/Samples/UniTask Sample/UniTaskRef目录
|
|
||||||
|
|
||||||
3. 添加引擎里的宏定义(在宏定义未生效的情况下)
|
|
||||||
|
|
||||||
Project Settings --> Player --> Scripting Define Symbols
|
|
||||||
|
|
||||||
```
|
|
||||||
UNITASK_YOOASSET_SUPPORT
|
|
||||||
```
|
|
||||||
|
|
||||||
4. 重启Unity引擎
|
|
||||||
|
|
||||||
重新打开工程后用上面的代码示例验证,看下是否有编译错误!
|
|
||||||
|
|
||||||
### 注意事项
|
|
||||||
|
|
||||||
- 注意检测程序集引用是否丢失
|
|
||||||
|
|
||||||

|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 6375cc739b170490fbc6c38181b2c600
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: aaf714c0c57134e7ab7675a7528c1505
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2bbb725df946a6f49afbc3ef104fbd8f
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: a06b0036f802a1c48805344cdbdfff1f
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: f4f000ae8d64e444fa5bf1090b648f76
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"reference": "GUID:f51ebe6a0ceec4240a699833d6309b23"
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: fb1a9972a41e10f40a752774a402830a
|
|
||||||
AssemblyDefinitionReferenceImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
[assembly: InternalsVisibleTo("UniTask.YooAsset")]
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: dc0f48d84ee89ad499856840eea08a64
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
Reference in New Issue
Block a user