报错修改

This commit is contained in:
2025-07-02 10:05:26 +08:00
parent c2bf9196b8
commit ec8b2f7e25
405 changed files with 16738 additions and 1883 deletions
@@ -1,163 +0,0 @@
using System.IO;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
namespace YooAsset.Editor
{
public class PackageComparatorWindow : EditorWindow
{
static PackageComparatorWindow _thisInstance;
[MenuItem("Evo/YooAsset/补丁包比对工具", false, 102)]
static void ShowWindow()
{
if (_thisInstance == null)
{
_thisInstance = EditorWindow.GetWindow(typeof(PackageComparatorWindow), false, "补丁包比对工具", true) as PackageComparatorWindow;
_thisInstance.minSize = new Vector2(800, 600);
}
_thisInstance.Show();
}
private string _manifestPath1 = string.Empty;
private string _manifestPath2 = string.Empty;
private readonly List<PackageBundle> _changeList = new List<PackageBundle>();
private readonly List<PackageBundle> _newList = new List<PackageBundle>();
private readonly List<PackageBundle> _deleteList = new List<PackageBundle>();
private Vector2 _scrollPos1;
private Vector2 _scrollPos2;
private Vector2 _scrollPos3;
private void OnGUI()
{
GUILayout.Space(10);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("选择补丁包1", GUILayout.MaxWidth(150)))
{
string resultPath = EditorUtility.OpenFilePanel("Find", "Assets/", "bytes");
if (string.IsNullOrEmpty(resultPath))
return;
_manifestPath1 = resultPath;
}
EditorGUILayout.LabelField(_manifestPath1);
EditorGUILayout.EndHorizontal();
GUILayout.Space(10);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("选择补丁包2", GUILayout.MaxWidth(150)))
{
string resultPath = EditorUtility.OpenFilePanel("Find", "Assets/", "bytes");
if (string.IsNullOrEmpty(resultPath))
return;
_manifestPath2 = resultPath;
}
EditorGUILayout.LabelField(_manifestPath2);
EditorGUILayout.EndHorizontal();
if (string.IsNullOrEmpty(_manifestPath1) == false && string.IsNullOrEmpty(_manifestPath2) == false)
{
if (GUILayout.Button("比对差异", GUILayout.MaxWidth(150)))
{
ComparePackage(_changeList, _newList);
}
}
EditorGUILayout.Space();
using (new EditorGUI.DisabledScope(false))
{
int totalCount = _changeList.Count;
EditorGUILayout.Foldout(true, $"差异列表 ( {totalCount} )");
EditorGUI.indentLevel = 1;
_scrollPos1 = EditorGUILayout.BeginScrollView(_scrollPos1);
{
foreach (var bundle in _changeList)
{
EditorGUILayout.LabelField($"{bundle.BundleName} | {(bundle.FileSize / 1024)}K");
}
}
EditorGUILayout.EndScrollView();
EditorGUI.indentLevel = 0;
}
EditorGUILayout.Space();
using (new EditorGUI.DisabledScope(false))
{
int totalCount = _newList.Count;
EditorGUILayout.Foldout(true, $"新增列表 ( {totalCount} )");
EditorGUI.indentLevel = 1;
_scrollPos2 = EditorGUILayout.BeginScrollView(_scrollPos2);
{
foreach (var bundle in _newList)
{
EditorGUILayout.LabelField($"{bundle.BundleName}");
}
}
EditorGUILayout.EndScrollView();
EditorGUI.indentLevel = 0;
}
EditorGUILayout.Space();
using (new EditorGUI.DisabledScope(false))
{
int totalCount = _deleteList.Count;
EditorGUILayout.Foldout(true, $"删除列表 ( {totalCount} )");
EditorGUI.indentLevel = 1;
_scrollPos3 = EditorGUILayout.BeginScrollView(_scrollPos3);
{
foreach (var bundle in _deleteList)
{
EditorGUILayout.LabelField($"{bundle.BundleName}");
}
}
EditorGUILayout.EndScrollView();
EditorGUI.indentLevel = 0;
}
}
private void ComparePackage(List<PackageBundle> changeList, List<PackageBundle> newList)
{
changeList.Clear();
newList.Clear();
// 加载补丁清单1
byte[] bytesData1 = FileUtility.ReadAllBytes(_manifestPath1);
PackageManifest manifest1 = ManifestTools.DeserializeFromBinary(bytesData1);
// 加载补丁清单1
byte[] bytesData2 = FileUtility.ReadAllBytes(_manifestPath2);
PackageManifest manifest2 = ManifestTools.DeserializeFromBinary(bytesData2);
// 拷贝文件列表
foreach (var bundle2 in manifest2.BundleList)
{
if (manifest1.TryGetPackageBundleByBundleName(bundle2.BundleName, out PackageBundle bundle1))
{
if (bundle2.FileHash != bundle1.FileHash)
{
changeList.Add(bundle2);
}
else
{
//检测是否新增
}
}
else
{
newList.Add(bundle2);
}
}
// 按字母重新排序
changeList.Sort((x, y) => string.Compare(x.BundleName, y.BundleName));
newList.Sort((x, y) => string.Compare(x.BundleName, y.BundleName));
Debug.Log("资源包差异比对完成!");
}
}
}
@@ -26,6 +26,7 @@ namespace Stary.Evo
public virtual void OnEnter(string param)
{
TransformInfo = transform.Find("TransformInfo");
}
/// <summary>
@@ -36,8 +37,7 @@ namespace Stary.Evo
{
isExit = true;
AudioCoreManager.StopMusic();
MainArchitecture.Interface.GetSystem<IVideoSystem>().StopVideo();
MainArchitecture.Interface.GetSystem<IDigitalHuman>().KillTalkState();
}
@@ -47,19 +47,14 @@ namespace Stary.Evo
isExit = true;
}
public virtual async Task OnExitAsync()
public virtual Task OnExitAsync()
{
await ForceUnloadAllAssets();
return Task.CompletedTask;
}
private async void OnDestroy()
{
// if (!isExit)
// {
// OnExit();
// await OnExitAsync();
// }
await ForceUnloadAllAssets();
}
// 强制卸载所有资源包,该方法请在合适的时机调用。
@@ -1,10 +1,12 @@
namespace Stary.Evo
using Main;
namespace Stary.Evo
{
public class FsmLoadSystem : FsmSystem , IFsmSystem
{
private OpenDomainType OpenDomainType { get; set; }
public ProgressBarPanel ProgressBarPanel { get; set; }
public void SetOpenDomainType(OpenDomainType type)
{
this.OpenDomainType = type;
@@ -42,7 +42,7 @@ namespace Stary.Evo
#if EDITOR_SIMULATEMODE
// Editor下无需加载,直接查找获得HotUpdate程序集
Assembly hotUpdateAss = System.AppDomain.CurrentDomain.GetAssemblies()
.First(a => a.GetName().Name == $"HotUpdate_{AppConfig.ASSETPACKGENAME}");
.First(a => a.GetName().Name == $"HotUpdate_{AppConfig.PackageDomainName}");
#else
string hotUpdateAssemblyName = $"HotUpdate_{AppConfig.PackageDomainName}";
@@ -91,6 +91,7 @@ namespace Stary.Evo
Debug.Log($"UnityEvo:dll:加载成功!!");
var hotfixPdbAsset = hotfixPdb.AssetObject as TextAsset;
hotUpdateAss = Assembly.Load(hotfixDllAsset.bytes, hotfixPdbAsset.bytes);
Debug.Log($"UnityEvo:dll: Assembly.Load加载成功!!");
}
else
{
@@ -105,6 +106,7 @@ namespace Stary.Evo
#endif
Debug.Log($"UnityEvo:dll: Assembly.Load加载后是否为空:{hotUpdateAss == null}");
if (hotUpdateAss != null)
{
@@ -119,16 +121,16 @@ namespace Stary.Evo
}
// 添加方法存在性检查
Debug.Log($"UnityEvo:dll:开始MethodInfo检查!!");
MethodInfo onEnterMethod = type.GetMethod("OnEnter");
MethodInfo onEnterAsyncMethod = type.GetMethod("OnEnterAsync");
if (onEnterMethod == null || onEnterAsyncMethod == null)
{
Debug.LogError($"UnityEvo:热更类进入方法缺失!\n" +
$"存在方法:{string.Join(", ", type.GetMethods().Select(m => m.Name))}");
return;
}
Debug.Log($"UnityEvo:dll:OnEnter检查成功!!");
MethodInfo onExitMethod = type.GetMethod("OnExit");
MethodInfo onExitAsyncMethod = type.GetMethod("OnExitAsync");
if (onExitMethod == null || onExitAsyncMethod == null)
@@ -137,7 +139,7 @@ namespace Stary.Evo
$"存在方法:{string.Join(", ", type.GetMethods().Select(m => m.Name))}");
return;
}
Debug.Log($"UnityEvo:dll:Type检查成功!!");
Debug.Log($"UnityEvo:dll:OnExit检查成功!!");
// AppConfig.SetDefaultHotfixType(type);
FsmSystem.SetCurState(nameof(LoadResState), domainConfig, type);
// // 创建热更类实例
@@ -0,0 +1,88 @@
using Cysharp.Threading.Tasks;
using Main;
using UnityEngine;
using YooAsset;
namespace Stary.Evo
{
public class LoadResMainState : AbstractFSMIState
{
private string _doMain = "Main";
public LoadResMainState(IFsmSystem system) : base(system)
{
}
public override async UniTask OnEnterAsync()
{
// Debug.Log("加载资源...");
// var package = YooAssets.GetPackage(_doMain);
//
// DomainConfig config = null;
// //加载热更配置文件
// var loadHotfixSettingsOp = package.LoadAssetAsync<DomainConfig>("Config_DomainConfig");
// await loadHotfixSettingsOp;
// if (loadHotfixSettingsOp.Status == EOperationStatus.Succeed)
// {
// //更新成功
// Debug.Log($"UnityEvo:加载主配置文件 loadHotfixSettings : 【成功】");
// config = loadHotfixSettingsOp.AssetObject as DomainConfig;
// }
// else
// {
// Debug.LogError($"UnityEvo:加载主配置文件 loadHotfixSettings : 【失败】");
// }
//
// // 加载热更资源
// var loadOperation = package.LoadAssetAsync<GameObject>(config.mainPrefab);
//
// await loadOperation;
// if (loadOperation.Status == EOperationStatus.Succeed)
// {
// GameObject loadhotfix = loadOperation.InstantiateSync();
// AppConfig.SetDefaultMainInstance(loadhotfix);
// if (loadhotfix != null)
// {
// DomainBase hotfixInstance = loadhotfix.GetComponent<MainDomain>();
// if (hotfixInstance == null)
// {
// hotfixInstance = loadhotfix.AddComponent<MainDomain>();
// }
//
// if (hotfixInstance == null)
// {
// Debug.LogError($"热更类{loadhotfix.name}实例创建失败!必须继承MonoBehaviour");
// return;
// }
//
//
// // 原有调用逻辑修改为使用实例
// hotfixInstance.OnEnter("");
// hotfixInstance.OnEnterAsync("");
// }
// }
}
public override UniTask OnEnterAsync<T>(T param)
{
return UniTask.CompletedTask;
}
public override UniTask OnEnterAsync<T1, T2>(T1 param1, T2 param2)
{
return UniTask.CompletedTask;
}
public override void OnUpdate()
{
base.OnUpdate();
}
public override UniTask OnExitAsync()
{
return UniTask.CompletedTask;
}
}
}
@@ -0,0 +1,144 @@
using System;
using Cysharp.Threading.Tasks;
using Immersal.AR;
using Stary.Evo;
using Stary.Evo.InformationSave;
using UnityEngine;
using UnityEngine.SceneManagement;
using YooAsset;
namespace Stary.Evo
{
public class LoadResState : AbstractFSMIState
{
private DomainConfig.LoadResType loadResType;
public GameObject mainPrefab;
private DomainConfig domainConfig;
public LoadResState(IFsmSystem system) : base(system)
{
}
public override UniTask OnEnterAsync()
{
return UniTask.CompletedTask;
}
public override UniTask OnEnterAsync<T>(T param)
{
return UniTask.CompletedTask;
}
public override async UniTask OnEnterAsync<T1, T2>(T1 param1, T2 param2)
{
Debug.Log("加载资源...");
domainConfig = param1 as DomainConfig;
loadResType = domainConfig.loadResType;
Type type = param2 as Type;
var package = YooAssets.GetPackage(domainConfig.domain);
if (loadResType == DomainConfig.LoadResType.Prefab)
{
// 加载热更资源
var loadOperation = package.LoadAssetAsync<GameObject>(domainConfig.mainPrefab);
await loadOperation;
if (loadOperation.Status == EOperationStatus.Succeed)
{
ARSpace arSpace = GameObject.FindObjectOfType<ARSpace>();
if (arSpace != null)
{
Debug.Log("UnityEvo:找到ARSpace,开始加载点云运行环境...");
mainPrefab = loadOperation.InstantiateSync(arSpace.transform);
}
else
{
Debug.Log("UnityEvo:未找到ARSpace,开始加载普通运行环境,通过语音唤醒...");
mainPrefab = loadOperation.InstantiateSync();
}
if(domainConfig.domain =="Main")
AppConfig.SetDefaultMainInstance(mainPrefab);
}
}
else if (loadResType == DomainConfig.LoadResType.Scene)
{
var sceneMode = domainConfig.loadSceneMode;
var physicsMode = LocalPhysicsMode.None;
SceneHandle handle = package.LoadSceneAsync(domainConfig.mainScene, sceneMode, physicsMode);
await handle;
mainPrefab = GameObject.Find(domainConfig.mainPrefab);
}
LocalTransformInfo info = mainPrefab.GetComponentInChildren<LocalTransformInfo>();
FsmLoadSystem fsmLoadSystem = FsmSystem as FsmLoadSystem;
if (info._list.Count >= 2)
{
if (fsmLoadSystem.GetOpenDomainType() == OpenDomainType.DEFAULT)
{
info.Switch(0);
}
else if (fsmLoadSystem.GetOpenDomainType() == OpenDomainType.VIOICE)
{
info.Switch(1);
}
}
else
{
Debug.LogError($"UnityEvo:{mainPrefab.name}的TransformInfo长度小于2,无法继续运行,请排查");
}
if (mainPrefab != null)
{
DomainBase hotfixInstance = mainPrefab.GetComponent(type) as DomainBase;
if (hotfixInstance == null)
{
hotfixInstance = mainPrefab.AddComponent(type) as DomainBase;
}
hotfixInstance.DomainName = domainConfig.domain;
if (hotfixInstance == null)
{
Debug.LogError($"热更类{type.Name}实例创建失败!必须继承MonoBehaviour");
return;
}
// 原有调用逻辑修改为使用实例
hotfixInstance.OnEnter("");
hotfixInstance.OnEnterAsync("");
}
}
public override void OnUpdate()
{
base.OnUpdate();
}
public override async UniTask OnExitAsync()
{
Debug.Log("UnityEvo:Domain退出...");
if (domainConfig.domain != "Main")
{
DomainBase domainBase = mainPrefab.GetComponent<DomainBase>();
if (domainBase == null)
{
Debug.LogError($"UnityEvo:{mainPrefab.name}的DomainBase为空,无法退出,请排查");
}
else
{
domainBase.OnExit();
await domainBase.OnExitAsync();
}
if (loadResType == DomainConfig.LoadResType.Scene)
{
await SceneManager.UnloadSceneAsync("server");
}
if (domainBase != null)
GameObject.Destroy(domainBase.gameObject);
}
}
}
}
@@ -9,6 +9,7 @@ using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.Networking;
using YooAsset;
using Object = UnityEngine.Object;
namespace Stary.Evo
{
@@ -31,7 +32,7 @@ namespace Stary.Evo
AppConfig.IpConfig = hotfixMainResDomain.hotfixMainResDomainEntity.ipconfig;
AppConfig.UserName = hotfixMainResDomain.hotfixMainResDomainEntity.username;
AppConfig.PassWord = hotfixMainResDomain.hotfixMainResDomainEntity.password;
AppConfig.ProductName = hotfixMainResDomain.hotfixMainResDomainEntity.productName;
AppConfig.ProductName =Application.identifier;
AppConfig.MainDomainVersion = hotfixMainResDomain.hotfixMainResDomainEntity.mainDomainVersion;
}
@@ -64,20 +65,20 @@ namespace Stary.Evo
await OFFLINE_PLAYMODE(package);
FsmSystem.SetCurState(nameof(ResUpdateLocalState));
#elif HOST_PLAYMODE
if (package.PackageName.Equals("Main"))
{
await OFFLINE_PLAYMODE(package);
}
else
{
// if (package.PackageName.Equals("Main"))
// {
// await OFFLINE_PLAYMODE(package);
// }
// else
// {
//登录
string url = AppConfig.IpConfig + "/Authentication/login";
bool isLogin = await WebRequestSystem.Login(url, AppConfig.UserName, AppConfig.PassWord);
if (isLogin)
await HOST_PLAYMODE(package);
else
await OFFLINE_PLAYMODE(package);
}
await Chche_PLAYMODE(package);
// }
FsmSystem.SetCurState(nameof(ResUpdateLocalState));
@@ -126,11 +127,7 @@ namespace Stary.Evo
private async UniTask EDITOR_SIMULATEMODE(ResourcePackage package)
{
var buildResult = EditorSimulateModeHelper.SimulateBuild(AppConfig.PackageDomainName);
var packageRoot = buildResult.PackageRootDirectory;
var editorFileSystemParameters = FileSystemParameters.CreateDefaultEditorFileSystemParameters(packageRoot);
var initParams = new EditorSimulateModeParameters();
initParams.EditorFileSystemParameters = editorFileSystemParameters;
var initParams=YooAssetFileSystem.EditorSimulateInitializeParameter();
var initialization = package.InitializeAsync(initParams);
await initialization;
if (initialization.Status == EOperationStatus.Succeed)
@@ -143,14 +140,45 @@ namespace Stary.Evo
Debug.LogError($"UnityEvo:资源包初始化失败:{initialization.Error}");
}
}
private async UniTask Chche_PLAYMODE(ResourcePackage package)
{
Debug.Log("UnityEvo:网络连接不通畅,切换缓存加载!");
var initParams=YooAssetFileSystem.hostInitializeParameter();
var initOperation = package.InitializeAsync(initParams);
await initOperation;
var operation = package.RequestPackageVersionAsync();
await operation;
if (operation.Status == EOperationStatus.Succeed)
{
PlayerPrefs.SetString($"{AppConfig.PackageDomainName}_GAME_VERSION", operation.PackageVersion);
Debug.Log("UnityEvo:从本地缓存中加载资源包,初始化获取版本号成功!");
}else
{
Debug.LogError($"UnityEvo:从本地缓存中加载资源包,初始化获取版本号失败!");
}
if (initOperation.Status == EOperationStatus.Succeed)
Debug.Log("UnityEvo:从本地缓存中资源包,初始化成功!");
else
Debug.LogError($"UnityEvo:从本地缓存中资源包,初始化失败:{initOperation.Error}");
}
private async UniTask OFFLINE_PLAYMODE(ResourcePackage package)
{
var buildinFileSystemParams = FileSystemParameters.CreateDefaultBuildinFileSystemParameters();
var initParameters = new OfflinePlayModeParameters();
initParameters.BuildinFileSystemParameters = buildinFileSystemParams;
var initOperation = package.InitializeAsync(initParameters);
var initParams=YooAssetFileSystem.OfflineInitializeParameter();
var initOperation = package.InitializeAsync(initParams);
await initOperation;
var operation = package.RequestPackageVersionAsync();
await operation;
if (operation.Status == EOperationStatus.Succeed)
{
PlayerPrefs.SetString($"{AppConfig.PackageDomainName}_GAME_VERSION", operation.PackageVersion);
Debug.Log("UnityEvo:从本地加载资源包,初始化获取版本号成功!");
}else
{
Debug.LogError($"UnityEvo:从本地加载资源包,初始化获取版本号失败!");
}
if (initOperation.Status == EOperationStatus.Succeed)
Debug.Log("UnityEvo:从本地加载资源包,初始化成功!");
@@ -202,15 +230,10 @@ namespace Stary.Evo
Debug.LogError($"UnityEvo:获取资源版本失败: 【{resDmainMessageEntity.message}】");
}
var initParameters = new OfflinePlayModeParameters();
var buildinFileSystemParams = FileSystemParameters.CreateDefaultBuildinFileSystemParameters(null,
$"{Application.persistentDataPath}/DownloadedContent/{AppConfig.PackageDomainName}");
buildinFileSystemParams.AddParameter(FileSystemParametersDefine.APPEND_FILE_EXTENSION, true);
buildinFileSystemParams.AddParameter(FileSystemParametersDefine.COPY_BUILDIN_PACKAGE_MANIFEST, true);
initParameters.BuildinFileSystemParameters = buildinFileSystemParams;
var initParams=YooAssetFileSystem.hostInitializeParameter();
// initParameters.CacheFileSystemParameters = cacheFileSystemParams;
var initOperation = package.InitializeAsync(initParameters);
var initOperation = package.InitializeAsync(initParams);
await initOperation;
@@ -228,24 +251,27 @@ namespace Stary.Evo
{
Directory.Delete(loadPath, true);
}
await MainArchitecture.Interface.GetSystem<IPanelSystem>()
.PushQueue<ProgressBarPanel>(Camera.main.transform, "Main");
FsmLoadSystem loadSystem =FsmSystem as FsmLoadSystem;
if (loadSystem.ProgressBarPanel == null)
{
loadSystem.ProgressBarPanel =Object.Instantiate(Resources.Load<GameObject>("ProgressBarPanel"),
Camera.main.transform).GetOrAddComponent<ProgressBarPanel>();
}
await ZipTool.DownloadAndUnzipAsync(fileId, loadPath, DownLoadProgress, UnzipProgress);
}
private void DownLoadProgress(float progress)
{
Debug.Log($"下载进度:{progress:P0}");
MainArchitecture.Interface.GetSystem<IPanelSystem>()
.SendPanelEvent(ProgressBarPanel.ProgressBarType.Add, "下载中", progress);
FsmLoadSystem loadSystem =FsmSystem as FsmLoadSystem;
loadSystem.ProgressBarPanel.SetProgressBarValue("下载中", progress);
}
private void UnzipProgress(float progress)
{
Debug.Log($"解压进度:{progress:P0}");
MainArchitecture.Interface.GetSystem<IPanelSystem>()
.SendPanelEvent(ProgressBarPanel.ProgressBarType.Add, "解压中", progress);
FsmLoadSystem loadSystem =FsmSystem as FsmLoadSystem;
loadSystem.ProgressBarPanel.SetProgressBarValue("解压中", progress);
}
}
}
@@ -7,19 +7,14 @@ namespace Stary.Evo
{
public class ResUpdateLocalState : AbstractFSMIState
{
public ResUpdateLocalState(IFsmSystem system) : base(system)
{
}
public override async UniTask OnEnterAsync()
public override async UniTask OnEnterAsync()
{
//初始化读取资源配置表
//初始化读取资源配置表
var package = YooAssets.GetPackage(AppConfig.PackageDomainName);
@@ -40,7 +35,7 @@ namespace Stary.Evo
else
{
//更新失败
Debug.LogError("Unity:【Main】"+operation.Error);
Debug.LogError("Unity:【Main】" + operation.Error);
}
}
else
@@ -53,7 +48,7 @@ namespace Stary.Evo
return;
}
}
Debug.Log($"UnityEvo:获取资源版本 Version : 【{packageVersion}】");
Debug.Log($"UnityEvo:开始加载本地资源...");
@@ -90,44 +85,41 @@ namespace Stary.Evo
{
//更新成功
Debug.Log($"UnityEvo:加载热更配置文件 DomainConfig : 【成功】");
domainConfig = loadHotfixSettingsOp.AssetObject as DomainConfig;
domainConfig = loadHotfixSettingsOp.AssetObject as DomainConfig;
}
else
{
Debug.LogError($"UnityEvo:加载热更配置文件 DomainConfig : 【失败】");
}
if (package.PackageName.Equals("Main"))
if (domainConfig == null)
{
FsmSystem.SetCurState(nameof(LoadResMainState));
Debug.LogError($"UnityEvo:【{package.PackageName}】加载DomainConfig为空,无法继续执行后续流程,请检查!!!");
}
else
{
if (domainConfig == null)
{
Debug.LogError($"UnityEvo:【{package.PackageName}】加载DomainConfig为空,无法继续执行后续流程,请检查!!!");
}
FsmSystem.SetCurState(nameof(HotFixState), domainConfig);
}
FsmSystem.SetCurState(nameof(HotFixState), domainConfig);
}
public override UniTask OnEnterAsync<T>(T param)
public override UniTask OnEnterAsync<T>(T param)
{
return UniTask.CompletedTask;
}
public override UniTask OnEnterAsync<T1, T2>(T1 param1, T2 param2)
{
return UniTask.CompletedTask;
}
public override void OnUpdate()
{
base.OnUpdate();
}
public override UniTask OnExitAsync()
{
return UniTask.CompletedTask;
return UniTask.CompletedTask;
}
#region
@@ -0,0 +1,193 @@
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.Assertions;
using YooAsset;
namespace Stary.Evo
{
public class ResUpdateServerState : AbstractFSMIState
{
public ResUpdateServerState(IFsmSystem system) : base(system)
{
}
public override async UniTask OnEnterAsync()
{
Debug.Log("UnityEvo:开始资源更新...");
// //初始化读取资源配置表
var package = YooAssets.GetPackage(AppConfig.PackageDomainName);
// 请求资源版本
var requetVersionOp = package.RequestPackageVersionAsync();
await requetVersionOp;
string packageVersion = "";
if (requetVersionOp.Status == EOperationStatus.Succeed)
{
//更新成功
packageVersion = requetVersionOp.PackageVersion;
PlayerPrefs.SetString($"{AppConfig.PackageDomainName}_GAME_VERSION", packageVersion);
Debug.Log($"UnityEvo:获取资源版本 Version : 【{packageVersion}】");
Debug.Log($"UnityEvo:开始加载服务器资源...");
}
else
{
Debug.LogError($"UnityEvo:获取资源版本失败: 【{requetVersionOp.Error}】");
FsmSystem.SetCurState(nameof(ResUpdateLocalState));
return;
}
// Assert.AreEqual(EOperationStatus.Succeed, requetVersionOp.Status);
// 更新资源清单
var updateManifestOp = package.UpdatePackageManifestAsync(packageVersion);
await updateManifestOp;
if (updateManifestOp.Status == EOperationStatus.Succeed)
{
//更新成功
Debug.Log($"UnityEvo:更新资源清单 updateManifest : 【成功】");
}
else
{
//更新失败
Debug.LogError($"UnityEvo:更新资源清单失败: 【{updateManifestOp.Error}】");
}
Assert.AreEqual(EOperationStatus.Succeed, updateManifestOp.Status);
//4.下载补丁包
await Download();
//加载热更配置文件
var loadHotfixSettingsOp = package.LoadAssetAsync<DomainConfig>("Config_DomainConfig");
await loadHotfixSettingsOp;
DomainConfig domainConfig = null;
if (loadHotfixSettingsOp.Status == EOperationStatus.Succeed)
{
//更新成功
Debug.Log($"UnityEvo:加载热更配置文件 loadHotfixSettings : 【成功】");
domainConfig = loadHotfixSettingsOp.AssetObject as DomainConfig;
}
else
{
Debug.LogError($"UnityEvo:加载热更配置文件 loadHotfixSettings : 【失败】");
}
if (domainConfig == null)
{
Debug.LogError($"UnityEvo:【{package.PackageName}】加载DomainConfig为空,无法继续执行后续流程,请检查!!!");
}
FsmSystem.SetCurState(nameof(HotFixState), domainConfig);
}
public override UniTask OnEnterAsync<T>(T param)
{
return UniTask.CompletedTask;
}
public override UniTask OnEnterAsync<T1, T2>(T1 param1, T2 param2)
{
return UniTask.CompletedTask;
}
public override void OnUpdate()
{
base.OnUpdate();
}
public override UniTask OnExitAsync()
{
return UniTask.CompletedTask;
}
#region
public async UniTask Download()
{
int downloadingMaxNum = 10;
int failedTryAgain = 3;
var package = YooAssets.GetPackage(AppConfig.PackageDomainName);
var downloader = package.CreateResourceDownloader(downloadingMaxNum, failedTryAgain);
//没有需要下载的资源
if (downloader.TotalDownloadCount == 0)
{
Debug.Log("UnityEvo:没有需要下载的资源,跳过更新");
return;
}
//需要下载的文件总数和总大小
int totalDownloadCount = downloader.TotalDownloadCount;
long totalDownloadBytes = downloader.TotalDownloadBytes;
Debug.Log($"UnityEvo:需要下载的资源的个数【{totalDownloadCount}】,需要下载的资源的总大小{totalDownloadBytes / 1024} MB");
//===================================适应新版本YooAsset插件的修改===================================
//注册回调方法
downloader.DownloadErrorCallback = OnDownloadErrorFunction;
downloader.DownloadUpdateCallback = OnDownloadProgressUpdateFunction;
downloader.DownloadFinishCallback = OnDownloadOverFunction;
downloader.DownloadFileBeginCallback = OnStartDownloadFileFunction;
//===================================适应新版本YooAsset插件的修改===================================
//开启下载
downloader.BeginDownload();
await downloader;
//检测下载结果
if (downloader.Status == EOperationStatus.Succeed)
{
//下载成功
Debug.Log("UnityEvo:资源更新完成");
}
else
{
//下载失败
Debug.Log("UnityEvo:资源更新失败");
}
}
//===================================适应新版本YooAsset插件的修改===================================
/// <summary>
/// 开始下载
/// </summary>
private void OnStartDownloadFileFunction(DownloadFileData downloadFileData)
{
Debug.Log(
$"UnityEvo:开始下载:文件名:{downloadFileData.FileName},文件大小:{downloadFileData.FileSize / 1024f / 1024f} MB");
}
/// <summary>
/// 下载完成
/// </summary>
private void OnDownloadOverFunction(DownloaderFinishData downloaderFinishData)
{
Debug.Log("UnityEvo:下载" + (downloaderFinishData.Succeed ? "成功" : "失败"));
}
/// <summary>
/// 更新中
/// </summary>
private void OnDownloadProgressUpdateFunction(DownloadUpdateData downloadUpdateData)
{
Debug.Log(
$"UnityEvo:文件总数:{downloadUpdateData.TotalDownloadCount},已下载文件数:{downloadUpdateData.CurrentDownloadCount},下载总大小:{downloadUpdateData.TotalDownloadBytes / 1024f / 1024f} MB,已下载大小{downloadUpdateData.CurrentDownloadBytes / 1024f / 1024f} MB");
}
/// <summary>
/// 下载出错
/// </summary>
/// <param name="errorData"></param>
private void OnDownloadErrorFunction(DownloadErrorData errorData)
{
Debug.Log($"UnityEvo:下载出错:包名:{errorData.PackageName} 文件名:{errorData.FileName},错误信息:{errorData.ErrorInfo}");
}
//===================================适应新版本YooAsset插件的修改===================================
#endregion
}
}
@@ -21,7 +21,7 @@ namespace Stary.Evo
_fsmSystem.AddState(new ResUpdateLocalState(_fsmSystem));
_fsmSystem.AddState(new HotFixState(_fsmSystem));
_fsmSystem.AddState(new LoadResState(_fsmSystem));
_fsmSystem.AddState(new LoadResMainState(_fsmSystem));
//_fsmSystem.AddState(new LoadResMainState(_fsmSystem));
}
private void Start()
@@ -1,4 +1,6 @@
using Cysharp.Threading.Tasks;
using System;
using System.Threading;
using Cysharp.Threading.Tasks;
using Stary.Evo;
using UnityEngine;
using YooAsset;
@@ -23,20 +25,22 @@ namespace Main
private Stary.Evo.TableTextConversion.UITableData uiTableDatas;
private CancellationTokenSource _cancellationTokenSource;
protected override async void OnInit()
{
}
public async UniTask LoadData(string audiotabledata_asset, string uitabledata_asset)
{
_cancellationTokenSource = new CancellationTokenSource();
var audioHandle =
YooAssets.LoadAssetAsync<Stary.Evo.TableTextConversion.AudioTableData>(audiotabledata_asset);
await audioHandle.Task;
await audioHandle.WithCancellation(_cancellationTokenSource.Token);
audioTableData = audioHandle.GetAssetObject<Stary.Evo.TableTextConversion.AudioTableData>();
var UIHandle =
YooAssets.LoadAssetAsync<Stary.Evo.TableTextConversion.UITableData>(uitabledata_asset);
await UIHandle.Task;
await UIHandle.WithCancellation(_cancellationTokenSource.Token);
uiTableDatas = UIHandle.GetAssetObject<Stary.Evo.TableTextConversion.UITableData>();
}
@@ -66,7 +70,7 @@ namespace Main
{
var info=GetAudioInfo(auid);
var handle = YooAssets.LoadAssetAsync<AudioClip>(info.filename);
await handle.Task;
await handle.WithCancellation(_cancellationTokenSource.Token);
if (handle.Status == EOperationStatus.Succeed)
{
return handle.GetAssetObject<AudioClip>();
@@ -99,7 +103,7 @@ namespace Main
}
else
{
Debug.LogError($"没有找到对应的uiid,错误的id为:{info.uirelated}");
Debug.Log($"没有找到对应的uiid,错误的id为:{info.uirelated}");
return default;
}
}
@@ -112,21 +116,29 @@ namespace Main
{
var info=GetAudioToUIInfo(auid);
AudioClip audioClip = await GetAudioClip(auid);
Sprite sprite = await GetUISprite(info.UIMessageInfo.uiid);
if (audioClip != null && sprite != null)
var audioTableData = new AudioToUIData();
if (audioClip != null)
{
return new AudioToUIData()
{
audioClip = audioClip,
sprite = sprite
};
audioTableData.audioClip = audioClip;
}
else
{
Debug.LogError($"没有找到对应的uiid,错误的id为:{info.UIMessageInfo.uiid}");
return default;
Debug.LogError($"没有找到对应的auid,错误的id为:{auid}");
}
if (info.UIMessageInfo != null)
{
Sprite sprite = await GetUISprite(info.UIMessageInfo.uiid);
if ( sprite != null)
{
audioTableData.sprite = sprite;
}
else
{
Debug.LogError($"没有找到对应的uiid,错误的id为:{info.UIMessageInfo.uiid}");
}
}
return audioTableData;
}
/// <summary>
/// 获取UI数据
@@ -153,7 +165,7 @@ namespace Main
var info = GetUIInfo(uiid);
var handle = YooAssets.LoadAssetAsync<Sprite>(info.filename);
await handle.Task;
await handle.WithCancellation(_cancellationTokenSource.Token);
if (handle.Status == EOperationStatus.Succeed)
{
return handle.GetAssetObject<Sprite>();
@@ -168,6 +180,18 @@ namespace Main
public override void Dispose()
{
try
{
if (_cancellationTokenSource != null && !_cancellationTokenSource.IsCancellationRequested)
{
_cancellationTokenSource.Cancel();
_cancellationTokenSource.Dispose();
}
}
catch (OperationCanceledException e)
{
Debug.Log("异步取消操作");
}
}
public struct AudioToUITableData
@@ -0,0 +1,42 @@
using System;
using Cysharp.Threading.Tasks;
using Stary.Evo;
using Stary.Evo.AudioCore;
using Stary.Evo.InformationSave;
using Stary.Evo.UIFarme;
using UnityEngine;
using UnityEngine.UI;
using YooAsset;
namespace Main
{
public class ProgressBarPanel : MonoBehaviour
{
private Image _fill;
private Text _fillText;
private Text _fillMessage;
private void Awake()
{
_fill = this.transform.Find("Fill").GetComponent<Image>();
_fillText = _fill.transform.Find("FillText").GetComponent<Text>();
_fillMessage = _fill.transform.Find("FillMessage").GetComponent<Text>();
_fill.fillAmount = 0;
_fillText.text = "0%";
}
public async void SetProgressBarValue(string message, float value)
{
this.gameObject.SetActive(true);
_fill.fillAmount = value;
_fillMessage.text = message;
_fillText.text = $"{value:P0}";
if (value >= 1)
{
this.gameObject.SetActive(false);
}
}
}
}
@@ -0,0 +1,45 @@
using Cysharp.Threading.Tasks;
using Stary.Evo;
using YooAsset;
namespace X_04_04
{
public interface IUITableData : IData
{
UniTask LoadData(string audiotabledata_asset);
Stary.Evo.TableTextConversion.UITableData.MessageInfo GetUIInfo(string uiid);
}
public class UITableData : AbstractData, IUITableData
{
private Stary.Evo.TableTextConversion.UITableData uiTableDatas;
protected override async void OnInit()
{
}
public async UniTask LoadData(string audiotabledata_asset)
{
var handle = YooAssets.LoadAssetAsync<Stary.Evo.TableTextConversion.UITableData>(audiotabledata_asset);
await handle.Task;
uiTableDatas = handle.GetAssetObject<Stary.Evo.TableTextConversion.UITableData>();
}
public Stary.Evo.TableTextConversion.UITableData.MessageInfo GetUIInfo(string uiid)
{
var info = uiTableDatas.infos.Find(x => x.uiid == uiid);
if (info != null && !info.filename.Contains("Sprites_"))
{
info.filename="Sprites_"+info.filename;
}
return info;
}
public override void Dispose()
{
}
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 79b808b96820ad546951a6859e2a99be
guid: 31eb4845a899e544dab03b7aba620e01
MonoImporter:
externalObjects: {}
serializedVersion: 2
@@ -1,5 +1,8 @@
using Cysharp.Threading.Tasks;
using System;
using System.Threading;
using Cysharp.Threading.Tasks;
using Stary.Evo;
using UnityEngine;
using YooAsset;
namespace Main
@@ -9,38 +12,52 @@ namespace Main
UniTask LoadData(string videotabledata_asset);
Stary.Evo.TableTextConversion.VideoTableData.MessageInfo PlayVideoName(string vidid);
}
public class VideoTableData : AbstractData, IVideoTableData
{
private Stary.Evo.TableTextConversion.VideoTableData videoTableDatas;
private CancellationTokenSource _cancellationTokenSource;
protected override async void OnInit()
{
}
public async UniTask LoadData(string videotabledata_asset)
{
_cancellationTokenSource = new CancellationTokenSource();
var handle = YooAssets.LoadAssetAsync<Stary.Evo.TableTextConversion.VideoTableData>(videotabledata_asset);
await handle.Task;
await handle.WithCancellation(this._cancellationTokenSource.Token);
videoTableDatas = handle.GetAssetObject<Stary.Evo.TableTextConversion.VideoTableData>();
}
public Stary.Evo.TableTextConversion.VideoTableData.MessageInfo PlayVideoName(string vidid)
{
var info = videoTableDatas.infos.Find(x => x.vidid == vidid);
if (info != null && !info.filename.Contains("Video"))
{
info.filename="Video_"+info.filename;
info.filename = "Video_" + info.filename;
}
return info;
}
public override void Dispose()
{
try
{
if (_cancellationTokenSource != null && !_cancellationTokenSource.IsCancellationRequested)
{
_cancellationTokenSource.Cancel();
_cancellationTokenSource.Dispose();
}
}
catch (OperationCanceledException e)
{
Debug.Log("异步取消操作");
}
}
}
}
@@ -0,0 +1,190 @@
using System;
using Cysharp.Threading.Tasks;
using DG.Tweening;
using Stary.Evo;
using Stary.Evo.AudioCore;
using Stary.Evo.UIFarme;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Video;
using YooAsset;
public class VideoPanel : BasePanel
{
private RawImage intro;
private GameObject prospect;
private GameObject bg;
private Animator _animator;
private VideoPlayer videoPlayer;
private AudioSource audioSource;
private RenderTexture renderTexture;
public VideoPanel()
{
}
public override void Initialize(GameObject panelGo)
{
base.Initialize(panelGo);
intro = activePanel.transform.Find("Intro").GetComponent<RawImage>();
prospect = activePanel.transform.Find("prospect").gameObject;
bg = activePanel.transform.Find("bg").gameObject;
videoPlayer = activePanel.GetComponentInChildren<VideoPlayer>();
audioSource = activePanel.GetComponentInChildren<AudioSource>();
_animator = activePanel.GetComponentInChildren<Animator>();
}
public override void OnEnter()
{
base.OnEnter();
this.RegisterEvent<ModeType, VideoInfo>(ModeType.VideoStart, OnStartMove);
this.RegisterEvent<ModeType>(ModeType.VideoEnd, OnStopMove);
}
public override void OnExit(float delay = 0)
{
base.OnExit(delay);
this.UnRegisterEvent<ModeType, VideoInfo>(ModeType.VideoStart, OnStartMove);
this.UnRegisterEvent<ModeType>(ModeType.VideoEnd, OnStopMove);
}
private void OnStartMove(VideoInfo info)
{
if (info.filename.Equals(""))
{
Debug.LogError("UnityEvo:视频文件名为空,必须传文件名才能执行");
return;
}
if (info.position != null)
{
activePanel.transform.position = info.position.SetVector3Ctor();
}
if (info.rotation != null)
{
activePanel.transform.rotation = Quaternion.Euler(info.rotation.SetVector3Ctor());
}
if (info.scale != null)
{
activePanel.transform.DOScale(info.scale.SetVector3Ctor(), 0.5f);
}
OnStartMove(info.filename, info.callback, info.isFixedSize);
}
private async void OnStartMove(string fileName, Action callback, bool isFixedSize)
{
if (isFixedSize)
{
_animator.gameObject.SetActive(false);
bg.SetActive(false);
prospect.SetActive(false);
}
else
{
_animator.gameObject.SetActive(true);
bg.SetActive(true);
prospect.SetActive(true);
}
//新增renderTexture创建
if (videoPlayer.isPlaying)
{
videoPlayer.Stop();
//释放renderTexture
if (renderTexture != null)
{
renderTexture.Release();
renderTexture = null;
}
}
var videHandle = YooAssets.LoadAssetAsync<VideoClip>(fileName);
await videHandle.Task;
Debug.Log("UnityEvo:开始播放视频:" + fileName);
VideoClip videoClip = videHandle.GetAssetObject<VideoClip>();
renderTexture = new RenderTexture((int)videoClip.width, (int)videoClip.height, 24);
videoPlayer.targetTexture = renderTexture;
intro.texture = renderTexture;
intro.SetNativeSize();
var musicHandle = YooAssets.LoadAssetAsync<AudioClip>(fileName + "_mp3");
await musicHandle.Task;
videoPlayer.source = VideoSource.VideoClip;
videoPlayer.clip = videoClip;
Debug.Log("UnityEvo:开始播放视频的音频:" + fileName + "_mp3");
AudioClip audioClip = musicHandle.GetAssetObject<AudioClip>();
audioSource.clip = audioClip;
//等待视频加载完成
videoPlayer.Prepare();
videoPlayer.prepareCompleted += (source) =>
{
_animator.Play("vid_maskAni", 0, 0);
//预加载
if (videoPlayer.isPrepared)
{
videoPlayer.Play();
audioSource.Play();
}
};
videoPlayer.loopPointReached += (source) =>
{
OnStopMove();
callback?.Invoke();
};
videoPlayer.errorReceived += (source, error) => { Debug.LogError($"视频播放失败:{error}"); };
}
private void OnStopMove()
{
Debug.Log("UnityEvo:视频播放完成");
AudioCoreManager.SetMusicVolume(new AudioData()
{
fadeDuration = 2f,
volume = 1f,
});
_animator.Play("vid_maskDefault", 0, 0);
if (renderTexture != null)
{
renderTexture.Release();
renderTexture = null;
}
if (audioSource.isPlaying)
{
audioSource.Stop();
}
PanelSystem.PopQueue<VideoPanel>();
}
public struct VideoInfo
{
public string filename;
public Vector3Ctor position;
public Vector3Ctor rotation;
public Vector3Ctor scale;
public Action callback;
public bool isFixedSize;
}
}
@@ -1,4 +1,5 @@
using System;
using System.Threading;
using Stary.Evo;
using Stary.Evo.AudioCore;
using Stary.Evo.UIFarme;
@@ -12,8 +13,10 @@ public interface IVideoSystem : ISystem
public class VideoSystem : AbstractSystem, IVideoSystem
{
private CancellationTokenSource _cancellationTokenSource;
protected override void OnInit()
{
_cancellationTokenSource = new CancellationTokenSource();
}
public override void Dispose()
@@ -133,6 +133,9 @@ namespace R
public const string vid_mask_060_png = "vid_video_mask_vid_mask_060";
}
}
public static class video
{
}
}
}
}
@@ -0,0 +1,88 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class BezierCurve
{
// 新增路径生成方法
public static Vector3[] GenerateBezierPath(Vector3[] controlPoints, int segments = 20)
{
Vector3[] path = new Vector3[segments + 1];
for (int i = 0; i <= segments; i++)
{
float t = i / (float)segments;
switch (controlPoints.Length)
{
case 2:
path[i] = LineBezier(controlPoints[0], controlPoints[1], t);
break;
case 3:
path[i] = QuadraticBezier(controlPoints, t);
break;
case 4:
path[i] = CubicBezier(controlPoints, t);
break;
default: // 处理n阶情况
path[i] = BezierInterpolation(controlPoints, t);
break;
}
}
return path;
}
// 一阶贝塞尔(线性插值)
public static Vector3 LineBezier(Vector3 p0, Vector3 p1, float t)
{
return Vector3.Lerp(p0, p1, t);
}
// 二阶贝塞尔曲线
public static Vector3 QuadraticBezier(Vector3[] points, float t)
{
if (points.Length != 3) Debug.LogError("需要3个控制点");
float u = 1 - t;
return
u * u * points[0] +
2 * u * t * points[1] +
t * t * points[2];
}
// 三阶贝塞尔曲线
public static Vector3 CubicBezier(Vector3[] points, float t)
{
if (points.Length != 4) Debug.LogError("需要4个控制点");
float u = 1 - t;
return
u * u * u * points[0] +
3 * u * u * t * points[1] +
3 * u * t * t * points[2] +
t * t * t * points[3];
}
// n阶贝塞尔曲线(通用实现)
public static Vector3 BezierInterpolation(Vector3[] points, float t)
{
if (points.Length < 2)
{
Debug.LogError("至少需要2个控制点");
return Vector3.zero;
}
Vector3[] temp = new Vector3[points.Length];
points.CopyTo(temp, 0);
// 德卡斯特里奥算法递推
for (int k = 1; k < points.Length; k++)
{
for (int i = 0; i < points.Length - k; i++)
{
temp[i] = Vector3.Lerp(temp[i], temp[i + 1], t);
}
}
return temp[0];
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 121e5154d8bb6ac49a32eeeadeba3e45
guid: d0f6bf90b6c476e4eb75f7a6dae5c45d
MonoImporter:
externalObjects: {}
serializedVersion: 2
@@ -0,0 +1,35 @@
using UnityEngine;
using YooAsset;
namespace Stary.Evo
{
public class YooAssetFileSystem
{
public static InitializeParameters OfflineInitializeParameter()
{
var buildinFileSystemParams = FileSystemParameters.CreateDefaultBuildinFileSystemParameters();
var initParameters = new OfflinePlayModeParameters();
initParameters.BuildinFileSystemParameters = buildinFileSystemParams;
return initParameters;
}
public static InitializeParameters hostInitializeParameter()
{
var initParameters = new OfflinePlayModeParameters();
var buildinFileSystemParams = FileSystemParameters.CreateDefaultBuildinFileSystemParameters(null,
$"{Application.persistentDataPath}/DownloadedContent/{AppConfig.PackageDomainName}");
buildinFileSystemParams.AddParameter(FileSystemParametersDefine.APPEND_FILE_EXTENSION, true);
buildinFileSystemParams.AddParameter(FileSystemParametersDefine.COPY_BUILDIN_PACKAGE_MANIFEST, true);
initParameters.BuildinFileSystemParameters = buildinFileSystemParams;
return initParameters;
}
public static InitializeParameters EditorSimulateInitializeParameter()
{
var buildResult = EditorSimulateModeHelper.SimulateBuild(AppConfig.PackageDomainName);
var packageRoot = buildResult.PackageRootDirectory;
var editorFileSystemParameters = FileSystemParameters.CreateDefaultEditorFileSystemParameters(packageRoot);
var initParams = new EditorSimulateModeParameters();
initParams.EditorFileSystemParameters = editorFileSystemParameters;
return initParams;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c6f288f9aa65416baf25a50a4056fcae
timeCreated: 1749695458
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 90f5ed74142c4ae695e3e0c175e59b06
timeCreated: 1750651156
@@ -0,0 +1,14 @@
*.sln
*.csproj
SocketClient/.vscode/
SocketClient/Packages/
SocketClient/Logs/
SocketClient/Library/
SocketServer/Packages/
SocketServer/obj/
SocketServer/Logs/
SocketServer/Library/
SocketServer/.vscode/
SocketClient/obj/
SocketClient/Temp/
SocketServer/Temp/
@@ -0,0 +1,71 @@
# UnitySocket
该项目是基于Unity平台 纯C#编写的Socket网络模块,包括客户端与服务端的实现
## 环境依赖
- 项目运行平台: Unity2022.3.22f1
该项目仅包含网络底层的几个C#脚本与一个测试脚本,可以随意选择Unity版本测试。
## 特点
1. 回调事件完善,包含服务器主动踢出、客户端主动断开、心跳包等底层功能逻辑。
2. 对象形式,非单例模式,一个项目可new多个连接
3. 代码量少,纯C#编写,未使用插件、DLL及工具类,便于二次封装,利于移植
## 报文组成
- 通用
报文总长度(4byte) + 报文类型(2byte) + 数据(N byte)
- 心跳包
报文总长度(4byte) + 报文类型-心跳包(2byte)
- 客户端断开
报文总长度(4byte) + 报文类型-客户端断开(2byte)
- 服务端踢出
报文总长度(4byte) + 报文类型-服务端踢出(2byte)
## 工作流
- 建立连接
1. 服务端通过 new SocketServer(string ip,int port) 建立连接
2. 客户端通过 new SocketClient(string ip,int port) 建立实例,通过Connect函数尝试连接。
3. 客户端连接成功后,开始定时发送心跳包报文;服务端接收后记录时间,定时检测判断是否超时。
4. 如存在以下情况,则断开连接:
- 服务端主动踢出连接,即时响应,回调DisConnect
- 客户端主动断开连接,即时响应,回调DisConnect
- 客户端关闭连接,即时响应,回调DisConnect
- 服务端检测到客户端太久没有发送心跳包,此处需要响应时间,根据心跳包超时间隔、心跳包发送间隔及服务端心跳包超时检测间隔来决定,发现超时则回调DisConnect
- 通信逻辑过程中报错,即时响应,自动重连,默认重连上限为三次,达到重连上限并未成功,则回调DisConnect
- 接收数据
1. 接收线程收到数据,存放入DataBuff数据缓存区。
2. DataBuff中不断通过SocketDataPack尝试解包,解包成功后将报文发送到接收线程。
3. 接收线程收到报文后,触发OnReceive回调
4. 业务层通过OnReceive回调接收到报文后,反序列化报文体得到数据
- 发送数据
1. 业务层序列化数据得到报文体字节集,通过Send函数发送数据。
2. Send函数中,通过SocketDataPack装包后,以字节集的形式发送出去。
## 代码说明
- DataBufferSocket传输数据缓存区,此处主要处理Socket传输时粘包、分包的情况
- SocketEventSocket报文类型枚举,此处只枚举了网络底层需要发送的报文类型,业务逻辑层所使用的报文类型,建议封装至报文体序列化类中
- SocketDataPackSocket报文类,处理具体的拆包、装包逻辑
- SocketServerSocket服务端
- SocketClientSocket客户端
## 回调事件
- SocketServer 服务端
- public event Action<Socket> OnConnect; //客户端建立连接回调
- public event Action<Socket> OnDisconnect; // 客户端断开连接回调
- public event Action<Socket, SocketDataPack> OnReceive; // 接收报文回调
- SocketClient 客户端
- public event Action OnConnectSuccess; // 连接成功回调
- public event Action OnConnectError; // 连接失败回调
- public event Action OnDisconnect; // 断开回调
- public event Action<SocketDataPack> OnReceive; // 接收报文回调
- public event Action<SocketException> OnError; // 异常捕获回调
- public event Action<int> OnReConnectSuccess; // 重连成功回调
- public event Action<int> OnReConnectError; // 单次重连失败回调
- public event Action<int> OnReconnecting; // 单次重连中回调
@@ -1,7 +1,6 @@
fileFormatVersion: 2
guid: 08e4dd259b2cfef419fa885222c533b1
folderAsset: yes
DefaultImporter:
guid: 3f0c65b3aa2616440978bf5d9f804e7c
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 0dfec6660d6d5d34c9a5b4ba8a2e3498
guid: 7b43e2f4bdef74642999b4d5530a9b3d
folderAsset: yes
DefaultImporter:
externalObjects: {}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 0f3ff09b4853f0948ab930b5371dd636
guid: 2e04a0e82198abe4fb1796dc44bc9e9d
folderAsset: yes
DefaultImporter:
externalObjects: {}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 3196c042bce6e4f41b144335b4bfd000
guid: e3cdc884284e12f48a350017446975ca
folderAsset: yes
DefaultImporter:
externalObjects: {}
@@ -0,0 +1,57 @@
using System;
/// <summary>
/// Socket传输过程的缓冲区,尝试拆包获得数据
/// </summary>
public class DataBuffer
{
// 缓存区长度
private const int MIN_BUFF_LEN = 1024;
private byte[] _buff;
private int _buffLength = 0;
public DataBuffer(int minBuffLen = MIN_BUFF_LEN)
{
if (minBuffLen <= 0)
{
minBuffLen = MIN_BUFF_LEN;
}
_buff = new byte[minBuffLen];
}
/// <summary>
/// 添加缓存数据
/// </summary>
public void AddBuffer(byte[] data, int len)
{
byte[] buff = new byte[len];
Array.Copy(data, buff, len);
if (len > _buff.Length - _buffLength) //超过当前缓存
{
byte[] temp = new byte[_buffLength + len];
Array.Copy(_buff, 0, temp, 0, _buffLength);
Array.Copy(buff, 0, temp, _buffLength, len);
_buff = temp;
}
else
{
Array.Copy(data, 0, _buff, _buffLength, len);
}
_buffLength += len;//修改当前数据标记
}
public bool TryUnpack(out SocketDataPack dataPack)
{
dataPack = SocketDataPack.Unpack(_buff);
if (dataPack == null)
{
return false;
}
// 清理旧缓存
_buffLength -= dataPack.BuffLength;
byte[] temp = new byte[_buffLength < MIN_BUFF_LEN ? MIN_BUFF_LEN : _buffLength];
Array.Copy(_buff, dataPack.BuffLength, temp, 0, _buffLength);
_buff = temp;
return true;
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 6ff3c700b7f108b48998aa1630a769e1
guid: e879d0a89aac39f4a8320fd3857d0012
MonoImporter:
externalObjects: {}
serializedVersion: 2
@@ -0,0 +1,332 @@
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Timers;
/// <summary>
/// Socket客户端
/// </summary>
public class SocketClient
{
/// <summary>
/// 主线程
/// </summary>
private readonly SynchronizationContext _mainThread;
private readonly string _ip;
private readonly int _port;
private const int TIMEOUT_CONNECT = 3000; // 连接超时时间 毫秒
private const int TIMEOUT_SEND = 3000; // 发送超时时间 毫秒
private const int TIMEOUT_RECEIVE = 3000; //接收超时时间 毫秒
private const int HEAD_OFFSET = 2000; //心跳包发送间隔 毫秒
private const int RECONN_MAX_SUM = 3; //最大重连次数
private Socket _client;
private Thread _receiveThread;
private System.Timers.Timer _connTimeoutTimer;
private System.Timers.Timer _headTimer;
private readonly DataBuffer _dataBuffer = new DataBuffer();
public event Action OnConnectSuccess; // 连接成功回调
public event Action OnConnectError; // 连接失败回调
public event Action OnDisconnect; // 断开回调
public event Action<SocketDataPack> OnReceive; // 接收报文回调
public event Action<SocketDataPack> OnSend; // 发送报文回调
public event Action<SocketException> OnError; // 异常捕获回调
public event Action<int> OnReConnectSuccess; // 重连成功回调
public event Action<int> OnReConnectError; // 单次重连失败回调
public event Action<int> OnReconnecting; // 单次重连中回调
private bool _isConnect = false;
private bool _isReconnect = false;
public SocketClient(string ip, int port)
{
_mainThread = SynchronizationContext.Current;
_ip = ip;
_port = port;
}
public void Connect(Action success = null, Action error = null)
{
OnDisconnect += () => { UnityEngine.Debug.Log("UnityEvo:断开连接"); };
OnReceive += (dataPack) => { UnityEngine.Debug.LogFormat("UnityEvo:接收数据>>>{0}", (SocketEvent)dataPack.Type); };
OnSend += (dataPack) => { UnityEngine.Debug.LogFormat("UnityEvo:发送数据>>>{0}", (SocketEvent)dataPack.Type); };
OnError += (ex) => { UnityEngine.Debug.LogFormat("UnityEvo:出现异常>>>{0}", ex); };
OnReConnectSuccess += (num) => { UnityEngine.Debug.LogFormat("UnityEvo:第{0}次重连成功", num); };
OnReConnectError += (num) => { UnityEngine.Debug.LogFormat("UnityEvo:第{0}次重连失败", num); };
OnReconnecting += (num) => { UnityEngine.Debug.LogFormat("UnityEvo:正在进行第{0}次重连", num); };
void OnTrigger(bool flag)
{
if (flag)
{
PostMainThreadAction(success);
PostMainThreadAction(OnConnectSuccess);
}
else
{
PostMainThreadAction(error);
PostMainThreadAction(OnConnectError);
}
if (_connTimeoutTimer != null)
{
_connTimeoutTimer.Stop();
_connTimeoutTimer = null;
}
}
try
{
_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建套接字
_client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, TIMEOUT_SEND);
_client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, TIMEOUT_RECEIVE);
IPAddress ipAddress = IPAddress.Parse(_ip);//解析IP地址
IPEndPoint ipEndpoint = new IPEndPoint(ipAddress, _port);
IAsyncResult result = _client.BeginConnect(ipEndpoint, new AsyncCallback((iar) =>
{
try
{
Socket client = (Socket)iar.AsyncState;
client.EndConnect(iar);
_isConnect = true;
// 开始发送心跳包
_headTimer = new System.Timers.Timer(HEAD_OFFSET);
_headTimer.AutoReset = true;
_headTimer.Elapsed += delegate (object sender, ElapsedEventArgs args)
{
Send((UInt16)SocketEvent.ClientHead);
};
_headTimer.Start();
// 开始接收数据
_receiveThread = new Thread(new ThreadStart(ReceiveEvent));
_receiveThread.IsBackground = true;
_receiveThread.Start();
OnTrigger(true);
}
catch (SocketException ex)
{
OnTrigger(false);
}
}), _client);//异步连接
_connTimeoutTimer = new System.Timers.Timer(TIMEOUT_CONNECT);
_connTimeoutTimer.AutoReset = false;
_connTimeoutTimer.Elapsed += delegate (object sender, ElapsedEventArgs args)
{
OnTrigger(false);
};
_connTimeoutTimer.Start();
}
catch (SocketException ex)
{
OnTrigger(false);
// throw;
}
}
/// <summary>
/// 断线重连
/// </summary>
/// <param name="num"></param>
/// <param name="index"></param>
public void ReConnect(int num = RECONN_MAX_SUM, int index = 0)
{
_isReconnect = true;
num--;
index++;
if (num < 0)
{
onDisconnect();
_isReconnect = false;
return;
}
PostMainThreadAction<int>(OnReconnecting, index);
Connect(() =>
{
PostMainThreadAction<int>(OnReConnectSuccess, index);
_isReconnect = false;
}, () =>
{
PostMainThreadAction<int>(OnReConnectError, index);
ReConnect(num, index);
});
}
public void Send(UInt16 e, byte[] buff = null, Action<SocketDataPack> onTrigger = null)
{
buff = buff ?? new byte[] { };
var dataPack = new SocketDataPack(e, buff);
var data = dataPack.Buff;
try
{
_client.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback((asyncSend) =>
{
Socket c = (Socket)asyncSend.AsyncState;
c.EndSend(asyncSend);
PostMainThreadAction<SocketDataPack>(onTrigger, dataPack);
PostMainThreadAction<SocketDataPack>(OnSend, dataPack);
}), _client);
}
catch (SocketException ex)
{
onError(ex);
}
}
/// <summary>
/// 线程内接收数据的函数
/// </summary>
private void ReceiveEvent()
{
while (true)
{
try
{
if (!_isConnect) break;
if (_client.Available <= 0) continue;
byte[] rbytes = new byte[8 * 1024];
int len = _client.Receive(rbytes);
if (len > 0)
{
_dataBuffer.AddBuffer(rbytes, len); // 将收到的数据添加到缓存器中
if (_dataBuffer.TryUnpack(out var dataPack)) // 尝试解包
{
if (dataPack.Type == (UInt16)SocketEvent.ServerKickout)
{
// 服务端踢出
onDisconnect();
}
else if (dataPack.Type == (UInt16)SocketEvent.ServerMessage)
{
// 收到消息
PostMainThreadAction<SocketDataPack>(OnReceive, dataPack);
}
}
}
}
catch (SocketException ex)
{
onError(ex);
// throw;
}
}
}
/// <summary>
/// 业务逻辑 - 客户端主动断开
/// </summary>
public void DisConnect()
{
Send((UInt16)SocketEvent.ClientDisconn);
onDisconnect();
}
/// <summary>
/// 缓存数据清理
/// </summary>
public void Close()
{
if (!_isConnect) return;
_isConnect = false;
if (_headTimer != null)
{
_headTimer.Stop();
_headTimer = null;
}
// if (_receiveThread != null)
// {
// _receiveThread.Abort();
// _receiveThread = null;
// }
if (_connTimeoutTimer != null)
{
_connTimeoutTimer.Stop();
_connTimeoutTimer = null;
}
if (_client != null)
{
_client.Close();
_client = null;
}
}
/// <summary>
/// 错误回调
/// </summary>
/// <param name="e"></param>
private void onError(SocketException ex)
{
Close();
PostMainThreadAction<SocketException>(OnError, ex);
if (!_isReconnect)
{
ReConnect();
}
}
/// <summary>
/// 断开回调
/// </summary>
private void onDisconnect()
{
Close();
PostMainThreadAction(OnDisconnect);
}
/// <summary>
/// 通知主线程回调
/// </summary>
private void PostMainThreadAction(Action action)
{
_mainThread.Post(new SendOrPostCallback((o) =>
{
Action e = (Action)o.GetType().GetProperty("action")?.GetValue(o);
if (e != null) e();
}), new { action = action });
}
private void PostMainThreadAction<T>(Action<T> action, T arg1)
{
_mainThread.Post(new SendOrPostCallback((o) =>
{
Action<T> e = (Action<T>)o.GetType().GetProperty("action")?.GetValue(o);
T t1 = (T)o.GetType().GetProperty("arg1")?.GetValue(o);
if (e != null) e(t1);
}), new { action = action, arg1 = arg1 });
}
public void PostMainThreadAction<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2)
{
_mainThread.Post(new SendOrPostCallback((o) =>
{
Action<T1, T2> e = (Action<T1, T2>)o.GetType().GetProperty("action")?.GetValue(o);
T1 t1 = (T1)o.GetType().GetProperty("arg1")?.GetValue(o);
T2 t2 = (T2)o.GetType().GetProperty("arg2")?.GetValue(o);
if (e != null) e(t1, t2);
}), new { action = action, arg1 = arg1, arg2 = arg2 });
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 1b21927e111c22c4b93513b595e9f4a2
guid: 8e91098b3165d6b478e1a1ab72aeb94c
MonoImporter:
externalObjects: {}
serializedVersion: 2
@@ -0,0 +1,105 @@
using System;
using System.IO;
/// <summary>
/// Socket通信过程中的数据包 处理具体拆包装包逻辑
/// </summary>
public class SocketDataPack
{
// 消息:数据总长度(4byte) + 数据类型(2byte) + 数据(N byte)
public const int HEAD_DATA_LEN = 4;
public const int HEAD_TYPE_LEN = 2;
public static int HeadLen
{
get { return HEAD_DATA_LEN + HEAD_TYPE_LEN; }
}
/// <summary>
/// 数据包类型
/// </summary>
public UInt16 Type;
/// <summary>
/// 数据包数据
/// </summary>
public byte[] Data;
public byte[] Buff;
public int BuffLength
{
get { return Buff.Length; }
}
public int DataLength
{
get { return Data.Length; }
}
public SocketDataPack()
{
}
public SocketDataPack(UInt16 type, byte[] data)
{
Type = type;
Data = data;
Buff = GetBuff(Type, Data);
}
public static byte[] GetBuff(UInt16 type, byte[] data)
{
byte[] buff = new byte[data.Length + HeadLen];
byte[] temp;
temp = BitConverter.GetBytes(buff.Length);
Array.Copy(temp, 0, buff, 0, HEAD_DATA_LEN);
temp = BitConverter.GetBytes(type);
Array.Copy(temp, 0, buff, HEAD_DATA_LEN, HEAD_TYPE_LEN);
Array.Copy(data, 0, buff, HeadLen, data.Length);
return buff;
}
public static SocketDataPack Unpack(byte[] buff)
{
try
{
if (buff.Length < HeadLen)
{
// 头部没取完则返回
return null;
}
byte[] temp;
// 取数据长度
temp = new byte[HEAD_DATA_LEN];
Array.Copy(buff, 0, temp, 0, HEAD_DATA_LEN);
int buffLength = BitConverter.ToInt32(temp, 0);
if (buffLength <= 0) return null;
if (buffLength > buff.Length)
{
// 数据没取完
return null;
}
int dataLength = buffLength - HeadLen;
// 取数据类型
temp = new byte[HEAD_TYPE_LEN];
Array.Copy(buff, HEAD_DATA_LEN, temp, 0, HEAD_TYPE_LEN);
UInt16 dataType = BitConverter.ToUInt16(temp, 0);
// 取数据
byte[] data = new byte[dataLength];
Array.Copy(buff, HeadLen, data, 0, dataLength);
var dataPack = new SocketDataPack(dataType, data);
// UnityEngine.Debug.LogFormat("buffLen:{0} type:{1} dataLength:{2}", buffLength, dataType, data.Length);
return dataPack;
}
catch
{
// 存在不完整数据解包 则返回null
return null;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5e0c4c6bf95d3324a975f6ce0cdee4c4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,14 @@
/// <summary>
/// 网络事件协议ID枚举
/// </summary>
public enum SocketEvent
{
ClientHead = 0x0001, //心跳包
ClientDisconn = 0x0002, //客户端主动断开
ServerKickout = 0x0003, //服务端踢出
ServerMessage = 0x0004, //服务端发送消息
ClientMessage = 0x0005, //客户端发送消息
ScTest = 0x1001, //测试用
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b1c8d60cbbc2c7547827955a371fda00
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,349 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Timers;
using UnityEngine;
public class SocketInfo
{
public string IP;
public Thread ReceiveThread;
public long HeadTime;
}
/// <summary>
/// Socket服务端
/// </summary>
public class SocketServer
{
/// <summary>
/// 主线程
/// </summary>
private readonly SynchronizationContext _mainThread;
private const int HEAD_TIMEOUT = 5000; // 心跳超时 毫秒
private const int HEAD_CHECKTIME = 5000; // 心跳包超时检测 毫秒
public readonly Dictionary<Socket, SocketInfo> ClientInfoDic = new Dictionary<Socket, SocketInfo>();
private readonly Socket _server;
private System.Timers.Timer _headCheckTimer;
private readonly DataBuffer _dataBuffer = new DataBuffer();
public event Action<Socket> OnConnect; //客户端建立连接回调
public event Action<Socket> OnDisconnect; // 客户端断开连接回调
public event Action<Socket, SocketDataPack> OnReceive; // 接收报文回调
public event Action<Socket, SocketDataPack> OnSend; // 发送报文回调
// 目前捕获异常将触发OnDisconnect回调 暂不单独处理
// public event Action<SocketException> OnError; // 异常捕获回调
private bool _isValid = true;
public SocketServer(string ip, int port)
{
OnConnect += (client) =>
{
UnityEngine.Debug.LogFormat("UnityEvo:连接成功 >> IP:{0}", client.LocalEndPoint.ToString());
};
OnDisconnect += (client) =>
{
if(ClientInfoDic.TryGetValue(client, out var value))
Debug.LogFormat("UnityEvo:连接断开 >> IP:{0}", value.IP);
};
_mainThread = SynchronizationContext.Current;
_server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ipAddress = IPAddress.Parse(ip); //解析IP地址
_server.Bind(new IPEndPoint(ipAddress, port)); //绑定IP地址:端口
_server.Listen(10); //设定最多10个排队连接请求
// 启动线程监听连接
var connectThread = new Thread(ListenClientConnect);
connectThread.Start();
// 心跳包定时检测
_headCheckTimer = new System.Timers.Timer(HEAD_CHECKTIME);
_headCheckTimer.AutoReset = true;
_headCheckTimer.Elapsed += delegate(object sender, ElapsedEventArgs args) { CheckHeadTimeOut(); };
_headCheckTimer.Start();
Debug.Log($"SocketServer Start: {ip}:{port}");
}
/// <summary>
/// 监听客户端连接
/// </summary>
private void ListenClientConnect()
{
while (true)
{
try
{
if (!_isValid) break;
Socket client = _server.Accept();
IPEndPoint ipEndPoint = (IPEndPoint)client.RemoteEndPoint;
Thread receiveThread = new Thread(ReceiveEvent);
ClientInfoDic.Add(client,
new SocketInfo() { IP = ipEndPoint.Address.ToString(), ReceiveThread = receiveThread, HeadTime = GetNowTime() });
receiveThread.Start(client);
PostMainThreadAction<Socket>(OnConnect, client);
}
catch
{
break;
}
}
}
/// <summary>
/// 获取当前时间戳
/// </summary>
/// <returns></returns>
private long GetNowTime()
{
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
return Convert.ToInt64(ts.TotalMilliseconds);
}
public void Send(Socket client, UInt16 e, byte[] buff = null, Action<SocketDataPack> onTrigger = null)
{
SendMessage(client, e, buff, onTrigger);
}
private void SendMessage(Socket client, UInt16 e, byte[] buff = null, Action<SocketDataPack> onTrigger = null)
{
buff = buff ?? new byte[] { };
var dataPack = new SocketDataPack(e, buff);
var data = dataPack.Buff;
try
{
client.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback((asyncSend) =>
{
Socket c = (Socket)asyncSend.AsyncState;
c.EndSend(asyncSend);
PostMainThreadAction<SocketDataPack>(onTrigger, dataPack);
PostMainThreadAction<Socket, SocketDataPack>(OnSend, client, dataPack);
}), client);
}
catch (SocketException ex)
{
CloseClient(client);
// onError(ex);
}
}
/// <summary>
/// 线程内接收数据的函数
/// </summary>
private void ReceiveEvent(object client)
{
Socket tsocket = (Socket)client;
while (true)
{
if (!_isValid) return;
if (!ClientInfoDic.ContainsKey(tsocket))
{
return;
}
try
{
byte[] rbytes = new byte[8 * 1024];
int len = tsocket.Receive(rbytes);
if (len > 0)
{
_dataBuffer.AddBuffer(rbytes, len); // 将收到的数据添加到缓存器中
if (_dataBuffer.TryUnpack(out var dataPack)) // 尝试解包
{
if (dataPack.Type == (UInt16)SocketEvent.ClientHead)
{
// 接收到心跳包
ReceiveHead(tsocket);
}
else if (dataPack.Type == (UInt16)SocketEvent.ClientDisconn)
{
// 客户端断开连接
CloseClient(tsocket);
}
else if (dataPack.Type == (UInt16)SocketEvent.ClientMessage)
{
// 收到消息
PostMainThreadAction<Socket, SocketDataPack>(OnReceive, tsocket, dataPack);
}
}
}
else
{
if (tsocket.Poll(-1, SelectMode.SelectRead))
{
CloseClient(tsocket);
return;
}
}
}
catch (SocketException ex)
{
CloseClient(tsocket);
// onError(ex);
return;
}
}
}
/// <summary>
/// 接收到心跳包
/// </summary>
private void ReceiveHead(Socket client)
{
SocketInfo info;
if (ClientInfoDic.TryGetValue(client, out info))
{
long now = GetNowTime();
long offset = now - info.HeadTime;
UnityEngine.Debug.Log("更新心跳时间戳 >>>" + now + " 间隔>>>" + offset);
if (offset > HEAD_TIMEOUT)
{
// 心跳包收到但超时逻辑
}
info.HeadTime = now;
}
}
/// <summary>
/// 检测心跳包超时
/// </summary>
private void CheckHeadTimeOut()
{
var tempList = new List<Socket>();
foreach (var socket in ClientInfoDic.Keys)
{
tempList.Add(socket);
}
foreach (var socket in tempList)
{
var info = ClientInfoDic[socket];
long now = GetNowTime();
long offset = now - info.HeadTime;
if (offset > HEAD_TIMEOUT)
{
// 心跳包超时
KickOut(socket);
}
}
}
public void KickOut(Socket client)
{
// 踢出连接
Send(client, (UInt16)SocketEvent.ServerKickout, null, (dataPack) => { CloseClient(client); });
}
public void KickOutAll()
{
var tempList = new List<Socket>();
foreach (var socket in ClientInfoDic.Keys)
{
tempList.Add(socket);
}
foreach (var socket in tempList)
{
KickOut(socket);
}
}
/// <summary>
/// 清理客户端连接
/// </summary>
/// <param name="client"></param>
private void CloseClient(Socket client)
{
PostMainThreadAction<Socket>((socket) =>
{
if (OnDisconnect != null) OnDisconnect(socket);
ClientInfoDic.Remove(socket);
socket.Close();
}, client);
}
/// <summary>
/// 关闭
/// </summary>
public void Close()
{
if (!_isValid) return;
_isValid = false;
// if (_connectThread != null) _connectThread.Abort();
var tempList = new List<Socket>();
foreach (var socket in ClientInfoDic.Keys)
{
tempList.Add(socket);
}
foreach (var socket in tempList)
{
CloseClient(socket);
}
if (_headCheckTimer != null)
{
_headCheckTimer.Stop();
_headCheckTimer = null;
}
_server.Close();
}
// /// <summary>
// /// 错误回调
// /// </summary>
// /// <param name="e"></param>
// private void onError(SocketException ex)
// {
// PostMainThreadAction<SocketException>(OnError, ex);
// }
// <summary>
/// 通知主线程回调
/// </summary>
private void PostMainThreadAction(Action action)
{
_mainThread.Post(new SendOrPostCallback((o) =>
{
Action e = (Action)o.GetType().GetProperty("action")?.GetValue(o);
if (e != null) e();
}), new { action = action });
}
private void PostMainThreadAction<T>(Action<T> action, T arg1)
{
_mainThread.Post(new SendOrPostCallback((o) =>
{
Action<T> e = (Action<T>)o.GetType().GetProperty("action")?.GetValue(o);
T t1 = (T)o.GetType().GetProperty("arg1")?.GetValue(o);
if (e != null) e(t1);
}), new { action = action, arg1 = arg1 });
}
public void PostMainThreadAction<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2)
{
_mainThread.Post(new SendOrPostCallback((o) =>
{
Action<T1, T2> e = (Action<T1, T2>)o.GetType().GetProperty("action")?.GetValue(o);
T1 t1 = (T1)o.GetType().GetProperty("arg1")?.GetValue(o);
T2 t2 = (T2)o.GetType().GetProperty("arg2")?.GetValue(o);
if (e != null) e(t1, t2);
}), new { action = action, arg1 = arg1, arg2 = arg2 });
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a2c6448e77af258458f5959d7e15c022
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,51 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SocketClientMain : MonoBehaviour
{
private string ip = "127.0.0.1";
private int port = 8080;
private SocketClient _client;
private void Awake()
{
_client = new SocketClient("192.168.31.67", 6854);
_client.Connect(() =>
{
UnityEngine.Debug.Log("连接成功");
// _client.DisConnect();
}, () => { UnityEngine.Debug.Log("连接失败"); });
}
public void StartConnect(string ip = "", int port = 0)
{
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
var bytes = System.Text.Encoding.UTF8.GetBytes("我是测试数据");
_client.Send((System.UInt16)SocketEvent.ScTest, bytes);
}
if (Input.GetKeyDown(KeyCode.D))
{
_client.DisConnect();
}
}
private void OnDestroy()
{
// 注意由于Unity编译器环境下,游戏开启/关闭只影响主线程的开关,游戏关闭回调时需要通过Close函数来关闭服务端/客户端的线程。
if (_client != null)
{
_client.Close();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 052b8595da3036e4a94eabc9a5a2b95b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,45 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SocketServerMain : MonoBehaviour
{
SocketServer _server;
private void Awake()
{
_server = new SocketServer("192.168.31.67", 6854);
_server.OnReceive += (client, data) =>
{
UnityEngine.Debug.LogFormat("[{0}]接收到数据>>>{1} {2}", client.LocalEndPoint.ToString(), (SocketEvent)data.Type, data.Buff.Length);
switch ((SocketEvent)data.Type)
{
case SocketEvent.ScTest:
UnityEngine.Debug.LogFormat("接收到测试数据 >>> {0}", System.Text.Encoding.UTF8.GetString(data.Data));
break;
}
};
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
// 踢出连接
foreach (var item in _server.ClientInfoDic.Keys)
{
_server.KickOutAll();
}
}
}
private void OnDestroy()
{
// 注意由于Unity编译器环境下,游戏开启/关闭只影响主线程的开关,游戏关闭回调时需要通过Close函数来关闭服务端/客户端的线程。
if (_server != null)
{
_server.Close();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6b72333f2bc06a7428fb3c0eadeed0d1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,5 +1,5 @@
{
"name": "stary.main",
"name": "stary.hotfixupdate.main",
"rootNamespace": "",
"references": [
"GUID:e34a5702dd353724aa315fb8011f08c3",
@@ -14,7 +14,8 @@
"GUID:66fdc96a271fc954e9da30c76a486d9c",
"GUID:6a5d7223300a2ef48aa366288a446472",
"GUID:10c9b58b77ad42b4193e2a393b1a9899",
"GUID:fad681b9bfe621d4fa07f4f69c311443"
"GUID:fad681b9bfe621d4fa07f4f69c311443",
"GUID:ff70fce64a3314305977bdf5610ed86b"
],
"includePlatforms": [],
"excludePlatforms": [],
@@ -13,7 +13,8 @@ MonoBehaviour:
m_Name: HotfixMainResDomain
m_EditorClassIdentifier: com.stary.evo.runtime:Stary.Evo:HotfixMainResDomain
hotfixMainResDomainEntity:
ipconfig: http://192.168.31.67:9527
ipconfig: http://192.168.31.100:9527
mainDomainVersion:
username: admin2023
password: admin@2023
productName: XOSMOPlug_inLibrary
productName: yuhanghealthhall
-140
View File
@@ -1,140 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 79b808b96820ad546951a6859e2a99be, type: 3}
m_Name: PointGatherData
m_EditorClassIdentifier:
ZoneDatas:
- id: 2
name: X_02
desc: "\u751F\u547D\u5065\u5EB7\u533A"
spriteName: ui_zone1_shengmingjiankangqu
position: {x: -12.82, y: 0, z: 5.85}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
pointDatas:
- id: 1
name: X_02_01
position: {x: 0, y: 0, z: 0}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
desc: "\u5168\u751F\u547D\u5468\u671F"
- id: 2
name: X_02_02
position: {x: 0, y: 0, z: 0}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
desc: "\u4EBA\u4F53\u516B\u5927\u7CFB\u7EDF"
- id: 3
name: X_03
desc: "\u5065\u5EB7\u5F71\u54CD\u56E0\u7D20\u533A"
spriteName: ui_zone2_jiankangyingxiangyinsuqu
position: {x: -10.44, y: 0, z: 5.85}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
pointDatas:
- id: 1
name: X_03_01_01
position: {x: 0, y: 0, z: 0}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
desc: "\u5BA4\u5916\u5927\u73AF\u5883\u5F71\u54CD\u56E0\u7D20"
- id: 2
name: X_03_01_02
position: {x: 0, y: 0, z: 0}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
desc: "\u53A8\u623F\u73AF\u5883\u5F71\u54CD\u56E0\u7D20"
- id: 4
name: X_04
desc: "\u751F\u547D\u9632\u62A4\u533A"
spriteName: ui_zone3_shengmingfanghuqu
position: {x: -7.65, y: 0, z: 5.85}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
pointDatas:
- id: 3
name: X_03_02_01
position: {x: 0, y: 0, z: 0}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
desc: "\u542C\u529B\u5065\u5EB7"
- id: 4
name: X_03_02_02
position: {x: 0, y: 0, z: 0}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
desc: "\u89C6\u529B\u5065\u5EB7"
- id: 5
name: X_03_02_03
position: {x: 0, y: 0, z: 0}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
desc: "\u53E3\u8154\u5065\u5EB7"
- id: 4
name: X_05
desc: "\u5065\u5EB7\u7D20\u517B\u533A"
spriteName: ui_zone4_jiankangsuyangqu
position: {x: -4.54, y: 0, z: 5.85}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
pointDatas:
- id: 1
name: X_04_01
position: {x: 0, y: 0, z: 0}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
desc: "\u80A5\u80D6\u5371\u9669\u56E0\u7D20\uFF08\u6162\u75C5\uFF09"
- id: 2
name: X_04_02
position: {x: 0, y: 0, z: 0}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
desc: "\u4F20\u67D3\u75C5"
- id: 3
name: X_04_03
position: {x: 0, y: 0, z: 0}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
desc: "\u75C5\u5A92\u751F\u7269\u751F\u7269\u4F20\u67D3\u75C5"
- id: 4
name: X_04_04
position: {x: 0, y: 0, z: 0}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
desc: "\u72C2\u72AC\u75C5"
- id: 5
name: X_04_05
position: {x: 0, y: 0, z: 0}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
desc: "\u5FAE\u751F\u7269\u5927\u4F5C\u6218"
- id: 6
name: X_06
desc: "\u5065\u5EB7\u751F\u6D3B\u65B9\u5F0F\u533A"
spriteName: ui_zone5_jiankangshenghuofangshiqu
position: {x: -1.04, y: 0, z: 5.85}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
pointDatas:
- id: 1
name: X_05_01
position: {x: 0, y: 0, z: 0}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
desc: "\u60C5\u7EEA\u6025\u6551\u7BB1"
- id: 1
name: ' X_06_01'
position: {x: 0, y: 0, z: 0}
rotation: {x: -0, y: 0, z: 0}
scale: {x: 1, y: 1, z: 1}
desc: "\u996E\u9152\u5371\u5BB3"
targetGameObject: {fileID: 0}
@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 17ac95220ddc8a449804eb0969d6297b
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,341 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &4567782109512309038
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4160048210915643038}
- component: {fileID: 825865997535607830}
- component: {fileID: 2727479573709789859}
- component: {fileID: 635877910647768279}
m_Layer: 0
m_Name: ProgressBarPanel
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4160048210915643038
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4567782109512309038}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 2}
m_LocalScale: {x: 0.0042, y: 0.0042, z: 0.0042}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 3019045779189427444}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 200, y: 200}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!223 &825865997535607830
Canvas:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4567782109512309038}
m_Enabled: 1
serializedVersion: 3
m_RenderMode: 2
m_Camera: {fileID: 0}
m_PlaneDistance: 100
m_PixelPerfect: 0
m_ReceivesEvents: 1
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0
m_AdditionalShaderChannelsFlag: 0
m_SortingLayerID: 0
m_SortingOrder: 0
m_TargetDisplay: 0
--- !u!114 &2727479573709789859
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4567782109512309038}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
m_Name:
m_EditorClassIdentifier:
m_UiScaleMode: 0
m_ReferencePixelsPerUnit: 100
m_ScaleFactor: 1
m_ReferenceResolution: {x: 800, y: 600}
m_ScreenMatchMode: 0
m_MatchWidthOrHeight: 0
m_PhysicalUnit: 3
m_FallbackScreenDPI: 96
m_DefaultSpriteDPI: 96
m_DynamicPixelsPerUnit: 1
m_PresetInfoIsWorld: 1
--- !u!114 &635877910647768279
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4567782109512309038}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreReversedGraphics: 1
m_BlockingObjects: 0
m_BlockingMask:
serializedVersion: 2
m_Bits: 55
--- !u!1 &5926684121426958632
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3019045779189427444}
- component: {fileID: 5861308620308585849}
- component: {fileID: 4575314728117427798}
m_Layer: 0
m_Name: Fill
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3019045779189427444
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5926684121426958632}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.2, y: 0.2, z: 0.2}
m_ConstrainProportionsScale: 1
m_Children:
- {fileID: 4478887775470361833}
- {fileID: 7061587243420078504}
m_Father: {fileID: 4160048210915643038}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &5861308620308585849
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5926684121426958632}
m_CullTransparentMesh: 1
--- !u!114 &4575314728117427798
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5926684121426958632}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10913, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 3
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &5969878386391244675
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4478887775470361833}
- component: {fileID: 407484292974360126}
- component: {fileID: 5313000614588967778}
m_Layer: 0
m_Name: FillMessage
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4478887775470361833
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5969878386391244675}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3019045779189427444}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 135.3}
m_SizeDelta: {x: 0, y: -129.5}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &407484292974360126
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5969878386391244675}
m_CullTransparentMesh: 1
--- !u!114 &5313000614588967778
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5969878386391244675}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 40
m_FontStyle: 1
m_BestFit: 0
m_MinSize: 1
m_MaxSize: 60
m_Alignment: 4
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: "\u89E3\u538B\u4E2D"
--- !u!1 &8961881545791775599
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7061587243420078504}
- component: {fileID: 1247723116626350990}
- component: {fileID: 5156535828674891212}
m_Layer: 0
m_Name: FillText
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7061587243420078504
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8961881545791775599}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3019045779189427444}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &1247723116626350990
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8961881545791775599}
m_CullTransparentMesh: 1
--- !u!114 &5156535828674891212
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8961881545791775599}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0, g: 0, b: 0, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 40
m_FontStyle: 1
m_BestFit: 0
m_MinSize: 1
m_MaxSize: 60
m_Alignment: 4
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: 100%
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 0ca468eb0fa7093438504ea17e009da0
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,79 +0,0 @@
// using UnityEditor;
// using UnityEngine;
//
// namespace Stary.Evo
// {
// [CustomEditor(typeof(DomainBase), true)]
// public class DomainBaseEditor : UnityEditor.Editor
// {
// //定义序列化属性
// // private SerializedProperty intValue;
// // private SerializedProperty floatValue;
// // private SerializedProperty stringValue;
// // private SerializedProperty boolValue;
// // private SerializedProperty vector3Value;
// // private SerializedProperty enumValue;
// // private SerializedProperty colorValue;
// // private SerializedProperty textureValue;
// /// <summary>
// /// 序列化属性,在OnEnable中获取
// /// </summary>
// [HideInInspector]
// private SerializedProperty domainConfig;
// [HideInInspector]
// private SerializedProperty domainName;
//
// private UnityEditor.Editor cacheEditor;
// private void OnEnable()
// {
// domainConfig = serializedObject.FindProperty("domainConfig");
// if (!Application.isPlaying)
// {
//
// domainName = serializedObject.FindProperty("DomainName");
// domainConfig.objectReferenceValue =
// AssetDatabase.LoadAssetAtPath<DomainConfig>(
// $"Assets/Domain/{domainName.stringValue}/AddressableRes/Config/DomainConfig.asset");
// }
// //通过名字查找被序列化属性。
// // intValue = serializedObject.FindProperty("intValue");
// // floatValue = serializedObject.FindProperty("floatValue");
// // stringValue = serializedObject.FindProperty("stringValue");
// // boolValue = serializedObject.FindProperty("boolValue");
// // vector3Value = serializedObject.FindProperty("vector3Value");
// // enumValue = serializedObject.FindProperty("enumValue");
// // colorValue = serializedObject.FindProperty("colorValue");
// // textureValue = serializedObject.FindProperty("textureValue");
// }
//
// public override void OnInspectorGUI()
// {
// //表示更新序列化物体
// serializedObject.Update();
//
// // EditorGUILayout.PropertyField(domainConfig,new GUIContent("111"),true);
//
//
// var data = ((DomainConfig)domainConfig.objectReferenceValue);
// if (data != null)
// {
// //创建TestClass的Editor
// if (cacheEditor == null)
// cacheEditor = UnityEditor. Editor.CreateEditor(data);
// cacheEditor.OnInspectorGUI();
// }
//
//
// // EditorGUILayout.PropertyField(intValue);
// // EditorGUILayout.PropertyField(floatValue);
// // EditorGUILayout.PropertyField(stringValue);
// // EditorGUILayout.PropertyField(boolValue);
// // EditorGUILayout.PropertyField(vector3Value);
// // EditorGUILayout.PropertyField(enumValue);
// // EditorGUILayout.PropertyField(colorValue);
// // EditorGUILayout.PropertyField(textureValue);
// //应用修改的属性值,不加的话,Inspector面板的值修改不了
// serializedObject.ApplyModifiedProperties();
// }
// }
// }
@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 4ca49f66bd64466d8cf1ede3acb36592
timeCreated: 1744097384

Some files were not shown because too many files have changed in this diff Show More