111
This commit is contained in:
@@ -6,13 +6,15 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor.Build.Pipeline;
|
||||
|
||||
public class BuildTool
|
||||
namespace Tuan.GameFramework
|
||||
{
|
||||
public class BuildTool
|
||||
{
|
||||
[MenuItem("Tools/打包Preload")]
|
||||
public static void BuildPreload()
|
||||
{
|
||||
CopyHotDll.CopyPreloadDll2Byte();
|
||||
ExecuteBuild("Preload",EBuildPipeline.ScriptableBuildPipeline, EditorUserBuildSettings.activeBuildTarget,EFileNameStyle.BundleName,EBuildinFileCopyOption.ClearAndCopyAll);
|
||||
ExecuteBuild("Preload", EBuildPipeline.ScriptableBuildPipeline, EditorUserBuildSettings.activeBuildTarget, EFileNameStyle.BundleName, EBuildinFileCopyOption.ClearAndCopyAll);
|
||||
Debug.Log($"打包Preload结束");
|
||||
}
|
||||
[MenuItem("Tools/打包Main %G")]
|
||||
@@ -83,6 +85,5 @@ public class BuildTool
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,9 +2,10 @@ using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.IO;
|
||||
|
||||
|
||||
public class CopyHotDll
|
||||
namespace Tuan.GameFramework
|
||||
{
|
||||
public class CopyHotDll
|
||||
{
|
||||
[MenuItem("Tools/更新生成PreloadDll")]
|
||||
public static void CopyPreloadDll2Byte()
|
||||
{
|
||||
@@ -56,4 +57,5 @@ public class CopyHotDll
|
||||
}
|
||||
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,8 +2,10 @@ using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using YooAsset;
|
||||
|
||||
public class Boot : MonoBehaviour
|
||||
namespace Tuan.GameFramework
|
||||
{
|
||||
public class Boot : MonoBehaviour
|
||||
{
|
||||
public Camera MainCamera;
|
||||
public EPlayMode PlayMode = EPlayMode.EditorSimulateMode;
|
||||
void Awake()
|
||||
@@ -32,4 +34,5 @@ public class Boot : MonoBehaviour
|
||||
PatchEvent.ClosePatchWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,10 @@ using System.Collections.Generic;
|
||||
using System;
|
||||
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();
|
||||
@@ -85,4 +87,5 @@ public static class EventBus
|
||||
_eventHandlers.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,30 @@
|
||||
public interface IEvent { }
|
||||
|
||||
public interface IEventHandler<TEvent> where TEvent : IEvent
|
||||
namespace Tuan.GameFramework
|
||||
{
|
||||
public interface IEvent { }
|
||||
|
||||
public interface IEventHandler<TEvent> where TEvent : IEvent
|
||||
{
|
||||
void HandleEvent(TEvent eventData);
|
||||
}
|
||||
}
|
||||
|
||||
public struct ApplicationFocusEvent : IEvent
|
||||
{
|
||||
public struct ApplicationFocusEvent : IEvent
|
||||
{
|
||||
public bool HasFocus;
|
||||
}
|
||||
}
|
||||
|
||||
public struct SceneLoadEvent : IEvent
|
||||
{
|
||||
public struct SceneLoadEvent : IEvent
|
||||
{
|
||||
public string SceneName;
|
||||
public float Progress;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class EventHandler<TEvent> : IEventHandler<TEvent> where TEvent : IEvent
|
||||
{
|
||||
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:f51ebe6a0ceec4240a699833d6309b23",
|
||||
"GUID:3fe1a3e70da50184f9897101cad7e4f2",
|
||||
"GUID:13ba8ce62aa80c74598530029cb2d649"
|
||||
"GUID:13ba8ce62aa80c74598530029cb2d649",
|
||||
"GUID:928f8a513cd12e84cb0d3c0a21a84e2f"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class GameManager : Singleton<GameManager>
|
||||
namespace Tuan.GameFramework
|
||||
{
|
||||
public class GameManager : Singleton<GameManager>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class MainUICanvas : SingletonMono<MainUICanvas>
|
||||
namespace Tuan.GameFramework
|
||||
{
|
||||
public class MainUICanvas : SingletonMono<MainUICanvas>
|
||||
{
|
||||
public GameObject InitBg;
|
||||
public RectTransform Top;
|
||||
public RectTransform Medium;
|
||||
@@ -12,4 +14,5 @@ public class MainUICanvas : SingletonMono<MainUICanvas>
|
||||
DontDestroyOnLoad(gameObject);
|
||||
DontDestroyOnLoad(UICamera);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,10 @@ using UnityEngine.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class MessageBox : MonoBehaviour
|
||||
namespace Tuan.GameFramework
|
||||
{
|
||||
public class MessageBox : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject panel;
|
||||
[SerializeField] private Text titleText;
|
||||
[SerializeField] private Text contentText;
|
||||
@@ -83,4 +85,5 @@ public class MessageBox : MonoBehaviour
|
||||
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,7 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class Singleton<T> where T:class,new()
|
||||
namespace Tuan.GameFramework
|
||||
{
|
||||
public class Singleton<T> where T : class, new()
|
||||
{
|
||||
static T _inst;
|
||||
static readonly object _lock = new object();
|
||||
public static T Inst
|
||||
@@ -10,7 +12,7 @@ public class Singleton<T> where T:class,new()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if(_inst == null)
|
||||
if (_inst == null)
|
||||
{
|
||||
_inst = new T();
|
||||
Debug.Log($"[Singleton] 创建 {typeof(T).Name} 实例");
|
||||
@@ -19,4 +21,5 @@ public class Singleton<T> where T:class,new()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class SingletonMono<T> : MonoBehaviour where T : MonoBehaviour
|
||||
namespace Tuan.GameFramework
|
||||
{
|
||||
public class SingletonMono<T> : MonoBehaviour where T : MonoBehaviour
|
||||
{
|
||||
private static T _instance;
|
||||
private static readonly object _lock = new object();
|
||||
public static T Inst
|
||||
@@ -26,4 +28,5 @@ public class SingletonMono<T> : MonoBehaviour where T : MonoBehaviour
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 361581cda23892243b32bc232eada060
|
||||
guid: b97f97e936caa3243b69996ed03e9a7b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
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:f51ebe6a0ceec4240a699833d6309b23",
|
||||
"GUID:e34a5702dd353724aa315fb8011f08c3",
|
||||
"GUID:75469ad4d38634e559750d17036d5f7c"
|
||||
"GUID:75469ad4d38634e559750d17036d5f7c",
|
||||
"GUID:928f8a513cd12e84cb0d3c0a21a84e2f"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
using Cysharp.Threading.Tasks;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Threading;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
using YooAsset;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Tuan.GameFramework;
|
||||
using Tuan.GameScripts.Preload;
|
||||
|
||||
public class GameStart : MonoBehaviour
|
||||
namespace Tuan.GameScripts.Main
|
||||
{
|
||||
public class GameStart : MonoBehaviour
|
||||
{
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
async void Start()
|
||||
{
|
||||
Debug.Log("GameStart");
|
||||
GamePreload.Inst.Test("call by GameStart");
|
||||
_=FrameSplittingTest(1);
|
||||
// _ = FrameSplittingTest(1);
|
||||
await UIManager.Inst.ShowUIAsync<SimpleR3Test>("test1", MainUICanvas.Inst.Medium);
|
||||
}
|
||||
async UniTask FrameSplittingTest(int delayFrame)
|
||||
@@ -26,4 +23,5 @@ public class GameStart : MonoBehaviour
|
||||
await UniTask.DelayFrame(delayFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,13 @@
|
||||
using static UnityEngine.InputSystem.InputAction;
|
||||
using UnityEngine;
|
||||
using R3;
|
||||
using UnityEngine.InputSystem;
|
||||
using YooAsset;
|
||||
using Cysharp.Threading.Tasks;
|
||||
|
||||
public class ThirdCharacterController : MonoBehaviour
|
||||
namespace Tuan.GameScripts.Main
|
||||
{
|
||||
public class ThirdCharacterController : MonoBehaviour
|
||||
{
|
||||
public CharacterController characterController;
|
||||
public Animator animator;
|
||||
public Transform forward;
|
||||
@@ -17,10 +21,23 @@ public class ThirdCharacterController : MonoBehaviour
|
||||
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,9 +1,10 @@
|
||||
using R3;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class SimpleR3Test : UIBase
|
||||
namespace Tuan.GameScripts.Main
|
||||
{
|
||||
public class SimpleR3Test : UIBase
|
||||
{
|
||||
public SerializableReactiveProperty<float> value = new(0);
|
||||
|
||||
public InputField inputField;
|
||||
@@ -14,4 +15,5 @@ public class SimpleR3Test : UIBase
|
||||
value.BindToScrollbar(scrollbar).AddTo(this);
|
||||
value.BindToInputField(inputField).AddTo(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class UIBase : MonoBehaviour
|
||||
namespace Tuan.GameScripts.Main
|
||||
{
|
||||
public class UIBase : MonoBehaviour
|
||||
{
|
||||
public RectTransform rectTransform
|
||||
{
|
||||
get
|
||||
@@ -35,4 +37,5 @@ public class UIBase : MonoBehaviour
|
||||
if (isFull)
|
||||
SetFull();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
using Cysharp.Threading.Tasks;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Tuan.GameFramework;
|
||||
using UnityEngine;
|
||||
using YooAsset;
|
||||
|
||||
public class UIManager : Singleton<UIManager>
|
||||
namespace Tuan.GameScripts.Main
|
||||
{
|
||||
public class UIManager : Singleton<UIManager>
|
||||
{
|
||||
Dictionary<string, UIBase> openedUIs = new Dictionary<string, UIBase>();
|
||||
Dictionary<string, AssetHandle> assetHandles = new Dictionary<string, AssetHandle>();
|
||||
Stack<UIBase> uiStack = new Stack<UIBase>();
|
||||
@@ -108,7 +111,7 @@ public class UIManager : Singleton<UIManager>
|
||||
Debug.Log($"TestShowUI====>name:{uiName}");
|
||||
return ui;
|
||||
}
|
||||
public async UniTask< GameObject> TestShowUIAsync(string path, string uiName, RectTransform parent = null, bool isFull = false)
|
||||
public async UniTask<GameObject> TestShowUIAsync(string path, string uiName, RectTransform parent = null, bool isFull = false)
|
||||
{
|
||||
GameObject ui = null;
|
||||
if (!testOpenedUIs.ContainsKey(uiName))
|
||||
@@ -153,4 +156,5 @@ public class UIManager : Singleton<UIManager>
|
||||
TestSetFull(ui);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace R3
|
||||
namespace Tuan.GameScripts.Main
|
||||
{
|
||||
public static class UnityUIBindings
|
||||
{
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
using UnityEngine;
|
||||
using Tuan.GameFramework;
|
||||
|
||||
public class GamePreload : Singleton<GamePreload>
|
||||
namespace Tuan.GameScripts.Preload
|
||||
{
|
||||
public class GamePreload : Singleton<GamePreload>
|
||||
{
|
||||
public void Test(string msg)
|
||||
{
|
||||
Debug.Log($"GamePreload.Test:{msg}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.Video;
|
||||
using Tuan.GameFramework;
|
||||
|
||||
public class PatchWindow : MonoBehaviour
|
||||
namespace Tuan.GameScripts.Preload
|
||||
{
|
||||
public class PatchWindow : MonoBehaviour
|
||||
{
|
||||
public Text statusText;
|
||||
public Slider progressBar;
|
||||
public Text downloadSizeText;
|
||||
@@ -44,4 +47,5 @@ public class PatchWindow : MonoBehaviour
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,5 +19,8 @@
|
||||
<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="" />
|
||||
</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>
|
||||
</root>
|
||||
@@ -99,3 +99,16 @@ MonoBehaviour:
|
||||
FilterRuleName: CollectAll
|
||||
AssetTags:
|
||||
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",
|
||||
"maps": [
|
||||
{
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a55ef7d1bba14cc982b478d482c4461
|
||||
guid: 9f1a339e4d0a6b444a9e489b81103fe3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -1,3 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2cceff5ec1f84bd0a6a9b4ed7719527c
|
||||
guid: 4118f9f3fcb736649a2ca8beab5d745c
|
||||
timeCreated: 1651978895
|
||||
@@ -1,3 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e1c9a3a6de2246bf88547a6b59b99b9f
|
||||
guid: 6c792e3f64e1fe144b0e2d0909295415
|
||||
timeCreated: 1650851321
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1278a46ce459c5a46b4eaeda148684ef
|
||||
guid: 928f8a513cd12e84cb0d3c0a21a84e2f
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
@@ -4,3 +4,4 @@
|
||||
[assembly: InternalsVisibleTo("UniTask.Addressables")]
|
||||
[assembly: InternalsVisibleTo("UniTask.DOTween")]
|
||||
[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