Update samples

This commit is contained in:
hevinci
2022-07-18 14:59:15 +08:00
parent df5f0b9c13
commit 95e6921a4e
357 changed files with 0 additions and 8 deletions

View File

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

View File

@@ -0,0 +1,11 @@
using System;
using System.IO;
using YooAsset.Editor;
public class CollectShaderVariants : IFilterRule
{
public bool IsCollectAsset(FilterRuleData data)
{
return Path.GetExtension(data.AssetPath) == ".shadervariants";
}
}

View File

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

View File

@@ -0,0 +1,10 @@
using System;
using YooAsset.Editor;
public class PackShaderVariants : IPackRule
{
public string GetBundleName(PackRuleData data)
{
return "myshaders";
}
}

View File

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

View File

@@ -0,0 +1,37 @@
using System;
using YooAsset.Editor;
public class EncryptionNone : IEncryptionServices
{
bool IEncryptionServices.Check(string bundleName)
{
return false;
}
byte[] IEncryptionServices.Encrypt(byte[] fileData)
{
throw new System.NotImplementedException();
}
}
public class GameEncryption : IEncryptionServices
{
/// <summary>
/// 检测资源包是否需要加密
/// </summary>
bool IEncryptionServices.Check(string bundleName)
{
// 对配置表进行加密
return bundleName.Contains("assets/gameres/config/");
}
/// <summary>
/// 对数据进行加密,并返回加密后的数据
/// </summary>
byte[] IEncryptionServices.Encrypt(byte[] fileData)
{
int offset = 32;
var temper = new byte[fileData.Length + offset];
Buffer.BlockCopy(fileData, 0, temper, offset, fileData.Length);
return temper;
}
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,15 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotateSelf : MonoBehaviour
{
public Vector3 Axis = Vector3.up;
private float _speed = 30f;
void Update()
{
this.transform.Rotate(Axis, Time.deltaTime * _speed);
}
}

View File

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

View File

@@ -0,0 +1,104 @@
using System;
using System.Collections;
using UnityEngine;
using YooAsset;
public class BootScene : MonoBehaviour
{
public static BootScene Instance { private set; get; }
public static YooAssets.EPlayMode GamePlayMode;
public YooAssets.EPlayMode PlayMode = YooAssets.EPlayMode.EditorSimulateMode;
void Awake()
{
Instance = this;
Application.targetFrameRate = 60;
Application.runInBackground = true;
}
void OnGUI()
{
GUIConsole.OnGUI();
}
void OnDestroy()
{
Instance = null;
}
void Update()
{
EventManager.Update();
FsmManager.Update();
}
IEnumerator Start()
{
GamePlayMode = PlayMode;
Debug.Log($"资源系统运行模式:{PlayMode}");
// 编辑器下的模拟模式
if (PlayMode == YooAssets.EPlayMode.EditorSimulateMode)
{
var createParameters = new YooAssets.EditorSimulateModeParameters();
createParameters.LocationServices = new DefaultLocationServices("Assets/Samples/BasicSample/GameRes");
//createParameters.SimulatePatchManifestPath = GetPatchManifestPath();
yield return YooAssets.InitializeAsync(createParameters);
}
// 单机运行模式
if (PlayMode == YooAssets.EPlayMode.OfflinePlayMode)
{
var createParameters = new YooAssets.OfflinePlayModeParameters();
createParameters.LocationServices = new DefaultLocationServices("Assets/Samples/BasicSample/GameRes");
yield return YooAssets.InitializeAsync(createParameters);
}
// 联机运行模式
if (PlayMode == YooAssets.EPlayMode.HostPlayMode)
{
var createParameters = new YooAssets.HostPlayModeParameters();
createParameters.LocationServices = new DefaultLocationServices("Assets/Samples/BasicSample/GameRes");
createParameters.DecryptionServices = null;
createParameters.ClearCacheWhenDirty = false;
createParameters.DefaultHostServer = GetHostServerURL();
createParameters.FallbackHostServer = GetHostServerURL();
createParameters.VerifyLevel = EVerifyLevel.High;
yield return YooAssets.InitializeAsync(createParameters);
}
// 运行补丁流程
PatchUpdater.Run();
}
private string GetPatchManifestPath()
{
string directory = System.IO.Path.GetDirectoryName(Application.dataPath);
return $"{directory}/Bundles/StandaloneWindows64/UnityManifest_SimulateBuild/PatchManifest_100.bytes";
}
private string GetHostServerURL()
{
//string hostServerIP = "http://10.0.2.2"; //安卓模拟器地址
string hostServerIP = "http://127.0.0.1";
string gameVersion = "v1.0";
#if UNITY_EDITOR
if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.Android)
return $"{hostServerIP}/CDN/Android/{gameVersion}";
else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.iOS)
return $"{hostServerIP}/CDN/IPhone/{gameVersion}";
else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.WebGL)
return $"{hostServerIP}/CDN/WebGL/{gameVersion}";
else
return $"{hostServerIP}/CDN/PC/{gameVersion}";
#else
if (Application.platform == RuntimePlatform.Android)
return $"{hostServerIP}/CDN/Android/{gameVersion}";
else if (Application.platform == RuntimePlatform.IPhonePlayer)
return $"{hostServerIP}/CDN/IPhone/{gameVersion}";
else if (Application.platform == RuntimePlatform.WebGLPlayer)
return $"{hostServerIP}/CDN/WebGL/{gameVersion}";
else
return $"{hostServerIP}/CDN/PC/{gameVersion}";
#endif
}
}

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,66 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GUIConsole
{
private static Vector2 _scrollViewPos = Vector2.zero;
private static Texture _bgTexture;
private static bool _isInitConsole = false;
private static bool _visible = false;
private static readonly List<string> _logs = new List<string>(1000);
private static void InitConsole()
{
if (_isInitConsole)
return;
_isInitConsole = true;
// 监听日志
Application.logMessageReceived += HandleUnityEngineLog;
// 加载背景纹理
string textureName = "console_background";
_bgTexture = Resources.Load<Texture>(textureName);
if (_bgTexture == null)
UnityEngine.Debug.LogWarning($"Not found {textureName} texture in Resources folder.");
}
private static void HandleUnityEngineLog(string logString, string stackTrace, LogType type)
{
_logs.Add(logString);
if (_logs.Count > 1000)
{
_logs.RemoveAt(0);
}
}
public static void OnGUI()
{
InitConsole();
// 绘制背景
if (_visible && _bgTexture != null)
GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), _bgTexture, ScaleMode.StretchToFill, true);
GUILayout.BeginHorizontal();
string btnName = _visible ? "Hide" : "Show";
if (GUI.Button(new Rect(10, 0, 60, 30), btnName))
_visible = !_visible;
if (GUI.Button(new Rect(100, 0, 60, 30), "Clear"))
_logs.Clear();
GUILayout.EndHorizontal();
if (_visible == false)
return;
float scrollWidth = Screen.safeArea.width;
float scrollHeight = Screen.safeArea.height;
_scrollViewPos = GUILayout.BeginScrollView(_scrollViewPos, GUILayout.Width(scrollWidth), GUILayout.Height(scrollHeight));
for (int i = 0; i < _logs.Count; i++)
{
GUILayout.Label($"<size={18}><color=white>{_logs[i]}</color></size>");
}
GUILayout.EndScrollView();
}
}

View File

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

View File

@@ -0,0 +1,225 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.U2D;
using UnityEngine.UI;
using YooAsset;
public class Game1Scene : MonoBehaviour
{
public GameObject CanvasRoot;
private readonly List<AssetOperationHandle> _cachedAssetOperationHandles = new List<AssetOperationHandle>(1000);
private readonly List<SubAssetsOperationHandle> _cachedSubAssetsOperationHandles = new List<SubAssetsOperationHandle>(1000);
private int _npcIndex = 0;
void Start()
{
YooAssets.UnloadUnusedAssets();
// 初始化窗口
InitWindow();
// 异步加载背景音乐
AsyncLoadMusic();
}
void OnDestroy()
{
foreach (var handle in _cachedAssetOperationHandles)
{
handle.Release();
}
_cachedAssetOperationHandles.Clear();
foreach (var handle in _cachedSubAssetsOperationHandles)
{
handle.Release();
}
_cachedSubAssetsOperationHandles.Clear();
}
void OnGUI()
{
GUIConsole.OnGUI();
}
void InitWindow()
{
var resVersion = CanvasRoot.transform.Find("res_version/label").GetComponent<Text>();
resVersion.text = $"资源版本 : {YooAssets.GetResourceVersion()}";
var playMode = CanvasRoot.transform.Find("play_mode/label").GetComponent<Text>();
if (BootScene.GamePlayMode == YooAssets.EPlayMode.EditorSimulateMode)
playMode.text = "编辑器下模拟模式";
else if (BootScene.GamePlayMode == YooAssets.EPlayMode.OfflinePlayMode)
playMode.text = "离线运行模式";
else if (BootScene.GamePlayMode == YooAssets.EPlayMode.HostPlayMode)
playMode.text = "网络运行模式";
else
throw new NotImplementedException();
// 通过资源标签加载资源
{
string assetTag = "sphere";
AssetInfo[] assetInfos = YooAssets.GetAssetInfos(assetTag);
foreach (var assetInfo in assetInfos)
{
Debug.Log($"{assetInfo.AssetPath}");
}
}
// 同步加载背景图片
#if UNITY_WEBGL
{
var rawImage = CanvasRoot.transform.Find("background").GetComponent<RawImage>();
AssetOperationHandle handle = YooAssets.LoadAssetAsync<Texture>("Texture/bg");
_cachedAssetOperationHandles.Add(handle);
handle.Completed += (AssetOperationHandle obj) =>
{
rawImage.texture = handle.AssetObject as Texture;
};
}
#else
{
var rawImage = CanvasRoot.transform.Find("background").GetComponent<RawImage>();
AssetOperationHandle handle = YooAssets.LoadAssetSync<Texture>("Texture/bg");
_cachedAssetOperationHandles.Add(handle);
rawImage.texture = handle.AssetObject as Texture;
}
#endif
// 同步加载LOGO
#if UNITY_WEBGL
{
var logoImage = CanvasRoot.transform.Find("title/logo").GetComponent<Image>();
AssetOperationHandle handle = YooAssets.LoadAssetAsync<Sprite>("Texture/logo.png");
_cachedAssetOperationHandles.Add(handle);
handle.Completed += (AssetOperationHandle obj) =>
{
logoImage.sprite = handle.AssetObject as Sprite;
};
}
#else
{
var logoImage = CanvasRoot.transform.Find("title/logo").GetComponent<Image>();
AssetOperationHandle handle = YooAssets.LoadAssetSync<Sprite>("Texture/logo.png");
_cachedAssetOperationHandles.Add(handle);
logoImage.sprite = handle.AssetObject as Sprite;
}
#endif
// 同步加载预制体
{
string[] entityAssetNames =
{
"Level1/footman_Blue",
"Level2/footman_Green",
"Level3/footman_Red",
"Level3/footman_Yellow"
};
var btn = CanvasRoot.transform.Find("load_npc/btn").GetComponent<Button>();
btn.onClick.AddListener(() =>
{
#if UNITY_WEBGL
var icon = CanvasRoot.transform.Find("load_npc/icon").GetComponent<Image>();
AssetOperationHandle handle = YooAssets.LoadAssetAsync<GameObject>($"Entity/{entityAssetNames[_npcIndex]}");
_cachedAssetOperationHandles.Add(handle);
handle.Completed += (AssetOperationHandle op) =>
{
GameObject go = handle.InstantiateSync(icon.transform);
go.transform.localPosition = new Vector3(0, -50, -100);
go.transform.localRotation = Quaternion.EulerAngles(0, 180, 0);
go.transform.localScale = Vector3.one * 50;
};
#else
var icon = CanvasRoot.transform.Find("load_npc/icon").GetComponent<Image>();
AssetOperationHandle handle = YooAssets.LoadAssetSync<GameObject>($"Entity/{entityAssetNames[_npcIndex]}");
_cachedAssetOperationHandles.Add(handle);
GameObject go = handle.InstantiateSync(icon.transform);
go.transform.localPosition = new Vector3(0, -50, -100);
go.transform.localRotation = Quaternion.EulerAngles(0, 180, 0);
go.transform.localScale = Vector3.one * 50;
#endif
_npcIndex++;
if (_npcIndex > 3)
_npcIndex = 0;
});
}
// 异步加载UnityEngine生成的图集
{
var btn = CanvasRoot.transform.Find("load_unity_atlas/btn").GetComponent<Button>();
btn.onClick.AddListener(() =>
{
AssetOperationHandle handle = YooAssets.LoadAssetAsync<Sprite>("UISprite/Icon_Leafs_128");
_cachedAssetOperationHandles.Add(handle);
handle.Completed += OnUnityAtlas_Completed;
});
}
// 异步加载TexturePacker生成的图集
{
var btn = CanvasRoot.transform.Find("load_tp_atlas/btn").GetComponent<Button>();
btn.onClick.AddListener(() =>
{
SubAssetsOperationHandle handle = YooAssets.LoadSubAssetsAsync<Sprite>("TpAtlas/tpAtlas");
_cachedSubAssetsOperationHandles.Add(handle);
handle.Completed += OnTpAtlasAsset_Completed;
});
}
// 异步加载原生文件
{
var btn = CanvasRoot.transform.Find("load_rawfile/btn").GetComponent<Button>();
btn.onClick.AddListener(() =>
{
string savePath = $"{YooAssets.GetSandboxRoot()}/config1.txt";
RawFileOperation operation = YooAssets.GetRawFileAsync("Config/config1.txt", savePath);
operation.Completed += OnRawFile_Completed;
});
}
// 异步加载主场景
{
var btn = CanvasRoot.transform.Find("load_scene").GetComponent<Button>();
btn.onClick.AddListener(() =>
{
YooAssets.LoadSceneAsync("Scene/Game2.unity");
});
}
}
private void OnUnityAtlas_Completed(AssetOperationHandle handle)
{
var icon = CanvasRoot.transform.Find("load_unity_atlas/icon").GetComponent<Image>();
icon.sprite = handle.AssetObject as Sprite;
}
private void OnTpAtlasAsset_Completed(SubAssetsOperationHandle handle)
{
var icon = CanvasRoot.transform.Find("load_tp_atlas/icon").GetComponent<Image>();
icon.sprite = handle.GetSubAssetObject<Sprite>("Icon_Shield_128");
}
private void OnRawFile_Completed(AsyncOperationBase operation)
{
var hint = CanvasRoot.transform.Find("load_rawfile/icon/hint").GetComponent<Text>();
RawFileOperation op = operation as RawFileOperation;
hint.text = op.LoadFileText();
}
/// <summary>
/// 异步加载背景音乐
/// </summary>
async void AsyncLoadMusic()
{
// 加载背景音乐
{
var audioSource = CanvasRoot.transform.Find("music").GetComponent<AudioSource>();
AssetOperationHandle handle = YooAssets.LoadAssetAsync<AudioClip>("Music/town");
_cachedAssetOperationHandles.Add(handle);
await handle.Task;
audioSource.clip = handle.AssetObject as AudioClip;
audioSource.Play();
}
}
}

View File

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

View File

@@ -0,0 +1,107 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.U2D;
using UnityEngine.UI;
using YooAsset;
public class Game2Scene : MonoBehaviour
{
public GameObject CanvasRoot;
private readonly List<AssetOperationHandle> _cachedAssetOperationHandles = new List<AssetOperationHandle>(1000);
private SceneOperationHandle _subSceneHandle = null;
void Start()
{
YooAssets.UnloadUnusedAssets();
// 初始化窗口
InitWindow();
// 异步加载背景音乐
StartCoroutine(AsyncLoadMusic());
}
void OnDestroy()
{
foreach (var handle in _cachedAssetOperationHandles)
{
handle.Release();
}
_cachedAssetOperationHandles.Clear();
}
void OnGUI()
{
GUIConsole.OnGUI();
}
void InitWindow()
{
// 同步加载背景图片
#if UNITY_WEBGL
{
var rawImage = CanvasRoot.transform.Find("background").GetComponent<RawImage>();
AssetOperationHandle handle = YooAssets.LoadAssetAsync<Texture>("Texture/bg");
_cachedAssetOperationHandles.Add(handle);
handle.Completed += (AssetOperationHandle obj) =>
{
rawImage.texture = handle.AssetObject as Texture;
};
}
#else
{
var rawImage = CanvasRoot.transform.Find("background").GetComponent<RawImage>();
AssetOperationHandle handle = YooAssets.LoadAssetSync<Texture>("Texture/bg");
_cachedAssetOperationHandles.Add(handle);
rawImage.texture = handle.AssetObject as Texture;
}
#endif
// 异步加载主场景
{
var btn = CanvasRoot.transform.Find("load_scene").GetComponent<Button>();
btn.onClick.AddListener(() =>
{
YooAssets.LoadSceneAsync("Scene/Game1");
});
}
// 异步加载子场景
{
var btn = CanvasRoot.transform.Find("subSceneLoadBtn").GetComponent<Button>();
btn.onClick.AddListener(() =>
{
_subSceneHandle = YooAssets.LoadSceneAsync("Scene/SubScene", UnityEngine.SceneManagement.LoadSceneMode.Additive);
});
}
// 异步卸载子场景
{
var btn = CanvasRoot.transform.Find("subSceneUnloadBtn").GetComponent<Button>();
btn.onClick.AddListener(() =>
{
if(_subSceneHandle != null)
{
_subSceneHandle.UnloadAsync();
_subSceneHandle = null;
}
});
}
}
/// <summary>
/// 异步加载背景音乐
/// </summary>
IEnumerator AsyncLoadMusic()
{
// 加载背景音乐
{
var audioSource = CanvasRoot.transform.Find("music").GetComponent<AudioSource>();
AssetOperationHandle handle = YooAssets.LoadAssetAsync<AudioClip>("Music/town");
_cachedAssetOperationHandles.Add(handle);
yield return handle;
audioSource.clip = handle.AssetObject as AudioClip;
audioSource.Play();
}
}
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections;
using System.Collections.Generic;
public class EventGroup
{
private readonly Dictionary<System.Type, List<Action<IEventMessage>>> _cachedListener = new Dictionary<System.Type, List<Action<IEventMessage>>>();
/// <summary>
/// 添加一个监听
/// </summary>
public void AddListener<TEvent>(System.Action<IEventMessage> listener) where TEvent : IEventMessage
{
System.Type eventType = typeof(TEvent);
if (_cachedListener.ContainsKey(eventType) == false)
_cachedListener.Add(eventType, new List<Action<IEventMessage>>());
if (_cachedListener[eventType].Contains(listener) == false)
{
_cachedListener[eventType].Add(listener);
EventManager.AddListener(eventType, listener);
}
else
{
UnityEngine.Debug.LogWarning($"Event listener is exist : {eventType}");
}
}
/// <summary>
/// 移除所有缓存的监听
/// </summary>
public void RemoveAllListener()
{
foreach (var pair in _cachedListener)
{
System.Type eventType = pair.Key;
for (int i = 0; i < pair.Value.Count; i++)
{
EventManager.RemoveListener(eventType, pair.Value[i]);
}
pair.Value.Clear();
}
_cachedListener.Clear();
}
}

View File

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

View File

@@ -0,0 +1,171 @@
using System;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// 事件管理器
/// </summary>
public static class EventManager
{
private class PostWrapper
{
public int PostFrame;
public int EventID;
public IEventMessage Message;
public void OnRelease()
{
PostFrame = 0;
EventID = 0;
Message = null;
}
}
private static readonly Dictionary<int, List<Action<IEventMessage>>> _listeners = new Dictionary<int, List<Action<IEventMessage>>>(1000);
private static readonly List<PostWrapper> _postWrappers = new List<PostWrapper>(1000);
public static void Update()
{
for (int i = _postWrappers.Count - 1; i >= 0; i--)
{
var wrapper = _postWrappers[i];
if (UnityEngine.Time.frameCount > wrapper.PostFrame)
{
SendMessage(wrapper.EventID, wrapper.Message);
_postWrappers.RemoveAt(i);
}
}
}
/// <summary>
/// 添加监听
/// </summary>
public static void AddListener<TEvent>(System.Action<IEventMessage> listener) where TEvent : IEventMessage
{
AddListener(typeof(TEvent), listener);
}
/// <summary>
/// 添加监听
/// </summary>
public static void AddListener(System.Type eventType, System.Action<IEventMessage> listener)
{
int eventId = eventType.GetHashCode();
AddListener(eventId, listener);
}
/// <summary>
/// 添加监听
/// </summary>
public static void AddListener(int eventId, System.Action<IEventMessage> listener)
{
if (_listeners.ContainsKey(eventId) == false)
_listeners.Add(eventId, new List<Action<IEventMessage>>());
if (_listeners[eventId].Contains(listener) == false)
_listeners[eventId].Add(listener);
}
/// <summary>
/// 移除监听
/// </summary>
public static void RemoveListener<TEvent>(System.Action<IEventMessage> listener) where TEvent : IEventMessage
{
RemoveListener(typeof(TEvent), listener);
}
/// <summary>
/// 移除监听
/// </summary>
public static void RemoveListener(System.Type eventType, System.Action<IEventMessage> listener)
{
int eventId = eventType.GetHashCode();
RemoveListener(eventId, listener);
}
/// <summary>
/// 移除监听
/// </summary>
public static void RemoveListener(int eventId, System.Action<IEventMessage> listener)
{
if (_listeners.ContainsKey(eventId))
{
if (_listeners[eventId].Contains(listener))
_listeners[eventId].Remove(listener);
}
}
/// <summary>
/// 实时广播事件
/// </summary>
public static void SendMessage(IEventMessage message)
{
int eventId = message.GetType().GetHashCode();
SendMessage(eventId, message);
}
/// <summary>
/// 实时广播事件
/// </summary>
public static void SendMessage(int eventId, IEventMessage message)
{
if (_listeners.ContainsKey(eventId) == false)
return;
List<Action<IEventMessage>> listeners = _listeners[eventId];
for (int i = listeners.Count - 1; i >= 0; i--)
{
listeners[i].Invoke(message);
}
}
/// <summary>
/// 延迟广播事件
/// </summary>
public static void PostMessage(IEventMessage message)
{
int eventId = message.GetType().GetHashCode();
PostMessage(eventId, message);
}
/// <summary>
/// 延迟广播事件
/// </summary>
public static void PostMessage(int eventId, IEventMessage message)
{
var wrapper = new PostWrapper();
wrapper.PostFrame = UnityEngine.Time.frameCount;
wrapper.EventID = eventId;
wrapper.Message = message;
_postWrappers.Add(wrapper);
}
/// <summary>
/// 清空所有监听
/// </summary>
public static void ClearListeners()
{
foreach (int eventId in _listeners.Keys)
{
_listeners[eventId].Clear();
}
_listeners.Clear();
}
/// <summary>
/// 获取监听者总数
/// </summary>
private static int GetAllListenerCount()
{
int count = 0;
foreach (var list in _listeners)
{
count += list.Value.Count;
}
return count;
}
}

View File

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

View File

@@ -0,0 +1,4 @@

public interface IEventMessage
{
}

View File

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

View File

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

View File

@@ -0,0 +1,121 @@
using System;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// 有限状态机
/// </summary>
public static class FsmManager
{
private static readonly List<IFsmNode> _nodes = new List<IFsmNode>();
private static IFsmNode _curNode;
private static IFsmNode _preNode;
/// <summary>
/// 当前运行的节点名称
/// </summary>
public static string CurrentNodeName
{
get { return _curNode != null ? _curNode.Name : string.Empty; }
}
/// <summary>
/// 之前运行的节点名称
/// </summary>
public static string PreviousNodeName
{
get { return _preNode != null ? _preNode.Name : string.Empty; }
}
/// <summary>
/// 启动状态机
/// </summary>
/// <param name="entryNode">入口节点</param>
public static void Run(string entryNode)
{
_curNode = GetNode(entryNode);
_preNode = GetNode(entryNode);
if (_curNode != null)
_curNode.OnEnter();
else
UnityEngine.Debug.LogError($"Not found entry node : {entryNode}");
}
/// <summary>
/// 更新状态机
/// </summary>
public static void Update()
{
if (_curNode != null)
_curNode.OnUpdate();
}
/// <summary>
/// 加入一个节点
/// </summary>
public static void AddNode(IFsmNode node)
{
if (node == null)
throw new ArgumentNullException();
if (_nodes.Contains(node) == false)
{
_nodes.Add(node);
}
else
{
UnityEngine.Debug.LogWarning($"Node {node.Name} already existed");
}
}
/// <summary>
/// 转换节点
/// </summary>
public static void Transition(string nodeName)
{
if (string.IsNullOrEmpty(nodeName))
throw new ArgumentNullException();
IFsmNode node = GetNode(nodeName);
if (node == null)
{
UnityEngine.Debug.LogError($"Can not found node {nodeName}");
return;
}
UnityEngine.Debug.Log($"FSM change {_curNode.Name} to {node.Name}");
_preNode = _curNode;
_curNode.OnExit();
_curNode = node;
_curNode.OnEnter();
}
/// <summary>
/// 返回到之前的节点
/// </summary>
public static void RevertToPreviousNode()
{
Transition(PreviousNodeName);
}
private static bool IsContains(string nodeName)
{
for (int i = 0; i < _nodes.Count; i++)
{
if (_nodes[i].Name == nodeName)
return true;
}
return false;
}
private static IFsmNode GetNode(string nodeName)
{
for (int i = 0; i < _nodes.Count; i++)
{
if (_nodes[i].Name == nodeName)
return _nodes[i];
}
return null;
}
}

View File

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

View File

@@ -0,0 +1,12 @@

public interface IFsmNode
{
/// <summary>
/// 节点名称
/// </summary>
string Name { get; }
void OnEnter();
void OnUpdate();
void OnExit();
}

View File

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

View File

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

View File

@@ -0,0 +1,26 @@

/// <summary>
/// 用户层反馈的操作方式
/// </summary>
public enum EPatchOperation
{
/// <summary>
/// 开始下载网络文件
/// </summary>
BeginDownloadWebFiles,
/// <summary>
/// 尝试再次更新静态版本
/// </summary>
TryUpdateStaticVersion,
/// <summary>
/// 尝试再次更新补丁清单
/// </summary>
TryUpdatePatchManifest,
/// <summary>
/// 尝试再次下载网络文件
/// </summary>
TryDownloadWebFiles,
}

View File

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

View File

@@ -0,0 +1,31 @@

/// <summary>
/// 补丁系统更新状态
/// </summary>
public enum EPatchStates
{
/// <summary>
/// 更新静态的资源版本
/// </summary>
UpdateStaticVersion,
/// <summary>
/// 更新补丁清单
/// </summary>
UpdateManifest,
/// <summary>
/// 创建下载器
/// </summary>
CreateDownloader,
/// <summary>
/// 下载远端文件
/// </summary>
DownloadWebFiles,
/// <summary>
/// 补丁流程完毕
/// </summary>
PatchDone,
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6f1f35b77d2285045b35f588be8f7236
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
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,46 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
public class FsmCreateDownloader : IFsmNode
{
public string Name { private set; get; } = nameof(FsmCreateDownloader);
void IFsmNode.OnEnter()
{
PatchEventDispatcher.SendPatchStepsChangeMsg(EPatchStates.CreateDownloader);
BootScene.Instance.StartCoroutine(CreateDownloader());
}
void IFsmNode.OnUpdate()
{
}
void IFsmNode.OnExit()
{
}
IEnumerator CreateDownloader()
{
yield return new WaitForSecondsRealtime(0.5f);
Debug.Log("创建补丁下载器.");
int downloadingMaxNum = 10;
int failedTryAgain = 3;
PatchUpdater.Downloader = YooAssets.CreatePatchDownloader(downloadingMaxNum, failedTryAgain);
if (PatchUpdater.Downloader.TotalDownloadCount == 0)
{
Debug.Log("没有发现需要下载的资源");
FsmManager.Transition(nameof(FsmPatchDone));
}
else
{
Debug.Log($"一共发现了{PatchUpdater.Downloader.TotalDownloadCount}个资源需要更新下载。");
// 发现新更新文件后,挂起流程系统
// 注意:开发者需要在下载前检测磁盘空间不足
int totalDownloadCount = PatchUpdater.Downloader.TotalDownloadCount;
long totalDownloadBytes = PatchUpdater.Downloader.TotalDownloadBytes;
PatchEventDispatcher.SendFoundUpdateFilesMsg(totalDownloadCount, totalDownloadBytes);
}
}
}

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,36 @@
using System.Collections;
using YooAsset;
public class FsmDownloadWebFiles : IFsmNode
{
public string Name { private set; get; } = nameof(FsmDownloadWebFiles);
void IFsmNode.OnEnter()
{
PatchEventDispatcher.SendPatchStepsChangeMsg(EPatchStates.DownloadWebFiles);
BootScene.Instance.StartCoroutine(BeginDownload());
}
void IFsmNode.OnUpdate()
{
}
void IFsmNode.OnExit()
{
}
private IEnumerator BeginDownload()
{
var downloader = PatchUpdater.Downloader;
// 注册下载回调
downloader.OnDownloadErrorCallback = PatchEventDispatcher.SendWebFileDownloadFailedMsg;
downloader.OnDownloadProgressCallback = PatchEventDispatcher.SendDownloadProgressUpdateMsg;
downloader.BeginDownload();
yield return downloader;
// 检测下载结果
if (downloader.Status != EOperationStatus.Succeed)
yield break;
FsmManager.Transition(nameof(FsmPatchDone));
}
}

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,22 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
internal class FsmPatchDone : IFsmNode
{
public string Name { private set; get; } = nameof(FsmPatchDone);
void IFsmNode.OnEnter()
{
PatchEventDispatcher.SendPatchStepsChangeMsg(EPatchStates.PatchDone);
Debug.Log("补丁流程更新完毕!");
YooAsset.YooAssets.LoadSceneAsync("Scene/Game1");
}
void IFsmNode.OnUpdate()
{
}
void IFsmNode.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,30 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
internal class FsmPatchInit : IFsmNode
{
public string Name { private set; get; } = nameof(FsmPatchInit);
void IFsmNode.OnEnter()
{
// 加载更新面板
var go = Resources.Load<GameObject>("PatchWindow");
GameObject.Instantiate(go);
BootScene.Instance.StartCoroutine(Begin());
}
void IFsmNode.OnUpdate()
{
}
void IFsmNode.OnExit()
{
}
private IEnumerator Begin()
{
yield return new WaitForSecondsRealtime(0.5f);
FsmManager.Transition(nameof(FsmUpdateStaticVersion));
}
}

View File

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

View File

@@ -0,0 +1,40 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
public class FsmUpdateManifest : IFsmNode
{
public string Name { private set; get; } = nameof(FsmUpdateManifest);
void IFsmNode.OnEnter()
{
PatchEventDispatcher.SendPatchStepsChangeMsg(EPatchStates.UpdateManifest);
BootScene.Instance.StartCoroutine(UpdateManifest());
}
void IFsmNode.OnUpdate()
{
}
void IFsmNode.OnExit()
{
}
private IEnumerator UpdateManifest()
{
yield return new WaitForSecondsRealtime(0.5f);
// 更新补丁清单
var operation = YooAssets.UpdateManifestAsync(PatchUpdater.ResourceVersion, 30);
yield return operation;
if(operation.Status == EOperationStatus.Succeed)
{
FsmManager.Transition(nameof(FsmCreateDownloader));
}
else
{
Debug.LogWarning(operation.Error);
PatchEventDispatcher.SendPatchManifestUpdateFailedMsg();
}
}
}

View File

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

View File

@@ -0,0 +1,42 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
internal class FsmUpdateStaticVersion : IFsmNode
{
public string Name { private set; get; } = nameof(FsmUpdateStaticVersion);
void IFsmNode.OnEnter()
{
PatchEventDispatcher.SendPatchStepsChangeMsg(EPatchStates.UpdateStaticVersion);
BootScene.Instance.StartCoroutine(GetStaticVersion());
}
void IFsmNode.OnUpdate()
{
}
void IFsmNode.OnExit()
{
}
private IEnumerator GetStaticVersion()
{
yield return new WaitForSecondsRealtime(0.5f);
// 更新资源版本号
var operation = YooAssets.UpdateStaticVersionAsync(30);
yield return operation;
if (operation.Status == EOperationStatus.Succeed)
{
Debug.Log($"Found static version : {operation.ResourceVersion}");
PatchUpdater.ResourceVersion = operation.ResourceVersion;
FsmManager.Transition(nameof(FsmUpdateManifest));
}
else
{
Debug.LogWarning(operation.Error);
PatchEventDispatcher.SendStaticVersionUpdateFailedMsg();
}
}
}

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,43 @@

public static class PatchEventDispatcher
{
public static void SendPatchStepsChangeMsg(EPatchStates currentStates)
{
PatchEventMessageDefine.PatchStatesChange msg = new PatchEventMessageDefine.PatchStatesChange();
msg.CurrentStates = currentStates;
EventManager.SendMessage(msg);
}
public static void SendFoundUpdateFilesMsg(int totalCount, long totalSizeBytes)
{
PatchEventMessageDefine.FoundUpdateFiles msg = new PatchEventMessageDefine.FoundUpdateFiles();
msg.TotalCount = totalCount;
msg.TotalSizeBytes = totalSizeBytes;
EventManager.SendMessage(msg);
}
public static void SendDownloadProgressUpdateMsg(int totalDownloadCount, int currentDownloadCount, long totalDownloadSizeBytes, long currentDownloadSizeBytes)
{
PatchEventMessageDefine.DownloadProgressUpdate msg = new PatchEventMessageDefine.DownloadProgressUpdate();
msg.TotalDownloadCount = totalDownloadCount;
msg.CurrentDownloadCount = currentDownloadCount;
msg.TotalDownloadSizeBytes = totalDownloadSizeBytes;
msg.CurrentDownloadSizeBytes = currentDownloadSizeBytes;
EventManager.SendMessage(msg);
}
public static void SendStaticVersionUpdateFailedMsg()
{
PatchEventMessageDefine.StaticVersionUpdateFailed msg = new PatchEventMessageDefine.StaticVersionUpdateFailed();
EventManager.SendMessage(msg);
}
public static void SendPatchManifestUpdateFailedMsg()
{
PatchEventMessageDefine.PatchManifestUpdateFailed msg = new PatchEventMessageDefine.PatchManifestUpdateFailed();
EventManager.SendMessage(msg);
}
public static void SendWebFileDownloadFailedMsg(string fileName, string error)
{
PatchEventMessageDefine.WebFileDownloadFailed msg = new PatchEventMessageDefine.WebFileDownloadFailed();
msg.FileName = fileName;
msg.Error = error;
EventManager.SendMessage(msg);
}
}

View File

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

View File

@@ -0,0 +1,54 @@

public class PatchEventMessageDefine
{
/// <summary>
/// 补丁流程步骤改变
/// </summary>
public class PatchStatesChange : IEventMessage
{
public EPatchStates CurrentStates;
}
/// <summary>
/// 发现更新文件
/// </summary>
public class FoundUpdateFiles : IEventMessage
{
public int TotalCount;
public long TotalSizeBytes;
}
/// <summary>
/// 下载进度更新
/// </summary>
public class DownloadProgressUpdate : IEventMessage
{
public int TotalDownloadCount;
public int CurrentDownloadCount;
public long TotalDownloadSizeBytes;
public long CurrentDownloadSizeBytes;
}
/// <summary>
/// 资源版本号更新失败
/// </summary>
public class StaticVersionUpdateFailed : IEventMessage
{
}
/// <summary>
/// 补丁清单更新失败
/// </summary>
public class PatchManifestUpdateFailed : IEventMessage
{
}
/// <summary>
/// 网络文件下载失败
/// </summary>
public class WebFileDownloadFailed : IEventMessage
{
public string FileName;
public string Error;
}
}

View File

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

View File

@@ -0,0 +1,73 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
public static class PatchUpdater
{
private static bool _isRun = false;
/// <summary>
/// 下载器
/// </summary>
public static PatchDownloaderOperation Downloader { set; get; }
/// <summary>
/// 资源版本
/// </summary>
public static int ResourceVersion { set; get; }
/// <summary>
/// 开启初始化流程
/// </summary>
public static void Run()
{
if (_isRun == false)
{
_isRun = true;
Debug.Log("开始补丁更新...");
// 注意:按照先后顺序添加流程节点
FsmManager.AddNode(new FsmPatchInit());
FsmManager.AddNode(new FsmUpdateStaticVersion());
FsmManager.AddNode(new FsmUpdateManifest());
FsmManager.AddNode(new FsmCreateDownloader());
FsmManager.AddNode(new FsmDownloadWebFiles());
FsmManager.AddNode(new FsmPatchDone());
FsmManager.Run(nameof(FsmPatchInit));
}
else
{
Debug.LogWarning("补丁更新已经正在进行中!");
}
}
/// <summary>
/// 处理请求操作
/// </summary>
public static void HandleOperation(EPatchOperation operation)
{
if (operation == EPatchOperation.BeginDownloadWebFiles)
{
FsmManager.Transition(nameof(FsmDownloadWebFiles));
}
else if(operation == EPatchOperation.TryUpdateStaticVersion)
{
FsmManager.Transition(nameof(FsmUpdateStaticVersion));
}
else if (operation == EPatchOperation.TryUpdatePatchManifest)
{
FsmManager.Transition(nameof(FsmUpdateManifest));
}
else if (operation == EPatchOperation.TryDownloadWebFiles)
{
FsmManager.Transition(nameof(FsmCreateDownloader));
}
else
{
throw new NotImplementedException($"{operation}");
}
}
}

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,185 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PatchWindow : MonoBehaviour
{
/// <summary>
/// 对话框封装类
/// </summary>
private class MessageBox
{
private GameObject _cloneObject;
private Text _content;
private Button _btnOK;
private System.Action _clickOK;
public bool ActiveSelf
{
get
{
return _cloneObject.activeSelf;
}
}
public void Create(GameObject cloneObject)
{
_cloneObject = cloneObject;
_content = cloneObject.transform.Find("txt_content").GetComponent<Text>();
_btnOK = cloneObject.transform.Find("btn_ok").GetComponent<Button>();
_btnOK.onClick.AddListener(OnClickYes);
}
public void Show(string content, System.Action clickOK)
{
_content.text = content;
_clickOK = clickOK;
_cloneObject.SetActive(true);
_cloneObject.transform.SetAsLastSibling();
}
public void Hide()
{
_content.text = string.Empty;
_clickOK = null;
_cloneObject.SetActive(false);
}
private void OnClickYes()
{
_clickOK?.Invoke();
Hide();
}
}
private readonly EventGroup _eventGroup = new EventGroup();
private readonly List<MessageBox> _msgBoxList = new List<MessageBox>();
// UGUI相关
private GameObject _messageBoxObj;
private Slider _slider;
private Text _tips;
void Awake()
{
_slider = transform.Find("UIWindow/Slider").GetComponent<Slider>();
_tips = transform.Find("UIWindow/Slider/txt_tips").GetComponent<Text>();
_tips.text = "Initializing the game world !";
_messageBoxObj = transform.Find("UIWindow/MessgeBox").gameObject;
_messageBoxObj.SetActive(false);
_eventGroup.AddListener<PatchEventMessageDefine.PatchStatesChange>(OnHandleEvent);
_eventGroup.AddListener<PatchEventMessageDefine.FoundUpdateFiles>(OnHandleEvent);
_eventGroup.AddListener<PatchEventMessageDefine.DownloadProgressUpdate>(OnHandleEvent);
_eventGroup.AddListener<PatchEventMessageDefine.StaticVersionUpdateFailed>(OnHandleEvent);
_eventGroup.AddListener<PatchEventMessageDefine.PatchManifestUpdateFailed>(OnHandleEvent);
_eventGroup.AddListener<PatchEventMessageDefine.WebFileDownloadFailed>(OnHandleEvent);
}
void OnDestroy()
{
_eventGroup.RemoveAllListener();
}
/// <summary>
/// 接收事件
/// </summary>
private void OnHandleEvent(IEventMessage msg)
{
if (msg is PatchEventMessageDefine.PatchStatesChange)
{
var message = msg as PatchEventMessageDefine.PatchStatesChange;
if (message.CurrentStates == EPatchStates.UpdateStaticVersion)
_tips.text = "Update static version.";
else if (message.CurrentStates == EPatchStates.UpdateManifest)
_tips.text = "Update patch manifest.";
else if (message.CurrentStates == EPatchStates.CreateDownloader)
_tips.text = "Check download contents.";
else if (message.CurrentStates == EPatchStates.DownloadWebFiles)
_tips.text = "Downloading patch files.";
else if (message.CurrentStates == EPatchStates.PatchDone)
_tips.text = "Welcome to game world !";
else
throw new NotImplementedException(message.CurrentStates.ToString());
}
else if (msg is PatchEventMessageDefine.FoundUpdateFiles)
{
var message = msg as PatchEventMessageDefine.FoundUpdateFiles;
System.Action callback = () =>
{
PatchUpdater.HandleOperation(EPatchOperation.BeginDownloadWebFiles);
};
float sizeMB = message.TotalSizeBytes / 1048576f;
sizeMB = Mathf.Clamp(sizeMB, 0.1f, float.MaxValue);
string totalSizeMB = sizeMB.ToString("f1");
ShowMessageBox($"Found update patch files, Total count {message.TotalCount} Total szie {totalSizeMB}MB", callback);
}
else if (msg is PatchEventMessageDefine.DownloadProgressUpdate)
{
var message = msg as PatchEventMessageDefine.DownloadProgressUpdate;
_slider.value = (float)message.CurrentDownloadCount / message.TotalDownloadCount;
string currentSizeMB = (message.CurrentDownloadSizeBytes / 1048576f).ToString("f1");
string totalSizeMB = (message.TotalDownloadSizeBytes / 1048576f).ToString("f1");
_tips.text = $"{message.CurrentDownloadCount}/{message.TotalDownloadCount} {currentSizeMB}MB/{totalSizeMB}MB";
}
else if (msg is PatchEventMessageDefine.StaticVersionUpdateFailed)
{
System.Action callback = () =>
{
PatchUpdater.HandleOperation(EPatchOperation.TryUpdateStaticVersion);
};
ShowMessageBox($"Failed to update static version, please check the network status.", callback);
}
else if (msg is PatchEventMessageDefine.PatchManifestUpdateFailed)
{
System.Action callback = () =>
{
PatchUpdater.HandleOperation(EPatchOperation.TryUpdatePatchManifest);
};
ShowMessageBox($"Failed to update patch manifest, please check the network status.", callback);
}
else if (msg is PatchEventMessageDefine.WebFileDownloadFailed)
{
var message = msg as PatchEventMessageDefine.WebFileDownloadFailed;
System.Action callback = () =>
{
PatchUpdater.HandleOperation(EPatchOperation.TryDownloadWebFiles);
};
ShowMessageBox($"Failed to download file : {message.FileName}", callback);
}
else
{
throw new System.NotImplementedException($"{msg.GetType()}");
}
}
/// <summary>
/// 显示对话框
/// </summary>
private void ShowMessageBox(string content, System.Action ok)
{
// 尝试获取一个可用的对话框
MessageBox msgBox = null;
for (int i = 0; i < _msgBoxList.Count; i++)
{
var item = _msgBoxList[i];
if (item.ActiveSelf == false)
{
msgBox = item;
break;
}
}
// 如果没有可用的对话框,则创建一个新的对话框
if (msgBox == null)
{
msgBox = new MessageBox();
var cloneObject = GameObject.Instantiate(_messageBoxObj, _messageBoxObj.transform.parent);
msgBox.Create(cloneObject);
_msgBoxList.Add(msgBox);
}
// 显示对话框
msgBox.Show(content, ok);
}
}

View File

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