This commit is contained in:
2025-09-17 18:56:28 +08:00
commit 54c72710a5
5244 changed files with 5717609 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e011c0de116e3214cabe88ae742c5d19
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,93 @@
using UnityEditor;
using UnityEngine;
using YooAsset.Editor;
using YooAsset;
using System;
using System.Collections.Generic;
using UnityEditor.Build.Pipeline;
public class BuildTool
{
[MenuItem("Tools/<2F><><EFBFBD><EFBFBD>Preload")]
public static void BuildPreload()
{
CopyHotDll.CopyPreloadDll2Byte();
ExecuteBuild("Preload",EBuildPipeline.ScriptableBuildPipeline, EditorUserBuildSettings.activeBuildTarget,EFileNameStyle.BundleName_HashName,EBuildinFileCopyOption.ClearAndCopyAll);
Debug.Log($"<22><><EFBFBD><EFBFBD>Preload<61><64><EFBFBD><EFBFBD>");
}
[MenuItem("Tools/<2F><><EFBFBD><EFBFBD>Main %G")]
public static void BuildMain()
{
CopyHotDll.CopyMainDll2Byte();
ExecuteBuild("Main", EBuildPipeline.ScriptableBuildPipeline, EditorUserBuildSettings.activeBuildTarget, EFileNameStyle.BundleName_HashName, EBuildinFileCopyOption.None);
Debug.Log($"<22><><EFBFBD><EFBFBD>Main<69><6E><EFBFBD><EFBFBD>");
}
[MenuItem("Tools/ȫ<><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>")]
public static void BuildAll()
{
BuildPreload();
BuildMain();
}
public static void ExecuteBuild(string PackageName, EBuildPipeline BuildPipeline, BuildTarget BuildTarget, EFileNameStyle fileNameStyle, EBuildinFileCopyOption buildinFileCopyOption)
{
var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(PackageName, BuildPipeline);
var compressOption = AssetBundleBuilderSetting.GetPackageCompressOption(PackageName, BuildPipeline);
var clearBuildCache = AssetBundleBuilderSetting.GetPackageClearBuildCache(PackageName, BuildPipeline);
var useAssetDependencyDB = AssetBundleBuilderSetting.GetPackageUseAssetDependencyDB(PackageName, BuildPipeline);
var builtinShaderBundleName = GetBuiltinShaderBundleName(PackageName);
ScriptableBuildParameters buildParameters = new ScriptableBuildParameters();
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
buildParameters.BuildPipeline = BuildPipeline.ToString();
buildParameters.BuildBundleType = (int)EBuildBundleType.AssetBundle;
buildParameters.BuildTarget = BuildTarget;
buildParameters.PackageName = PackageName;
buildParameters.PackageVersion = GetPackageVersion();
buildParameters.EnableSharePackRule = true;
buildParameters.VerifyBuildingResult = true;
buildParameters.FileNameStyle = fileNameStyle;
buildParameters.BuildinFileCopyOption = buildinFileCopyOption;
buildParameters.BuildinFileCopyParams = buildinFileCopyParams;
buildParameters.CompressOption = compressOption;
buildParameters.ClearBuildCacheFiles = clearBuildCache;
buildParameters.UseAssetDependencyDB = useAssetDependencyDB;
buildParameters.BuiltinShadersBundleName = builtinShaderBundleName;
buildParameters.EncryptionServices = CreateEncryptionInstance(PackageName, BuildPipeline);
ScriptableBuildPipeline pipeline = new ScriptableBuildPipeline();
var buildResult = pipeline.Run(buildParameters, true);
if (buildResult.Success)
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;
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// ע<><EFBFBD><E2A3BA><EFBFBD>Զ<EFBFBD><D4B6>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>£<EFBFBD>
/// </summary>
public 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.GetPackageEncyptionClassName(PackageName, BuildPipeline);
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;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e57cfc5fd962f5746a2c991575785b97
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,63 @@
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using System;
using System.IO;
using System.Text;
public class CopyHotDll
{
[MenuItem("Tools/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>PreloadDll")]
public static void CopyPreloadDll2Byte()
{
HybridCLR.Editor.Commands.CompileDllCommand.CompileDllActiveBuildTarget();
string sourceDir = $"{Application.dataPath.Replace("/Assets", "")}/HybridCLRData/HotUpdateDlls/{UnityEditor.EditorUserBuildSettings.activeBuildTarget}/Preload.dll";
string destDir = $"{Application.dataPath}/Res/Preload/HotUpdateDll/Preload.bytes";
if (File.Exists(destDir))
{
File.Delete(destDir);
}
File.Copy(sourceDir, destDir);
AssetDatabase.Refresh();
Debug.Log($"copy {sourceDir} to {destDir}");
}
[MenuItem("Tools/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>MainDll")]
public static void CopyMainDll2Byte()
{
HybridCLR.Editor.Commands.CompileDllCommand.CompileDllActiveBuildTarget();
string sourceDir = $"{Application.dataPath.Replace("/Assets", "")}/HybridCLRData/HotUpdateDlls/{UnityEditor.EditorUserBuildSettings.activeBuildTarget}/Main.dll";
string destDir = $"{Application.dataPath}/Res/Main/HotUpdateDll/Main.bytes";
if (File.Exists(destDir))
{
File.Delete(destDir);
}
File.Copy(sourceDir, destDir);
AssetDatabase.Refresh();
Debug.Log($"copy {sourceDir} to {destDir}");
}
[MenuItem("Tools/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɲ<EFBFBD><C9B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ")]
public static void CopyDepDll2Byte()
{
HybridCLR.Editor.Commands.CompileDllCommand.CompileDllActiveBuildTarget();
string sourceDir = $"{Application.dataPath.Replace("/Assets", "")}/HybridCLRData/AssembliesPostIl2CppStrip/{UnityEditor.EditorUserBuildSettings.activeBuildTarget}/";
string destDir = $"{Application.dataPath}/Res/Main/HotUpdateDll/";
foreach (string dll in Boot.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");
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f880c60e7ea774c47a093b013d9469db
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,21 @@
{
"name": "MyScripts.Editor",
"rootNamespace": "",
"references": [
"GUID:e34a5702dd353724aa315fb8011f08c3",
"GUID:4d1926c9df5b052469a1c63448b7609a",
"GUID:2373f786d14518f44b0f475db77ba4de",
"GUID:8804cd4b3fef1e041ad4f6c94ec49e0c"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 632de22e4f40cf04bbaa1b1a2ded480d
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,67 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
using YooAsset.Editor;
public class SchemaTools
{
/// <summary>
/// 通用扫描快捷方法
/// </summary>
public static List<ReportElement> ScanAssets(string[] scanAssetList, System.Func<string, ReportElement> scanFun, int unloadAssetLimit = int.MaxValue)
{
int scanNumber = 0;
int progressCount = 0;
int totalCount = scanAssetList.Length;
List<ReportElement> results = new List<ReportElement>(totalCount);
EditorTools.ClearProgressBar();
foreach (string assetPath in scanAssetList)
{
scanNumber++;
progressCount++;
EditorTools.DisplayProgressBar("扫描中...", progressCount, totalCount);
var scanResult = scanFun.Invoke(assetPath);
if (scanResult != null)
results.Add(scanResult);
// 释放编辑器未使用的资源
if (scanNumber >= unloadAssetLimit)
{
scanNumber = 0;
EditorUtility.UnloadUnusedAssetsImmediate(true);
}
}
EditorTools.ClearProgressBar();
return results;
}
/// <summary>
/// 通用修复快捷方法
/// </summary>
public static void FixAssets(List<ReportElement> fixAssetList, System.Action<ReportElement> fixFun, int unloadAssetLimit = int.MaxValue)
{
int scanNumber = 0;
int totalCount = fixAssetList.Count;
int progressCount = 0;
EditorTools.ClearProgressBar();
foreach (var scanResult in fixAssetList)
{
scanNumber++;
progressCount++;
EditorTools.DisplayProgressBar("修复中...", progressCount, totalCount);
fixFun.Invoke(scanResult);
// 释放编辑器未使用的资源
if (scanNumber >= unloadAssetLimit)
{
scanNumber = 0;
EditorUtility.UnloadUnusedAssetsImmediate(true);
}
}
EditorTools.ClearProgressBar();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 97a68688a58fbb24ba31cd80e808d315
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,198 @@
#if UNITY_2019_4_OR_NEWER
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
using YooAsset.Editor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
[CreateAssetMenu(fileName = "TextureSchema", menuName = "YooAssetArt/Create TextureSchema")]
public class TextureSchema : ScannerSchema
{
/// <summary>
/// 图片最大宽度
/// </summary>
public int MaxWidth = 1024;
/// <summary>
/// 图片最大高度
/// </summary>
public int MaxHeight = 1024;
/// <summary>
/// 测试列表
/// </summary>
public List<string> TestStringValues = new List<string>();
/// <summary>
/// 获取用户指南信息
/// </summary>
public override string GetUserGuide()
{
return "规则介绍:检测图片的格式,尺寸";
}
/// <summary>
/// 运行生成扫描报告
/// </summary>
public override ScanReport RunScanner(AssetArtScanner scanner)
{
// 创建扫描报告
string name = "扫描所有纹理资产";
string desc = GetUserGuide();
var report = new ScanReport(name, desc);
report.AddHeader("资源路径", 600, 500, 1000).SetStretchable().SetSearchable().SetSortable().SetCounter().SetHeaderType(EHeaderType.AssetPath);
report.AddHeader("图片宽度", 100).SetSortable().SetHeaderType(EHeaderType.LongValue);
report.AddHeader("图片高度", 100).SetSortable().SetHeaderType(EHeaderType.LongValue);
report.AddHeader("内存大小", 120).SetSortable().SetUnits("bytes").SetHeaderType(EHeaderType.LongValue);
report.AddHeader("苹果格式", 100);
report.AddHeader("安卓格式", 100);
report.AddHeader("错误信息", 500).SetStretchable();
// 获取扫描资源集合
var searchDirectorys = scanner.Collectors.Select(c => { return c.CollectPath; });
string[] findAssets = EditorTools.FindAssets(EAssetSearchType.Texture, searchDirectorys.ToArray());
// 开始扫描资源集合
var results = SchemaTools.ScanAssets(findAssets, ScanAssetInternal);
report.ReportElements.AddRange(results);
return report;
}
private ReportElement ScanAssetInternal(string assetPath)
{
var importer = TextureTools.GetAssetImporter(assetPath);
if (importer == null)
return null;
// 加载纹理对象
var texture = AssetDatabase.LoadAssetAtPath<Texture>(assetPath);
var assetGUID = AssetDatabase.AssetPathToGUID(assetPath);
var iosFormat = TextureTools.GetPlatformIOSFormat(importer);
var androidFormat = TextureTools.GetPlatformAndroidFormat(importer);
var memorySize = TextureTools.GetStorageMemorySize(texture);
// 获取错误信息
string errorInfo = string.Empty;
{
// 苹果格式
if (iosFormat != TextureImporterFormat.ASTC_4x4)
{
errorInfo += " | ";
errorInfo += "苹果格式不对";
}
// 安卓格式
if (androidFormat != TextureImporterFormat.ASTC_4x4)
{
errorInfo += " | ";
errorInfo += "安卓格式不对";
}
// 多级纹理
if (importer.isReadable)
{
errorInfo += " | ";
errorInfo += "开启了可读写";
}
// 超大纹理
if (texture.width > MaxWidth || texture.height > MaxHeight)
{
errorInfo += " | ";
errorInfo += "超大纹理";
}
}
// 添加扫描信息
ReportElement result = new ReportElement(assetGUID);
result.AddScanInfo("资源路径", assetPath);
result.AddScanInfo("图片宽度", texture.width);
result.AddScanInfo("图片高度", texture.height);
result.AddScanInfo("内存大小", memorySize);
result.AddScanInfo("苹果格式", iosFormat.ToString());
result.AddScanInfo("安卓格式", androidFormat.ToString());
result.AddScanInfo("错误信息", errorInfo);
// 判断是否通过
result.Passes = string.IsNullOrEmpty(errorInfo);
return result;
}
/// <summary>
/// 修复扫描结果
/// </summary>
public override void FixResult(List<ReportElement> fixList)
{
SchemaTools.FixAssets(fixList, FixAssetInternal);
}
private void FixAssetInternal(ReportElement result)
{
var scanInfo = result.GetScanInfo("资源路径");
var assetPath = scanInfo.ScanInfo;
var importer = TextureTools.GetAssetImporter(assetPath);
if (importer == null)
return;
// 苹果格式
var iosPlatformSetting = TextureTools.GetPlatformIOSSettings(importer);
iosPlatformSetting.format = TextureImporterFormat.ASTC_4x4;
iosPlatformSetting.overridden = true;
// 安卓格式
var androidPlatformSetting = TextureTools.GetPlatformAndroidSettings(importer);
androidPlatformSetting.format = TextureImporterFormat.ASTC_4x4;
androidPlatformSetting.overridden = true;
// 可读写
importer.isReadable = false;
// 保存配置
importer.SetPlatformTextureSettings(iosPlatformSetting);
importer.SetPlatformTextureSettings(androidPlatformSetting);
importer.SaveAndReimport();
Debug.Log($"修复了 : {assetPath}");
}
/// <summary>
/// 创建检视面板对
/// </summary>
public override SchemaInspector CreateInspector()
{
var container = new VisualElement();
// 图片最大宽度
var maxWidthField = new IntegerField();
maxWidthField.label = "图片最大宽度";
maxWidthField.SetValueWithoutNotify(MaxWidth);
maxWidthField.RegisterValueChangedCallback((evt) =>
{
MaxWidth = evt.newValue;
});
container.Add(maxWidthField);
// 图片最大高度
var maxHeightField = new IntegerField();
maxHeightField.label = "图片最大高度";
maxHeightField.SetValueWithoutNotify(MaxHeight);
maxHeightField.RegisterValueChangedCallback((evt) =>
{
MaxHeight = evt.newValue;
});
container.Add(maxHeightField);
// 创建测试列表
#if UNITY_2021_3_OR_NEWER
ReorderableListView reorderableListView = new ReorderableListView();
reorderableListView.SourceData = TestStringValues;
reorderableListView.HeaderName = "测试列表";
container.Add(reorderableListView);
#endif
SchemaInspector inspector = new SchemaInspector(container);
return inspector;
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 01b3d3fde6899514396008e1e4f6693b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,104 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
using YooAsset.Editor;
public class TextureTools
{
/// <summary>
/// POT尺寸检测
/// </summary>
public static bool IsPowerOfTwo(Texture tex)
{
if (Mathf.IsPowerOfTwo(tex.width) == false)
return false;
if (Mathf.IsPowerOfTwo(tex.height) == false)
return false;
return true;
}
/// <summary>
/// 获取纹理运行时内存大小
/// </summary>
public static long GetStorageMemorySize(Texture tex)
{
#if UNITY_2022_3_OR_NEWER
var assembly = typeof(AssetDatabase).Assembly;
var type = assembly.GetType("UnityEditor.TextureUtil");
long size = (long)EditorTools.InvokePublicStaticMethod(type, "GetStorageMemorySizeLong", tex);
return size;
#else
var assembly = typeof(AssetDatabase).Assembly;
var type = assembly.GetType("UnityEditor.TextureUtil");
int size = (int)EditorTools.InvokePublicStaticMethod(type, "GetStorageMemorySize", tex);
return size;
#endif
}
/// <summary>
/// 获取当前平台纹理的格式
/// </summary>
public static TextureFormat GetCurrentPlatformTextureFormat(Texture tex)
{
var assembly = typeof(AssetDatabase).Assembly;
var type = assembly.GetType("UnityEditor.TextureUtil");
TextureFormat format = (TextureFormat)EditorTools.InvokePublicStaticMethod(type, "GetTextureFormat", tex);
return format;
}
/// <summary>
/// 获取纹理的导入器
/// </summary>
public static TextureImporter GetAssetImporter(string assetPath)
{
TextureImporter importer = AssetImporter.GetAtPath(assetPath) as TextureImporter;
if (importer == null)
Debug.LogWarning($"Failed to load TextureImporter : {assetPath}");
return importer;
}
public static TextureImporterPlatformSettings GetPlatformPCSettings(TextureImporter importer)
{
TextureImporterPlatformSettings platformSetting = importer.GetPlatformTextureSettings("Standalone");
return platformSetting;
}
public static TextureImporterPlatformSettings GetPlatformIOSSettings(TextureImporter importer)
{
TextureImporterPlatformSettings platformSetting = importer.GetPlatformTextureSettings("iPhone");
return platformSetting;
}
public static TextureImporterPlatformSettings GetPlatformAndroidSettings(TextureImporter importer)
{
TextureImporterPlatformSettings platformSetting = importer.GetPlatformTextureSettings("Android");
return platformSetting;
}
public static TextureImporterFormat GetPlatformPCFormat(TextureImporter importer)
{
TextureImporterPlatformSettings platformSetting = GetPlatformPCSettings(importer);
var format = platformSetting.format;
if (format.ToString().StartsWith("Automatic"))
format = importer.GetAutomaticFormat("Standalone");
return format;
}
public static TextureImporterFormat GetPlatformIOSFormat(TextureImporter importer)
{
TextureImporterPlatformSettings platformSetting = GetPlatformIOSSettings(importer);
var format = platformSetting.format;
if (format.ToString().StartsWith("Automatic"))
format = importer.GetAutomaticFormat("iPhone");
return format;
}
public static TextureImporterFormat GetPlatformAndroidFormat(TextureImporter importer)
{
TextureImporterPlatformSettings platformSetting = GetPlatformAndroidSettings(importer);
var format = platformSetting.format;
if (format.ToString().StartsWith("Automatic"))
format = importer.GetAutomaticFormat("Android");
return format;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 58de59cc0b28bb1468c32bfa606d999d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6065ffea0b03bfb42845888ad42c692f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 83751407b8dde6f4fa9d7722a223ea9f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 615751979a29d8d42adbf3d007555fd0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,55 @@
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using YooAsset;
public class GameStart : MonoBehaviour
{
SceneHandle sceneHandle;
void Start()
{
StartCoroutine(LoadScene());
//StartCoroutine(LoadNetWorkManager());
StartCoroutine(LoadUIManager());
}
IEnumerator LoadScene()
{
sceneHandle = YooAssets.LoadSceneAsync("MirrorRoomOffline");
//sceneHandle = YooAssets.LoadSceneAsync("Game");
sceneHandle.Completed += (handle) =>
{
handle.ActivateScene();
};
yield return sceneHandle;
}
IEnumerator LoadUIManager()
{
AssetHandle _handle = YooAssets.LoadAssetAsync<GameObject>("UIManager");
_handle.Completed += (handle) =>
{
GameObject go = Instantiate((GameObject)_handle.AssetObject);
DontDestroyOnLoad(go);
Debug.Log(_handle.AssetObject);
};
yield return _handle;
}
IEnumerator LoadNetWorkManager()
{
AssetHandle _handle = YooAssets.LoadAssetAsync<GameObject>("MyRoomManager");
_handle.Completed += (handle) =>
{
GameObject go = Instantiate((GameObject)_handle.AssetObject);
DontDestroyOnLoad(go);
Debug.Log(_handle.AssetObject);
};
yield return _handle;
}
// Update is called once per frame
void Update()
{
if(sceneHandle!=null && !sceneHandle.IsDone)
{
Debug.Log(sceneHandle.Progress);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5db6d9ce76043f546b092e210f4512db
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,28 @@
{
"name": "Main",
"rootNamespace": "",
"references": [
"GUID:e34a5702dd353724aa315fb8011f08c3",
"GUID:df380645f10b7bc4b97d4f5eb6303d95",
"GUID:15fc0a57446b3144c949da3e2b9737a9",
"GUID:6055be8ebefd69e48b49212b09b47b2f",
"GUID:75469ad4d38634e559750d17036d5f7c",
"GUID:4307f53044263cf4b835bd812fc161a4",
"GUID:f22fac247a56d2d41b687bb0d900e54e",
"GUID:c55575a9f1747c240822f4b7e0400716",
"GUID:1ea6b676786131e4095182b742bb64ec",
"GUID:8804cd4b3fef1e041ad4f6c94ec49e0c",
"GUID:30817c1a0e6d646d99c048fc403f5979",
"GUID:72872094b21c16e48b631b2224833d49",
"GUID:3a5d3214f3d7fb845bf8991981763e58"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 23bab669d3df73a4c9da776078d30ddc
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6ebf83dfbd6c23248aac2f42449a4cc9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,77 @@
using Mirror;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class MyRoomManager : NetworkRoomManager
{
public static new MyRoomManager singleton => NetworkManager.singleton as MyRoomManager;
public override void OnRoomClientSceneChanged()
{
base.OnRoomClientSceneChanged();
if (networkSceneName == GameplayScene)
{
foreach (MyRoomPlayer player in roomSlots.ToList())
{
player.model.SetActive(false);
}
}
else if (networkSceneName == RoomScene)
{
foreach (MyRoomPlayer player in roomSlots.ToList())
{
player.model.SetActive(true);
}
}
}
public override void OnRoomStopClient()
{
base.OnRoomStopClient();
}
public override void OnRoomStopServer()
{
base.OnRoomStopServer();
}
/*
This code below is to demonstrate how to do a Start button that only appears for the Host player
showStartButton is a local bool that's needed because OnRoomServerPlayersReady is only fired when
all players are ready, but if a player cancels their ready state there's no callback to set it back to false
Therefore, allPlayersReady is used in combination with showStartButton to show/hide the Start button correctly.
Setting showStartButton false when the button is pressed hides it in the game scene since NetworkRoomManager
is set as DontDestroyOnLoad = true.
*/
#if !UNITY_SERVER
bool showStartButton;
#endif
public override void OnRoomServerPlayersReady()
{
// calling the base method calls ServerChangeScene as soon as all players are in Ready state.
if (Utils.IsHeadless())
base.OnRoomServerPlayersReady();
#if !UNITY_SERVER
else
showStartButton = true;
#endif
}
#if !UNITY_SERVER
public override void OnGUI()
{
base.OnGUI();
if (allPlayersReady && showStartButton && GUI.Button(new Rect(150, 300, 120, 20), "START GAME"))
{
// set to false to hide it in the game scene
showStartButton = false;
ServerChangeScene(GameplayScene);
}
}
#endif
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8bf7a40ab294c80448b22b82ca91c15d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,57 @@
using Cinemachine;
using Mirror;
using UnityEngine;
public class MyRoomPlayer : NetworkRoomPlayer
{
public CinemachineVirtualCamera vCam;
public GameObject model;
public override void OnStartClient()
{
//Debug.Log($"OnStartClient {gameObject}");
}
public override void OnClientEnterRoom()
{
//Debug.Log($"OnClientEnterRoom {SceneManager.GetActiveScene().path}");
}
[Command]
public override void CmdChangeReadyState(bool readyState)
{
Debug.Log($"CmdChangeReadyState called (Host={isServer}, Local={isLocalPlayer})");
SetReadyToBegin(readyState);
MyRoomManager room = MyRoomManager.singleton as MyRoomManager;
if (room != null)
{
room.ReadyStatusChanged();
}
//base.CmdChangeReadyState(readyState);
}
public override void OnClientExitRoom()
{
//Debug.Log($"OnClientExitRoom {SceneManager.GetActiveScene().path}");
}
public override void IndexChanged(int oldIndex, int newIndex)
{
//Debug.Log($"IndexChanged {newIndex}");
transform.position += new Vector3(2 * newIndex, 0, 0);
}
public override void ReadyStateChanged(bool oldReadyState, bool newReadyState)
{
//Debug.Log($"ReadyStateChanged {newReadyState}");
}
public override void OnStartLocalPlayer()
{
base.OnStartLocalPlayer();
vCam.Priority = 12;
}
#if !UNITY_SERVER
public override void OnGUI()
{
base.OnGUI();
}
#endif
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 84f3d79682e31e6478b25d85b6ff3f2a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f22eca2a26fff8040b7a28bdddff92e0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AttackController : MonoBehaviour
{
public GameObject Bullet;
public GameObject Root;
public float CD;
public float Timer;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void DoAttack()
{
GameObject go = Instantiate(Bullet);
go.transform.position = Root.transform.position;
go.transform.localScale = new Vector3(0.002f, 0.002f, 0.002f);
go.transform.rotation = Root.transform.rotation;
Timer = Time.time;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ae8de499914d30e438bbef1a3b7d4c5b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,38 @@
using DestroyIt;
using UnityEngine;
public class Bullet : MonoBehaviour
{
public float speed;
public float damage;
public Vector3 dir;
// Start is called before the first frame update
void Start()
{
GetComponent<Rigidbody>().velocity = transform.forward * speed;
dir = transform.forward;
}
// Update is called once per frame
void Update()
{
}
private void OnCollisionEnter(Collision collision)
{
GetComponent<Rigidbody>().velocity = dir * speed;
transform.forward = dir;
if (collision.gameObject.GetComponent<Destructible>())
{
HitEffects hitEffects = collision.gameObject.GetComponentInParent<HitEffects>();
if (hitEffects != null && hitEffects.effects.Count > 0)
hitEffects.PlayEffect(HitBy.Bullet, transform.position, transform.forward);
DestroyIt.Destructible destructible = collision.gameObject.GetComponent<DestroyIt.Destructible>();
destructible.ApplyDamage(damage);
if (destructible.CurrentHitPoints > 0)
{
Destroy(gameObject);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 34477b82ab45be24684e277ce61b0ecc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,262 @@
using Cinemachine;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using YooAsset;
using Mirror;
public class NetWorkThirdCharacterController : NetworkBehaviour
{
#region ThirdCharacterController
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;
public CharacterController controller;
public Animator animator;
public CinemachineVirtualCamera vCam;
public Transform forwardReference;
public Transform model;
private CinemachineFramingTransposer framingTransposer;
private CinemachinePOV pov;
private Vector3 moveDirection;
private Vector3 verticalVelocity;
private Vector2 moveInput;
private bool isGrounded;
private bool isCursorLocked = true;
void Awake()
{
//if (!isLocalPlayer) return;
framingTransposer = vCam.GetCinemachineComponent<CinemachineFramingTransposer>();
pov = vCam.GetCinemachineComponent<CinemachinePOV>();
UpdateCursorState();
}
void Update()
{
if (!isLocalPlayer) return;
ApplyGravity();
Move();
RotateModel();
UpdateAnimator();
}
private void UpdateCursorState()
{
if (!isLocalPlayer) return;
Cursor.lockState = isCursorLocked ? CursorLockMode.Locked : CursorLockMode.None;
Cursor.visible = !isCursorLocked;
if (pov == null) return;
pov.m_HorizontalAxis.m_InputAxisName = isCursorLocked ? "Mouse X" : "";
pov.m_VerticalAxis.m_InputAxisName = isCursorLocked ? "Mouse Y" : "";
pov.m_HorizontalAxis.m_MaxSpeed = isCursorLocked ? 300 : 0;
pov.m_VerticalAxis.m_MaxSpeed = isCursorLocked ? 300 : 0;
}
private void ApplyGravity()
{
if (!isLocalPlayer) return;
isGrounded = controller.isGrounded;
if (isGrounded && verticalVelocity.y < 0)
{
verticalVelocity.y = -2f;
}
else
{
verticalVelocity.y -= gravity * Time.deltaTime;
}
}
private void Move()
{
if (!isLocalPlayer) return;
forwardReference.rotation = Quaternion.AngleAxis(pov.m_HorizontalAxis.Value+transform.eulerAngles.y, Vector3.up);
Vector3 horizontalMovement = forwardReference.TransformDirection(
new Vector3(moveInput.x, 0, moveInput.y)) * moveSpeed;
moveDirection = horizontalMovement + verticalVelocity;
controller.Move(moveDirection * Time.deltaTime);
}
private void RotateModel()
{
if (!isLocalPlayer) return;
if (moveInput == Vector2.zero) return;
float targetAngle = Mathf.Atan2(moveInput.x, moveInput.y) * Mathf.Rad2Deg;
Quaternion targetRotation = forwardReference.rotation * Quaternion.AngleAxis(targetAngle, Vector3.up);
model.rotation = Quaternion.Slerp(model.rotation, targetRotation, turnSpeed * Time.deltaTime);
}
private void UpdateAnimator()
{
if (!isLocalPlayer) return;
if (animator == null) return;
animator.SetBool("Move", moveInput != Vector2.zero);
}
public void OnMove(InputAction.CallbackContext context)
{
if (!isLocalPlayer) return;
moveInput = context.ReadValue<Vector2>();
}
public void OnJump(InputAction.CallbackContext context)
{
if (!isLocalPlayer) return;
if (context.performed && isGrounded)
{
verticalVelocity.y = jumpSpeed;
}
}
public void OnFire(InputAction.CallbackContext context)
{
if (!isLocalPlayer) return;
if (context.performed)
{
animator.SetTrigger("Attack");
}
}
public void OnEsc(InputAction.CallbackContext context)
{
if (!isLocalPlayer) return;
if (context.performed)
{
isCursorLocked = !isCursorLocked;
UpdateCursorState();
if (isCursorLocked)
{
SettingsManager.Instance.CloseSettingWindow();
}
else
{
SettingsManager.Instance.OpenSettingWindow();
}
}
}
public void OnAlt(InputAction.CallbackContext context)
{
if (!isLocalPlayer) return;
if (context.performed)
{
isCursorLocked = false;
UpdateCursorState();
}
else if (context.canceled)
{
isCursorLocked = true;
UpdateCursorState();
}
}
public void OnZoom(InputAction.CallbackContext context)
{
if (!isLocalPlayer) return;
if (framingTransposer == null) return;
float scrollValue = context.ReadValue<float>();
float newDistance = framingTransposer.m_CameraDistance + (scrollValue * cameraZoomSpeed * 0.01f);
framingTransposer.m_CameraDistance = Mathf.Clamp(newDistance, minCameraDistance, maxCameraDistance);
}
#endregion
#region Start & Stop Callbacks
/// <summary>
/// This is invoked for NetworkBehaviour objects when they become active on the server.
/// <para>This could be triggered by NetworkServer.Listen() for objects in the scene, or by NetworkServer.Spawn() for objects that are dynamically created.</para>
/// <para>This will be called for objects on a "host" as well as for object on a dedicated server.</para>
/// </summary>
public override void OnStartServer()
{
Debug.Log("OnStartServer");
}
/// <summary>
/// Invoked on the server when the object is unspawned
/// <para>Useful for saving object data in persistent storage</para>
/// </summary>
public override void OnStopServer() { }
/// <summary>
/// Called on every NetworkBehaviour when it is activated on a client.
/// <para>Objects on the host have this function called, as there is a local client on the host. The values of SyncVars on object are guaranteed to be initialized correctly with the latest state from the server when this function is called on the client.</para>
/// </summary>
public override void OnStartClient()
{
Debug.Log("OnStartClient");
}
/// <summary>
/// This is invoked on clients when the server has caused this object to be destroyed.
/// <para>This can be used as a hook to invoke effects or do client specific cleanup.</para>
/// </summary>
public override void OnStopClient() { }
/// <summary>
/// Called when the local player object has been set up.
/// <para>This happens after OnStartClient(), as it is triggered by an ownership message from the server. This is an appropriate place to activate components or functionality that should only be active for the local player, such as cameras and input.</para>
/// </summary>
public override void OnStartLocalPlayer()
{
Debug.Log("OnStartLocalPlayer");
vCam.Priority = 15;
}
/// <summary>
/// Called when the local player object is being stopped.
/// <para>This happens before OnStopClient(), as it may be triggered by an ownership message from the server, or because the player object is being destroyed. This is an appropriate place to deactivate components or functionality that should only be active for the local player, such as cameras and input.</para>
/// </summary>
public override void OnStopLocalPlayer() { }
/// <summary>
/// This is invoked on behaviours that have authority, based on context and <see cref="NetworkIdentity.hasAuthority">NetworkIdentity.hasAuthority</see>.
/// <para>This is called after <see cref="OnStartServer">OnStartServer</see> and before <see cref="OnStartClient">OnStartClient.</see></para>
/// <para>When <see cref="NetworkIdentity.AssignClientAuthority">AssignClientAuthority</see> is called on the server, this will be called on the client that owns the object. When an object is spawned with <see cref="NetworkServer.Spawn">NetworkServer.Spawn</see> with a NetworkConnectionToClient parameter included, this will be called on the client that owns the object.</para>
/// </summary>
public override void OnStartAuthority() { }
/// <summary>
/// This is invoked on behaviours when authority is removed.
/// <para>When NetworkIdentity.RemoveClientAuthority is called on the server, this will be called on the client that owns the object.</para>
/// </summary>
public override void OnStopAuthority() { }
#endregion
public NetworkAnimator networkAnimator;
[SyncVar(hook = nameof(OnCurCharacterNameChange))]
public string curCharacterName;
public void OnCurCharacterNameChange(string _Old,string _New)
{
animator = null;
model.GetChild(0).gameObject.SetActive(false);
AssetHandle assetHandle = YooAssets.LoadAssetAsync(_New);
assetHandle.Completed += (handle) =>
{
GameObject character = handle.InstantiateSync(model);
animator = character.GetComponent<Animator>();
networkAnimator.animator = animator;
character.transform.SetAsFirstSibling();
curCharacterName = _New;
};
}
public void ChangeCharacter(InputAction.CallbackContext context)
{
if (context.performed && isLocalPlayer)
{
int bindingIndex = context.action.GetBindingIndexForControl(context.control);
CmdChangeCharacter(test[bindingIndex]);
}
}
[Command]
public void CmdChangeCharacter(string name)
{
curCharacterName = name;
}
List<string> test = new List<string>()
{
"Aris",
"Momoi",
"Midori",
"Yuzu",
"CH0200"
};
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e922d666ae574ca41bf0d6be534cb0cb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,190 @@
using Cinemachine;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using YooAsset;
public class ThirdCharacterController : MonoBehaviour
{
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;
public CharacterController controller;
public Animator animator;
public CinemachineVirtualCamera vCam;
public Transform forwardReference;
public Transform model;
private CinemachineFramingTransposer framingTransposer;
private CinemachinePOV pov;
private Vector3 moveDirection;
private Vector3 verticalVelocity;
private Vector2 moveInput;
private bool isGrounded;
private bool isCursorLocked = true;
public bool isLocalPlayer;
string curCharacterName;
public Action<GameObject> changeCharacterComplete;
void Awake()
{
//if (!isLocalPlayer) return;
framingTransposer = vCam.GetCinemachineComponent<CinemachineFramingTransposer>();
pov = vCam.GetCinemachineComponent<CinemachinePOV>();
UpdateCursorState();
ChangeCharacter("Aris");
}
void Update()
{
if (!isLocalPlayer) return;
ApplyGravity();
Move();
RotateModel();
UpdateAnimator();
}
private void UpdateCursorState()
{
if (!isLocalPlayer) return;
Cursor.lockState = isCursorLocked ? CursorLockMode.Locked : CursorLockMode.None;
Cursor.visible = !isCursorLocked;
if (pov == null) return;
pov.m_HorizontalAxis.m_InputAxisName = isCursorLocked ? "Mouse X" : "";
pov.m_VerticalAxis.m_InputAxisName = isCursorLocked ? "Mouse Y" : "";
pov.m_HorizontalAxis.m_MaxSpeed = isCursorLocked ? 300 : 0;
pov.m_VerticalAxis.m_MaxSpeed = isCursorLocked ? 300 : 0;
}
private void ApplyGravity()
{
if (!isLocalPlayer) return;
isGrounded = controller.isGrounded;
if (isGrounded && verticalVelocity.y < 0)
{
verticalVelocity.y = -2f;
}
else
{
verticalVelocity.y -= gravity * Time.deltaTime;
}
}
private void Move()
{
if (!isLocalPlayer) return;
forwardReference.rotation = Quaternion.AngleAxis(pov.m_HorizontalAxis.Value+transform.eulerAngles.y, Vector3.up);
Vector3 horizontalMovement = forwardReference.TransformDirection(
new Vector3(moveInput.x, 0, moveInput.y)) * moveSpeed;
moveDirection = horizontalMovement + verticalVelocity;
controller.Move(moveDirection * Time.deltaTime);
}
private void RotateModel()
{
if (!isLocalPlayer) return;
if (moveInput == Vector2.zero) return;
float targetAngle = Mathf.Atan2(moveInput.x, moveInput.y) * Mathf.Rad2Deg;
Quaternion targetRotation = forwardReference.rotation * Quaternion.AngleAxis(targetAngle, Vector3.up);
model.rotation = Quaternion.Slerp(model.rotation, targetRotation, turnSpeed * Time.deltaTime);
}
private void UpdateAnimator()
{
if (!isLocalPlayer) return;
if (animator == null) return;
animator.SetBool("Move", moveInput != Vector2.zero);
}
public void OnMove(InputAction.CallbackContext context)
{
if (!isLocalPlayer) return;
moveInput = context.ReadValue<Vector2>();
}
public void OnJump(InputAction.CallbackContext context)
{
if (!isLocalPlayer) return;
if (context.performed && isGrounded)
{
verticalVelocity.y = jumpSpeed;
}
}
public void OnEsc(InputAction.CallbackContext context)
{
if (!isLocalPlayer) return;
if (context.performed)
{
isCursorLocked = !isCursorLocked;
UpdateCursorState();
if (isCursorLocked)
{
SettingsManager.Instance.CloseSettingWindow();
}
else
{
SettingsManager.Instance.OpenSettingWindow();
}
}
}
public void OnFire(InputAction.CallbackContext context)
{
if (!isLocalPlayer) return;
if (context.performed)
{
animator.SetTrigger("Attack");
}
}
public void OnAlt(InputAction.CallbackContext context)
{
if (!isLocalPlayer) return;
if (context.performed)
{
isCursorLocked = false;
UpdateCursorState();
}
else if (context.canceled)
{
isCursorLocked = true;
UpdateCursorState();
}
}
public void OnZoom(InputAction.CallbackContext context)
{
if (!isLocalPlayer) return;
if (framingTransposer == null) return;
float scrollValue = context.ReadValue<float>();
float newDistance = framingTransposer.m_CameraDistance + (scrollValue * cameraZoomSpeed * 0.01f);
framingTransposer.m_CameraDistance = Mathf.Clamp(newDistance, minCameraDistance, maxCameraDistance);
}
public void OnChangeCharacter(InputAction.CallbackContext context)
{
if (!isLocalPlayer) return;
if (context.performed)
{
int bindingIndex = context.action.GetBindingIndexForControl(context.control);
ChangeCharacter(test[bindingIndex]);
}
}
public void ChangeCharacter(string name)
{
if (!isLocalPlayer) return;
if (curCharacterName == name) return;
animator = null;
model.GetChild(0).gameObject.SetActive(false);
AssetHandle assetHandle = YooAssets.LoadAssetAsync(name);
assetHandle.Completed += (handle) =>
{
GameObject character = handle.InstantiateSync(model);
animator = character.GetComponent<Animator>();
character.transform.SetAsFirstSibling();
curCharacterName = name;
changeCharacterComplete?.Invoke(character);
};
}
List<string> test = new List<string>()
{
"Aris",
"Momoi",
"Midori",
"Yuzu"
};
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3f5ea1583657bf34da64f427793797f1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d1669278f047d12459ab7558d17707b0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,32 @@
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Audio;
public class AudioPanel : MonoBehaviour
{
[SerializeField] private Slider masterVolumeSlider;
[SerializeField] private AudioMixer audioMixer;
private void OnEnable()
{
masterVolumeSlider.value = SettingsManager.Instance.CurrentSettings.masterVolume;
if (audioMixer == null) audioMixer = FindAnyObjectByType<AudioMixer>();
}
public void OnMasterVolumeChanged(float value)
{
SettingsManager.Instance.CurrentSettings.masterVolume = value;
SetVolume(value);
}
public void ApplySettings()
{
SetVolume(SettingsManager.Instance.CurrentSettings.masterVolume);
}
private void SetVolume(float volume)
{
if (audioMixer)
audioMixer.SetFloat("MasterVolume", Mathf.Log10(Mathf.Max(volume, 0.0001f)) * 20);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 71d4a15b9c9ec1e4d91d6be9e66bd865
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,138 @@
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using TMPro;
using System.Collections;
public class DisplayPanel : MonoBehaviour
{
[Header("UI References")]
[SerializeField] private TMP_Dropdown resolutionDropdown;
[SerializeField] private Toggle fullscreenToggle;
[SerializeField] private Toggle borderlessToggle;
[SerializeField] private TMP_Dropdown displayDropdown;
private Resolution[] resolutions;
private void Awake()
{
InitializeResolutionDropdown();
InitializeDisplayDropdown();
}
private void OnEnable()
{
StartCoroutine(InitializeDelayed());
}
IEnumerator InitializeDelayed()
{
yield return null;
var settings = SettingsManager.Instance.CurrentSettings;
resolutionDropdown.SetValueWithoutNotify(settings.resolutionIndex);
fullscreenToggle.SetIsOnWithoutNotify(settings.fullscreen);
borderlessToggle.SetIsOnWithoutNotify(settings.borderless);
displayDropdown.SetValueWithoutNotify(settings.displayIndex);
UpdateBorderlessToggleState();
}
private void InitializeResolutionDropdown()
{
resolutions = Screen.resolutions;
resolutionDropdown.ClearOptions();
var options = new List<string>();
for (int i = 0; i < resolutions.Length; i++)
{
// ʹ<><CAB9>refreshRateRatio<69><6F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>refreshRate
int refreshRate = Mathf.RoundToInt((float)resolutions[i].refreshRateRatio.value);
options.Add($"{resolutions[i].width}x{resolutions[i].height} {refreshRate}Hz");
}
resolutionDropdown.AddOptions(options);
}
private void InitializeDisplayDropdown()
{
displayDropdown.ClearOptions();
var options = new List<string>();
for (int i = 0; i < Display.displays.Length; i++)
{
options.Add($"Display {i + 1}");
}
displayDropdown.AddOptions(options);
}
public void OnResolutionChanged(int index)
{
SettingsManager.Instance.CurrentSettings.resolutionIndex = index;
ApplySetResolution();
}
public void OnFullscreenChanged(bool value)
{
SettingsManager.Instance.CurrentSettings.fullscreen = value;
UpdateBorderlessToggleState();
ApplySetResolution();
}
public void OnBorderlessChanged(bool value)
{
SettingsManager.Instance.CurrentSettings.borderless = value;
ApplySetResolution();
}
public void OnDisplayChanged(int index)
{
SettingsManager.Instance.CurrentSettings.displayIndex = index;
ApplySetDisplay();
}
private void UpdateBorderlessToggleState()
{
borderlessToggle.interactable = fullscreenToggle.isOn;
if (!fullscreenToggle.isOn)
borderlessToggle.isOn = false;
ApplySetResolution();
}
public void ApplySettings()
{
ApplySetResolution();
ApplySetDisplay();
}
void ApplySetResolution()
{
if (resolutions == null) return;
var settings = SettingsManager.Instance.CurrentSettings;
Resolution res = resolutions[resolutions.Length];
if (settings.resolutionIndex< resolutions.Length)
{
res = resolutions[settings.resolutionIndex];
}
FullScreenMode mode = settings.borderless ?
FullScreenMode.FullScreenWindow :
(settings.fullscreen ? FullScreenMode.ExclusiveFullScreen : FullScreenMode.Windowed);
// ʹ<><CAB9>refreshRateRatio<69><6F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>refreshRate
Screen.SetResolution(
res.width,
res.height,
mode,
res.refreshRateRatio
);
}
void ApplySetDisplay()
{
var settings = SettingsManager.Instance.CurrentSettings;
if (settings.displayIndex > 0 && settings.displayIndex < Display.displays.Length)
{
Display.displays[settings.displayIndex].Activate();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b16c03c5d0a387641a3c978840f52037
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class GeneralPanel : MonoBehaviour
{
[SerializeField] private TMP_InputField serverAddressInput;
private void OnEnable()
{
serverAddressInput.text = SettingsManager.Instance.CurrentSettings.serverAddress;
}
public void OnServerAddressChanged(string value)
{
SettingsManager.Instance.CurrentSettings.serverAddress = value;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4949deb4d1315ae4790fc0068c036c04
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,176 @@
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using TMPro;
using System.Collections;
public class GraphicsPanel : MonoBehaviour
{
[Header("UI References")]
[SerializeField] private TMP_Dropdown qualityDropdown;
[SerializeField] private Toggle vsyncToggle;
[SerializeField] private Slider shadowDistanceSlider;
[SerializeField] private TMP_Dropdown antiAliasingDropdown;
[SerializeField] private Toggle bloomToggle;
[SerializeField] private Slider renderScaleSlider;
[Header("Graphics References")]
[SerializeField] private VolumeProfile urpVolumeProfile;
[Header("Quality Presets")]
[SerializeField]
private QualityPreset[] qualityPresets = new QualityPreset[4]
{
new QualityPreset("Low", 0, false, 20f, 0, false, 0.8f),
new QualityPreset("Medium", 1, false, 40f, 1, true, 1.0f),
new QualityPreset("High", 2, true, 60f, 2, true, 1.2f),
new QualityPreset("Ultra", 3, true, 100f, 2, true, 1.5f)
};
[System.Serializable]
public class QualityPreset
{
public string name;
public int qualityLevel;
public bool vsyncEnabled;
public float shadowDistance;
public int antiAliasing;
public bool bloomEnabled;
public float renderScale;
public QualityPreset(string name, int qualityLevel, bool vsyncEnabled, float shadowDistance,
int antiAliasing, bool bloomEnabled, float renderScale)
{
this.name = name;
this.qualityLevel = qualityLevel;
this.vsyncEnabled = vsyncEnabled;
this.shadowDistance = shadowDistance;
this.antiAliasing = antiAliasing;
this.bloomEnabled = bloomEnabled;
this.renderScale = renderScale;
}
}
private UniversalRenderPipelineAsset _urpAsset;
private Bloom _bloom;
private void OnEnable()
{
StartCoroutine(InitializeDelayed());
}
private IEnumerator InitializeDelayed()
{
yield return null; // <20>ȴ<EFBFBD>һ֡ȷ<D6A1><C8B7>URP<52><50>ʼ<EFBFBD><CABC>
// <20><>ȡURP Asset
_urpAsset = GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
if (_urpAsset == null)
{
Debug.LogError("<22>޷<EFBFBD><DEB7><EFBFBD>ȡURP Asset<65><74><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD>Ŀʹ<C4BF><CAB9>URP");
yield break;
}
// <20><>ȡBloomЧ<6D><D0A7>
if (urpVolumeProfile != null && !urpVolumeProfile.TryGet(out _bloom))
{
Debug.LogWarning("Volume Profile<6C><65>δ<EFBFBD>ҵ<EFBFBD>BloomЧ<6D><D0A7>");
}
// <20><>ʼ<EFBFBD><CABC>UI
//InitializeQualityDropdown();
var settings = SettingsManager.Instance.CurrentSettings;
qualityDropdown.SetValueWithoutNotify(settings.qualityLevel);
vsyncToggle.SetIsOnWithoutNotify(settings.vsyncEnabled);
shadowDistanceSlider.SetValueWithoutNotify(settings.shadowDistance);
antiAliasingDropdown.SetValueWithoutNotify(settings.antiAliasing);
bloomToggle.SetIsOnWithoutNotify(settings.bloomEnabled);
renderScaleSlider.SetValueWithoutNotify(settings.renderScale);
ApplySettings();
}
//private void InitializeQualityDropdown()
//{
// qualityDropdown.ClearOptions();
// foreach (var preset in qualityPresets)
// {
// qualityDropdown.options.Add(new TMP_Dropdown.OptionData(preset.name));
// }
//}
public void OnQualityChanged(int index)
{
SettingsManager.Instance.CurrentSettings.qualityLevel = index;
var settings = SettingsManager.Instance.CurrentSettings;
if (index >= 0 && index < qualityPresets.Length)
{
var preset = qualityPresets[index];
// Ӧ<><D3A6>Ԥ<EFBFBD><D4A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
vsyncToggle.SetIsOnWithoutNotify(preset.vsyncEnabled);
shadowDistanceSlider.SetValueWithoutNotify(preset.shadowDistance);
antiAliasingDropdown.SetValueWithoutNotify(preset.antiAliasing);
bloomToggle.SetIsOnWithoutNotify(preset.bloomEnabled);
renderScaleSlider.SetValueWithoutNotify(preset.renderScale);
}
// <20><><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
OnVSyncChanged(settings.vsyncEnabled);
OnShadowDistanceChanged(settings.shadowDistance);
OnAntiAliasingChanged(settings.antiAliasing);
OnBloomChanged(settings.bloomEnabled);
OnRenderScaleChanged(settings.renderScale);
}
public void OnVSyncChanged(bool value)
{
SettingsManager.Instance.CurrentSettings.vsyncEnabled = value;
QualitySettings.vSyncCount = value ? 1 : 0;
}
public void OnShadowDistanceChanged(float value)
{
SettingsManager.Instance.CurrentSettings.shadowDistance = value;
if (_urpAsset != null)
_urpAsset.shadowDistance = value;
}
public void OnAntiAliasingChanged(int index)
{
SettingsManager.Instance.CurrentSettings.antiAliasing = index;
if (_urpAsset != null)
_urpAsset.msaaSampleCount = (int)Mathf.Pow(2, index);
}
public void OnBloomChanged(bool value)
{
SettingsManager.Instance.CurrentSettings.bloomEnabled = value;
if (_bloom != null)
_bloom.active = value;
}
public void OnRenderScaleChanged(float value)
{
SettingsManager.Instance.CurrentSettings.renderScale = value;
if (_urpAsset != null)
_urpAsset.renderScale = value;
}
public void ApplySettings()
{
if (_urpAsset == null) return;
var settings = SettingsManager.Instance.CurrentSettings;
if (settings.qualityLevel != 4)
QualitySettings.SetQualityLevel(settings.qualityLevel);
QualitySettings.vSyncCount = settings.vsyncEnabled ? 1 : 0;
_urpAsset.shadowDistance = settings.shadowDistance;
_urpAsset.msaaSampleCount = (int)Mathf.Pow(2, settings.antiAliasing);
_urpAsset.renderScale = settings.renderScale;
if (_bloom != null) _bloom.active = settings.bloomEnabled;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0a15301d059dcf34ea494f21cef46548
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,94 @@
using UnityEngine;
using System.IO;
using YooAsset;
using System;
public class SettingsManager : MonoBehaviour
{
public static SettingsManager Instance { get; private set; }
private GameSettings _currentSettings;
private SettingsWindow settingsWindow;
public GameSettings CurrentSettings => _currentSettings;
private string settingsPath;
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
settingsPath = Path.Combine(Application.persistentDataPath, "settings.json");
LoadSettings();
}
public void LoadSettings()
{
if (File.Exists(settingsPath))
{
string json = File.ReadAllText(settingsPath);
_currentSettings = JsonUtility.FromJson<GameSettings>(json);
}
else
{
ResetToDefaultSettings();
}
}
public void SaveSettings()
{
string json = JsonUtility.ToJson(_currentSettings, true);
File.WriteAllText(settingsPath, json);
}
public void ResetToDefaultSettings()
{
_currentSettings = new GameSettings();
SaveSettings();
}
public void OpenSettingWindow()
{
if (settingsWindow != null)
{
settingsWindow.gameObject.SetActive(true);
}
else
{
YooAssets.LoadAssetAsync<GameObject>("SettingsWindow").Completed += (handle) =>
{
settingsWindow = GameObject.Instantiate((GameObject)handle.AssetObject, GameManager.Inst.MainUICanvas.transform).GetComponent<SettingsWindow>();
};
}
}
public void CloseSettingWindow()
{
if (settingsWindow != null)
{
settingsWindow.gameObject.SetActive(false);
}
}
}
[System.Serializable]
public class GameSettings
{
public string serverAddress = "http://127.0.0.1:8080";
public float masterVolume = 0.75f;
public int qualityLevel = 2;
public bool vsyncEnabled = true;
public float shadowDistance = 50f;
public int antiAliasing = 2;
public bool bloomEnabled = true;
public float renderScale = 1.0f;
public int resolutionIndex = 0;
public bool fullscreen = true;
public bool borderless = false;
public int displayIndex = 0;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2d1ed5819e87e0f4ebbdf4dad51fcb7a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,90 @@
using UnityEngine;
using UnityEngine.UI;
public class SettingsWindow : MonoBehaviour
{
[Header("Panels")]
public GameObject generalPanel;
public GameObject audioPanel;
public GameObject graphicsPanel;
public GameObject displayPanel;
[Header("Tab Buttons")]
public Button generalTab;
public Button audioTab;
public Button graphicsTab;
public Button displayTab;
[Header("Action Buttons")]
public Button applyButton;
public Button cancelButton;
public Button defaultsButton;
public Button quitButton;
private GameObject currentPanel;
private void Awake()
{
// <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>ǩҳ<C7A9><D2B3>ť
generalTab.onClick.AddListener(() => SwitchPanel(generalPanel));
audioTab.onClick.AddListener(() => SwitchPanel(audioPanel));
graphicsTab.onClick.AddListener(() => SwitchPanel(graphicsPanel));
displayTab.onClick.AddListener(() => SwitchPanel(displayPanel));
// <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ť
applyButton.onClick.AddListener(ApplyAllSettings);
cancelButton.onClick.AddListener(CloseWindow);
defaultsButton.onClick.AddListener(ResetToDefaults);
quitButton.onClick.AddListener(() => { Application.Quit(); });
// Ĭ<>ϴ򿪵<CFB4>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
SwitchPanel(generalPanel);
}
private void SwitchPanel(GameObject newPanel)
{
if (currentPanel != null)
currentPanel.SetActive(false);
newPanel.SetActive(true);
currentPanel = newPanel;
UpdateTabButtons();
}
private void UpdateTabButtons()
{
generalTab.interactable = currentPanel != generalPanel;
audioTab.interactable = currentPanel != audioPanel;
graphicsTab.interactable = currentPanel != graphicsPanel;
displayTab.interactable = currentPanel != displayPanel;
}
public void ApplyAllSettings()
{
// Ӧ<><D3A6><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD>ã<EFBFBD><C3A3><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>ִ<EFBFBD>У<EFBFBD>
displayPanel.GetComponent<DisplayPanel>().ApplySettings();
// Ӧ<><D3A6>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
graphicsPanel.GetComponent<GraphicsPanel>().ApplySettings();
// Ӧ<><D3A6><EFBFBD><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>
audioPanel.GetComponent<AudioPanel>().ApplySettings();
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
SettingsManager.Instance.SaveSettings();
CloseWindow();
}
public void CloseWindow()
{
// <20><><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD>
SettingsManager.Instance.LoadSettings();
gameObject.SetActive(false);
}
public void ResetToDefaults()
{
SettingsManager.Instance.ResetToDefaultSettings();
SwitchPanel(currentPanel); // ˢ<>µ<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4d6ce7fe9c8bcb144bfed87170589a6e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
using UnityEngine;
public class Test : MonoBehaviour
{
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5cc3b18a638faa5499da9f527721a48d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6dbb9e263bc48ee45a2bf54a6970a16d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Video;
using YooAsset;
public class PatchWindow : MonoBehaviour
{
public Text statusText;
public Slider progressBar;
public Text downloadSizeText;
public VideoPlayer video;
private void Awake()
{
video.targetCamera = GameManager.Inst.UICamera;
}
IEnumerator Start()
{
GameManager.Inst.MainUICanvas.transform.Find("InitBg").gameObject.SetActive(false);
//更新Main
var operation = new PatchOperation(PatchManager.Inst.MainData(Boot.Inst.PlayMode, (data) =>
{
progressBar.value = data.Progress;
downloadSizeText.text = $"{data.CurrentDownloadBytes / 1024f / 1024f:F1}MB/{data.TotalDownloadBytes / 1024f / 1024f:F1}MB";
}));
YooAssets.StartOperation(operation);
yield return operation;
if(operation.Status == EOperationStatus.Succeed)
{
statusText.text = "更新完成";
YooAssets.SetDefaultPackage(YooAssets.GetPackage("Main"));
GameManager.Inst.LoadDll(YooAssets.GetPackage("Main"), "Main");
AssetHandle gameStartHandle = YooAssets.GetPackage("Main").LoadAssetAsync<GameObject>("GameStart");
gameStartHandle.InstantiateAsync();
}
else
{
statusText.text = "更新失败";
}
gameObject.SetActive(false);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e3ea340f8e2ac8b4697e13772a6a4df5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
{
"name": "Preload",
"rootNamespace": "",
"references": [
"GUID:e34a5702dd353724aa315fb8011f08c3",
"GUID:f22fac247a56d2d41b687bb0d900e54e",
"GUID:c55575a9f1747c240822f4b7e0400716",
"GUID:1ea6b676786131e4095182b742bb64ec",
"GUID:8804cd4b3fef1e041ad4f6c94ec49e0c"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 90f60af8868b92c498beb9f677f8731a
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 631e5633e0d02ff49b08cb300f7139a6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,55 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Event;
using YooAsset;
public class Boot : Singleton<Boot>
{
public GameObject MainUICanvas;
public Camera UICamera;
public List<string> DepDlls = new List<string>()
{
"mscorlib.dll",
"System.dll",
"System.Core.dll",
"Mirror.dll"
};
public List<GameObject> DontDestroyObjs = new List<GameObject>();
/// <summary>
/// 资源系统运行模式
/// </summary>
public EPlayMode PlayMode = EPlayMode.EditorSimulateMode;
void Awake()
{
Debug.Log($"资源系统运行模式:{PlayMode}");
Debug.Log($"Application.persistentDataPath{Application.persistentDataPath}");
Application.targetFrameRate = 60;
Application.runInBackground = true;
}
IEnumerator Start()
{
foreach (GameObject obj in DontDestroyObjs)
{
DontDestroyOnLoad(obj);
}
GameManager.Inst.Behaviour = this;
GameManager.Inst.MainUICanvas = MainUICanvas;
GameManager.Inst.UICamera = UICamera;
GameManager.Inst.LoadServerSettings();
YooAssets.Initialize();
//更新Preload
var operation = new PatchOperation(PatchManager.Inst.PreloadData(PlayMode));
YooAssets.StartOperation(operation);
yield return operation;
//加载更新界面Main更新流程以及GameStart调用在PatchWindow中
GameManager.Inst.LoadDll(YooAssets.GetPackage("Preload"), "Preload");
AssetHandle patchWindowHandle = YooAssets.GetPackage("Preload").LoadAssetAsync<GameObject>("PatchWindow");
patchWindowHandle.InstantiateAsync(GameManager.Inst.MainUICanvas.transform);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 41fef9a778e4e254b939e9dc3e553bf0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,23 @@
{
"name": "MyScripts.Runtime",
"rootNamespace": "",
"references": [
"GUID:e34a5702dd353724aa315fb8011f08c3",
"GUID:13ba8ce62aa80c74598530029cb2d649",
"GUID:f22fac247a56d2d41b687bb0d900e54e",
"GUID:c55575a9f1747c240822f4b7e0400716",
"GUID:1ea6b676786131e4095182b742bb64ec",
"GUID:fecf25954bb196642ab50657689761d6",
"GUID:30817c1a0e6d646d99c048fc403f5979",
"GUID:72872094b21c16e48b631b2224833d49"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8804cd4b3fef1e041ad4f6c94ec49e0c
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,24 @@
using UnityEngine;
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T _instance;
public static T Inst
{
get
{
if (_instance == null)
{
_instance = FindAnyObjectByType<T>();
if (_instance == null)
{
GameObject singletonObject = new GameObject(typeof(T).Name);
_instance = singletonObject.AddComponent<T>();
}
}
return _instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1e38d108023ce9d4ca9206ac329be382
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f8a154c95ffcec148b4d3170628a4dca
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 81ae789e37712a9409c6f805d7236f42
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,81 @@
using HybridCLR;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using UnityEngine;
using YooAsset;
using static UnityEngine.Rendering.VirtualTexturing.Debugging;
public class GameManager
{
public MonoBehaviour Behaviour;
public string ServerAddress;
public bool isServer;
public GameObject MainUICanvas;
public Camera UICamera;
private static GameManager _instance;
public static GameManager Inst
{
get
{
if (_instance == null)
_instance = new GameManager();
return _instance;
}
}
public void StartCoroutine(IEnumerator enumerator)
{
Behaviour.StartCoroutine(enumerator);
}
public void LoadDll(ResourcePackage package, string dll)
{
if (package.GetAssetInfo(dll).Error == string.Empty)
{
AssetHandle handle = package.LoadAssetSync<TextAsset>(dll);
#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 void LoadDepDll(ResourcePackage package,List<string> dlls)
{
foreach (string dll in dlls)
{
if (package.GetAssetInfo(dll).Error == string.Empty)
{
AssetHandle handle = package.LoadAssetSync<TextAsset>(dll);
RuntimeApi.LoadMetadataForAOTAssembly((handle.AssetObject as TextAsset).bytes, HomologousImageMode.SuperSet);
}
}
}
public void LoadServerSettings()
{
string settingsPath = Path.Combine(Application.persistentDataPath, "settings.json");
if (File.Exists(settingsPath))
{
string json = File.ReadAllText(settingsPath);
ServerAddress = JsonUtility.FromJson<ServerSettings>(json).serverAddress;
isServer = JsonUtility.FromJson<ServerSettings>(json).isServer;
Debug.Log(ServerAddress);
}
else
{
string json = JsonUtility.ToJson(new ServerSettings(), true);
File.WriteAllText(settingsPath, json);
}
}
[System.Serializable]
public class ServerSettings
{
public string serverAddress;
public bool isServer;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f6630e7de79efb24b9263519ba4282e1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 81fbe3bfa76809b4d82e46e8889d805e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 22a43ec58b9da1743bfa629be08ef1ac
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Machine;
using YooAsset;
internal class FsmClearCacheBundle : IStateNode
{
private StateMachine _machine;
PatchOperationData data;
void IStateNode.OnCreate(StateMachine machine)
{
_machine = machine;
}
void IStateNode.OnEnter()
{
data = (PatchOperationData)_machine.GetBlackboardValue("PatchOperationData");
var packageName = data.packageName;
var package = YooAssets.GetPackage(packageName);
var operation = package.ClearCacheFilesAsync(EFileClearMode.ClearUnusedBundleFiles);
operation.Completed += Operation_Completed;
}
void IStateNode.OnUpdate()
{
}
void IStateNode.OnExit()
{
}
private void Operation_Completed(YooAsset.AsyncOperationBase obj)
{
_machine.ChangeState<FsmStartGame>();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1d83ce785f1442a40a1ad0f837073b69
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,68 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Machine;
using YooAsset;
public class FsmCreateDownloader : IStateNode
{
private StateMachine _machine;
PatchOperationData data;
void IStateNode.OnCreate(StateMachine machine)
{
_machine = machine;
}
void IStateNode.OnEnter()
{
data = (PatchOperationData)_machine.GetBlackboardValue("PatchOperationData");
Debug.Log($"创建资源下载器{data.packageName}");
CreateDownloader();
}
void IStateNode.OnUpdate()
{
}
void IStateNode.OnExit()
{
}
void CreateDownloader()
{
var packageName = data.packageName;
var package = YooAssets.GetPackage(packageName);
var downloader = package.CreateResourceDownloader(10, 3);
downloader.DownloadErrorCallback = data.downloadError;
downloader.DownloadFinishCallback = data.downloadFinish;
downloader.DownloadUpdateCallback = data.downloadUpdate;
var curVersion = PlayerPrefs.GetString($"{packageName}_Version", string.Empty);
var packageVersion = (string)_machine.GetBlackboardValue($"{packageName}_Version");
_machine.SetBlackboardValue($"{packageName}_Downloader", downloader);
if (downloader.TotalDownloadCount == 0)
{
Debug.Log("Not found any download files !");
_machine.ChangeState<FsmStartGame>();
}
else
{
if (data.autoDownload)
{
_machine.ChangeState<FsmDownloadPackageFiles>();
}
else
{
MessageBox.Show()
.SetTitle(packageName)
.SetContent($"发现资源更新\n{curVersion}=>{packageVersion}: {downloader.TotalDownloadBytes / 1024f / 1024f:F1}MB")
.AddButton("下载", (box) => { _machine.ChangeState<FsmDownloadPackageFiles>(); })
.AddButton("取消", (box) =>
{
downloader.CancelDownload();
data.useLocal = true;
_machine.SetBlackboardValue("PatchOperationData", data);
_machine.ChangeState<FsmRequestPackageVersion>();
})
.AddButton("退出", (box) => { Application.Quit(); });
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8b104741ebcb72946abe282c1da73360
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,44 @@
using System.Collections;
using UnityEngine;
using UniFramework.Machine;
using YooAsset;
public class FsmDownloadPackageFiles : IStateNode
{
private StateMachine _machine;
PatchOperationData data;
void IStateNode.OnCreate(StateMachine machine)
{
_machine = machine;
}
void IStateNode.OnEnter()
{
data = (PatchOperationData)_machine.GetBlackboardValue("PatchOperationData");
Debug.Log($"{data.packageName}开始下载资源文件");
GameManager.Inst.StartCoroutine(BeginDownload());
}
void IStateNode.OnUpdate()
{
}
void IStateNode.OnExit()
{
}
private IEnumerator BeginDownload()
{
var downloader = (ResourceDownloaderOperation)_machine.GetBlackboardValue($"{data.packageName}_Downloader");
downloader.BeginDownload();
yield return downloader;
// 检测下载结果
if (downloader.Status != EOperationStatus.Succeed)
{
MessageBox.Show()
.SetTitle(data.packageName)
.SetContent($"下载失败{downloader.Error}")
.AddButton("退出", (box) => { Application.Quit(); });
yield break;
}
_machine.ChangeState<FsmDownloadPackageOver>();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a3fae22040fe2d541ab4582c7c1c71fb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Machine;
using YooAsset;
internal class FsmDownloadPackageOver : IStateNode
{
private StateMachine _machine;
PatchOperationData data;
void IStateNode.OnCreate(StateMachine machine)
{
_machine = machine;
}
void IStateNode.OnEnter()
{
data = (PatchOperationData)_machine.GetBlackboardValue("PatchOperationData");
Debug.Log($"{data.packageName}下载完成");
//// 注意:下载完成之后再保存本地版本
//if (data.playMode != EPlayMode.EditorSimulateMode)
//{
// var packageVersion = (string)_machine.GetBlackboardValue($"{data.packageName}_Version");
// PlayerPrefs.SetString($"{data.packageName}_Version", packageVersion);
// Debug.Log($"{data.packageName} 更新流程完毕 保存版本{packageVersion}");
//}
_machine.ChangeState<FsmClearCacheBundle>();
}
void IStateNode.OnUpdate()
{
}
void IStateNode.OnExit()
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c96c57c65f74bb3469dc71b13ef78c84
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,163 @@
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Machine;
using YooAsset;
internal class FsmInitializePackage : IStateNode
{
private StateMachine _machine;
PatchOperationData data;
void IStateNode.OnCreate(StateMachine machine)
{
_machine = machine;
}
void IStateNode.OnEnter()
{
data = (PatchOperationData)_machine.GetBlackboardValue("PatchOperationData");
Debug.Log($"初始化{data.packageName},下载路径:{GetHostServerURL(data.packageName)}");
GameManager.Inst.StartCoroutine(InitPackage());
}
void IStateNode.OnUpdate()
{
}
void IStateNode.OnExit()
{
}
private IEnumerator InitPackage()
{
var playMode = data.playMode;
var packageName = data.packageName;
// 创建资源包裹类
var package = YooAssets.TryGetPackage(packageName);
if (package == null)
package = YooAssets.CreatePackage(packageName);
// 编辑器下的模拟模式
InitializationOperation initializationOperation = null;
if (playMode == EPlayMode.EditorSimulateMode)
{
var buildResult = EditorSimulateModeHelper.SimulateBuild(packageName);
var packageRoot = buildResult.PackageRootDirectory;
var createParameters = new EditorSimulateModeParameters();
createParameters.EditorFileSystemParameters = FileSystemParameters.CreateDefaultEditorFileSystemParameters(packageRoot);
initializationOperation = package.InitializeAsync(createParameters);
}
// 单机运行模式
if (playMode == EPlayMode.OfflinePlayMode)
{
var createParameters = new OfflinePlayModeParameters();
createParameters.BuildinFileSystemParameters = FileSystemParameters.CreateDefaultBuildinFileSystemParameters();
initializationOperation = package.InitializeAsync(createParameters);
}
// 联机运行模式
if (playMode == EPlayMode.HostPlayMode)
{
// 注意设置参数COPY_BUILDIN_PACKAGE_MANIFEST可以初始化的时候拷贝内置清单到沙盒目录
var buildinFileSystemParams = FileSystemParameters.CreateDefaultBuildinFileSystemParameters();
buildinFileSystemParams.AddParameter(FileSystemParametersDefine.COPY_BUILDIN_PACKAGE_MANIFEST, true);
string defaultHostServer = GetHostServerURL(packageName);
string fallbackHostServer = GetHostServerURL(packageName);
IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
// 注意设置参数INSTALL_CLEAR_MODE可以解决覆盖安装的时候将拷贝的内置清单文件清理的问题。
var cacheFileSystemParams = FileSystemParameters.CreateDefaultCacheFileSystemParameters(remoteServices);
cacheFileSystemParams.AddParameter(FileSystemParametersDefine.INSTALL_CLEAR_MODE, EOverwriteInstallClearMode.None);
var createParameters = new HostPlayModeParameters();
createParameters.BuildinFileSystemParameters = packageName == "Preload" ? buildinFileSystemParams : null;
createParameters.CacheFileSystemParameters = cacheFileSystemParams;
initializationOperation = package.InitializeAsync(createParameters);
}
// WebGL运行模式
if (playMode == EPlayMode.WebPlayMode)
{
#if UNITY_WEBGL && WEIXINMINIGAME && !UNITY_EDITOR
var createParameters = new WebPlayModeParameters();
string defaultHostServer = GetHostServerURL(packageName);
string fallbackHostServer = GetHostServerURL(packageName);
string packageRoot = $"{WeChatWASM.WX.env.USER_DATA_PATH}/__GAME_FILE_CACHE"; //注意:如果有子目录,请修改此处!
IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
createParameters.WebServerFileSystemParameters = WechatFileSystemCreater.CreateFileSystemParameters(packageRoot, remoteServices);
initializationOperation = package.InitializeAsync(createParameters);
#else
var createParameters = new WebPlayModeParameters();
createParameters.WebServerFileSystemParameters = FileSystemParameters.CreateDefaultWebServerFileSystemParameters();
initializationOperation = package.InitializeAsync(createParameters);
#endif
}
yield return initializationOperation;
// 如果初始化失败弹出提示界面
if (initializationOperation.Status != EOperationStatus.Succeed)
{
MessageBox.Show()
.SetTitle(packageName)
.SetContent($"{initializationOperation.Error}")
.AddButton("退出", (box) => { Application.Quit(); });
}
else
{
_machine.ChangeState<FsmRequestPackageVersion>();
}
}
/// <summary>
/// 获取资源服务器地址
/// </summary>
public string GetHostServerURL(string packageName)
{
string hostServerIP = $"http://localhost:8080/{Application.productName}";
if (GameManager.Inst.ServerAddress != "" && GameManager.Inst.ServerAddress != null)
hostServerIP = $"{GameManager.Inst.ServerAddress}/{Application.productName}";
string appVersion = "v1";
#if UNITY_EDITOR
if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.Android)
return $"{hostServerIP}/CDN/Android/{packageName}/{appVersion}";
else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.iOS)
return $"{hostServerIP}/CDN/IPhone/{packageName}/{appVersion}";
else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.WebGL)
return $"{hostServerIP}/CDN/WebGL/{packageName}/{appVersion}";
else
return $"{hostServerIP}/CDN/PC/{packageName}/{appVersion}";
#else
if (Application.platform == RuntimePlatform.Android)
return $"{hostServerIP}/CDN/Android/{packageName}/{appVersion}";
else if (Application.platform == RuntimePlatform.IPhonePlayer)
return $"{hostServerIP}/CDN/IPhone/{packageName}/{appVersion}";
else if (Application.platform == RuntimePlatform.WebGLPlayer)
return $"{hostServerIP}/CDN/WebGL/{packageName}/{appVersion}";
else
return $"{hostServerIP}/CDN/PC/{packageName}/{appVersion}";
#endif
}
/// <summary>
/// 远端资源地址查询服务类
/// </summary>
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}";
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9c67e6e479b68e345afcdf325775c079
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,60 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Machine;
using YooAsset;
internal class FsmRequestPackageVersion : IStateNode
{
private StateMachine _machine;
PatchOperationData data;
void IStateNode.OnCreate(StateMachine machine)
{
_machine = machine;
}
void IStateNode.OnEnter()
{
data = (PatchOperationData)_machine.GetBlackboardValue("PatchOperationData");
Debug.Log($"更新版本信息{data.packageName}");
GameManager.Inst.StartCoroutine(UpdatePackageVersion());
}
void IStateNode.OnUpdate()
{
}
void IStateNode.OnExit()
{
}
private IEnumerator UpdatePackageVersion()
{
var packageName = data.packageName;
var package = YooAssets.GetPackage(packageName);
var operation = package.RequestPackageVersionAsync(true,10);
var curVersion = PlayerPrefs.GetString($"{packageName}_Version", string.Empty);
yield return operation;
if (operation.Status != EOperationStatus.Succeed || data.useLocal)
{
Debug.LogWarning(operation.Error);
if (string.IsNullOrEmpty(curVersion))
{
MessageBox.Show()
.SetTitle(packageName)
.SetContent(operation.Error)
.AddButton("退出", (box) => { Application.Quit(); });
}
else
{
Debug.Log($"{packageName}获取上次成功记录的版本{curVersion}");
_machine.SetBlackboardValue($"{packageName}_Version", curVersion);
_machine.ChangeState<FsmUpdatePackageManifest>();
}
}
else
{
Debug.Log($"{packageName}获取远端资源版本成功{operation.PackageVersion}");
_machine.SetBlackboardValue($"{packageName}_Version", operation.PackageVersion);
_machine.ChangeState<FsmUpdatePackageManifest>();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f5ea76dfe0fc52b47a00a3bf68a54d09
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,35 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Machine;
using YooAsset;
internal class FsmStartGame : IStateNode
{
private PatchOperation _owner;
private StateMachine _machine;
PatchOperationData data;
void IStateNode.OnCreate(StateMachine machine)
{
_owner = machine.Owner as PatchOperation;
_machine = machine;
}
void IStateNode.OnEnter()
{
data = (PatchOperationData)_machine.GetBlackboardValue("PatchOperationData");
if (data.playMode != EPlayMode.EditorSimulateMode)
{
var packageVersion = (string)_machine.GetBlackboardValue($"{data.packageName}_Version");
PlayerPrefs.SetString($"{data.packageName}_Version", packageVersion);
Debug.Log($"{data.packageName} 更新流程完毕 保存版本{packageVersion}");
}
_owner.SetFinish();
}
void IStateNode.OnUpdate()
{
}
void IStateNode.OnExit()
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6cf80cfbed474c34b892eaeda7fcb054
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,51 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniFramework.Machine;
using YooAsset;
public class FsmUpdatePackageManifest : IStateNode
{
private StateMachine _machine;
PatchOperationData data;
void IStateNode.OnCreate(StateMachine machine)
{
_machine = machine;
}
void IStateNode.OnEnter()
{
data = (PatchOperationData)_machine.GetBlackboardValue("PatchOperationData");
Debug.Log($"更新资源清单{data.packageName}");
GameManager.Inst.StartCoroutine(UpdateManifest());
}
void IStateNode.OnUpdate()
{
}
void IStateNode.OnExit()
{
}
private IEnumerator UpdateManifest()
{
var packageName = data.packageName;
var packageVersion = (string)_machine.GetBlackboardValue($"{packageName}_Version");
var package = YooAssets.GetPackage(packageName);
var operation = package.UpdatePackageManifestAsync(packageVersion);
yield return operation;
if (operation.Status != EOperationStatus.Succeed)
{
Debug.LogWarning(operation.Error);
MessageBox.Show()
.SetTitle(packageName)
.SetContent(operation.Error)
.AddButton("退出", (box) => { Application.Quit(); });
yield break;
}
else
{
Debug.Log($"{packageName}资源清单更新成功");
_machine.ChangeState<FsmCreateDownloader>();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 13faaa12de67f5e4db31cd8a44563089
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,39 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
public class PatchManager : Singleton<PatchManager>
{
public PatchOperationData PreloadData(EPlayMode PlayMode)
{
PatchOperationData preload = new PatchOperationData();
preload.packageName = "Preload";
preload.playMode = PlayMode;
preload.autoDownload = true;
//preload.downloadError = DefDownloadError;
//preload.downloadFinish = DefDownloadFinsh;
return preload;
}
public PatchOperationData MainData(EPlayMode PlayMode, DownloaderOperation.DownloadUpdate DownloadUpdate)
{
PatchOperationData main = new PatchOperationData();
main.packageName = "Main";
main.playMode = PlayMode;
main.autoDownload = GameManager.Inst.isServer?true:false;
//main.downloadError = DefDownloadError;
main.downloadUpdate = DownloadUpdate;
//main.downloadFinish = DefDownloadFinsh;
return main;
}
//Ĭ<><C4AC><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD><D8B4><EFBFBD>ص<EFBFBD>
//public void DefDownloadError(DownloadErrorData downloadErrorData)
//{
// MessageBox.Show()
// .SetTitle(packageName)
// .SetContent(downloadErrorData.ErrorInfo)
// .AddButton("<22>˳<EFBFBD>", (box) => { Application.Quit(); });
//}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 45a555daf207acb4cb579cd5bdf270a5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,72 @@
using UnityEngine;
using UniFramework.Machine;
using UniFramework.Event;
using YooAsset;
public class PatchOperation : GameAsyncOperation
{
private enum ESteps
{
None,
Update,
Done,
}
private readonly EventGroup _eventGroup = new EventGroup();
private readonly StateMachine _machine;
private readonly string _packageName;
private ESteps _steps = ESteps.None;
public PatchOperation(PatchOperationData data)
{
_packageName = data.packageName;
// 创建状态机
_machine = new StateMachine(this);
_machine.AddNode<FsmInitializePackage>();
_machine.AddNode<FsmRequestPackageVersion>();
_machine.AddNode<FsmUpdatePackageManifest>();
_machine.AddNode<FsmCreateDownloader>();
_machine.AddNode<FsmDownloadPackageFiles>();
_machine.AddNode<FsmDownloadPackageOver>();
_machine.AddNode<FsmClearCacheBundle>();
_machine.AddNode<FsmStartGame>();
_machine.SetBlackboardValue("PatchOperationData", data);
}
protected override void OnStart()
{
_steps = ESteps.Update;
_machine.Run<FsmInitializePackage>();
}
protected override void OnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.Update)
{
_machine.Update();
}
}
protected override void OnAbort()
{
}
public void SetFinish()
{
_steps = ESteps.Done;
_eventGroup.RemoveAllListener();
Status = EOperationStatus.Succeed;
Debug.Log($"Package {_packageName} patch done !");
}
}
public class PatchOperationData
{
public string packageName;
public EPlayMode playMode;
public bool autoDownload;
public bool useLocal;
public DownloaderOperation.DownloadError downloadError;
public DownloaderOperation.DownloaderFinish downloadFinish;
public DownloaderOperation.DownloadUpdate downloadUpdate;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4c1b4cadd806a1a409db720564a44a83
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5b859cdb20aace34b9b9080421cfc9e9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,86 @@
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections.Generic;
public class MessageBox : MonoBehaviour
{
[SerializeField] private GameObject panel;
[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()
{
if (hiddenMessageBoxes.Count > 0)
{
MessageBox box = hiddenMessageBoxes[0];
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, GameManager.Inst.MainUICanvas.transform);
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);
}
createdButtons.Clear();
}
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);
Hide();
});
createdButtons.Add(button);
button.gameObject.SetActive(true);
return this;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 639f3e5fe9a96404293c528ac57562dd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: