Compare commits

..

85 Commits

Author SHA1 Message Date
ALEXTANG
6a87db76ee 优化局部单位事件分发器ActorEventDispatcher,EventRegInfo池化
优化局部单位事件分发器ActorEventDispatcher,EventRegInfo池化
2023-12-15 15:11:12 +08:00
ALEXTANG
3a6170dca6 Update UIWidget.cs 2023-12-15 14:25:41 +08:00
ALEXTANG
9d137d613a 修正Utility.Unity注入非Mono的LateUpdate时序问题
修正Utility.Unity注入非Mono的LateUpdate时序问题
2023-12-15 14:15:08 +08:00
ALEXTANG
ba77ec6b45 Update EventInterfaceGenerate.cs 2023-12-14 15:07:04 +08:00
ALEXTANG
b661da68f2 Update EventInterfaceGenerate.cs 2023-12-14 10:12:56 +08:00
ALEXTANGXIAO
e1040110bb 升级拓展GameEvent,支持基于Interface的方法调用抛出事件,以及自动化根据声明的Interface来生成实现代码。
升级拓展GameEvent,支持基于Interface的方法调用抛出事件,以及自动化根据声明的Interface来生成实现代码。
2023-12-13 23:27:54 +08:00
ALEXTANGXIAO
2d53fa1687 升级HybridCLR 4.0.13=>4.0.14
升级HybridCLR 4.0.13=>4.0.14
2023-12-13 19:27:05 +08:00
ALEXTANG
c4ef07f13e Update UnityExtension.cs 2023-12-12 13:00:53 +08:00
ALEXTANG
1f2d99ddc9 修正UIWindow资源句柄时序导致UI同步显示失效的问题。 2023-12-08 10:38:19 +08:00
ALEXTANG
edf4925a7a UIWidget增加Visible设置
UIWidget增加Visible设置
2023-12-07 16:32:54 +08:00
ALEXTANG
5d67238c8f 统一封装对shader的管理和示例。
统一封装对shader的管理和示例。
2023-12-07 10:55:50 +08:00
ALEXTANG
6cfd352482 关闭ResourceCacheMgr测试日志
关闭ResourceCacheMgr测试日志
2023-12-07 10:30:50 +08:00
ALEXTANG
40373c473d 修改通过Tag加载资源对象集合接口。(Operation需要自行管理生命周期释放)
修改通过Tag加载资源对象集合接口。(Operation需要自行管理生命周期释放)
2023-12-07 10:27:17 +08:00
ALEXTANG
d799f9fdf0 优化资源引用类与资源分组类。 2023-12-06 17:57:54 +08:00
ALEXTANG
15735c3d2d 修正循环列表GetItem,增加普通列表组件。 2023-12-06 14:41:31 +08:00
ALEXTANG
818a74f437 释放资源前判断资源合法性 2023-12-06 11:35:33 +08:00
ALEXTANG
f248757401 消除Editor引用隐患
消除Editor引用隐患
2023-12-01 17:41:43 +08:00
ALEXTANG
6ada0e7de7 移除测试日志 2023-12-01 17:18:13 +08:00
ALEXTANG
7ea472f97e 修正日志重定向下层日志跳转功能
修正日志重定向下层日志跳转功能
2023-12-01 10:45:57 +08:00
ALEXTANG
fb8528ff52 音频代理类增加暂停和取消暂停接口。
音频代理类增加暂停和取消暂停接口。
2023-11-30 16:17:35 +08:00
ALEXTANG
e3ac92ef46 修正音频模块回收池
修正音频模块回收池
2023-11-30 15:30:01 +08:00
ALEXTANG
be6a19c26a 修正Sound轨道不受SoundVolume的影响,调整AudioMixer音频Group命名
修正Sound轨道不受SoundVolume的影响,调整AudioMixer音频Group命名
2023-11-30 13:18:20 +08:00
ALEXTANG
e7f0636f30 拓展细分内存对象生命周期。
拓展细分内存对象生命周期。
2023-11-30 00:13:23 +08:00
ALEXTANG
fb38e96e9e 修正循环列表根据下标获取索引Item
修正循环列表根据下标获取索引Item
2023-11-29 19:48:18 +08:00
ALEXTANG
dd658c7e1d 对象池支持ShutDown
对象池支持ShutDown
2023-11-29 15:39:44 +08:00
ALEXTANG
4d7cb7641d 修正LoadGameObjectAsync接口传参
修正LoadGameObjectAsync接口传参
2023-11-29 15:24:02 +08:00
ALEXTANG
ae075b1fad 修正ProcedureDownloadFile更新时网速计算
修正ProcedureDownloadFile更新时网速计算
2023-11-29 12:55:36 +08:00
ALEXTANG
02827ce3b8 优化/新增超牛逼且很方便使用的对象池。
优化/新增超牛逼且很方便使用的对象池。
2023-11-28 19:36:26 +08:00
ALEXTANG
1a0e3f91e0 优化/新增超牛逼且很方便使用的对象池。
优化/新增超牛逼且很方便使用的对象池。
2023-11-28 15:27:34 +08:00
ALEXTANG
6d376b0e07 增加安全定时器GameTimerTick
增加安全定时器GameTimerTick
2023-11-28 14:25:25 +08:00
ALEXTANGXIAO
cb73c9a9eb 升级HybridCLR 4.0.12=>4.0.13 强烈建议升级,修复了若干bug
升级HybridCLR 4.0.12=>4.0.13 强烈建议升级,修复了若干bug
2023-11-27 22:47:30 +08:00
ALEXTANG
7dda73a7ac 增加泛用加载资源并绑定资源引用到GameObject上。
增加泛用加载资源并绑定资源引用到GameObject上。
2023-11-23 13:34:33 +08:00
ALEXTANG
9bcb636ed7 修正SetSprite接口绑定资源引用关系,避免0引用导致AssetBundle被释放使图片丢失。
修正SetSprite接口绑定资源引用关系,避免0引用导致AssetBundle被释放使图片丢失。
2023-11-23 11:44:43 +08:00
ALEXTANG
bd0cfc5577 增加计时器TimerModule。
增加计时器TimerModule。
2023-11-22 12:20:08 +08:00
ALEXTANG
ff613e4130 更新修复导入图集初始化信息不全的bug
更新修复导入图集初始化信息不全的bug
2023-11-20 17:49:08 +08:00
ALEXTANG
fea1ae2278 Merge pull request #59 from AlanWeekend/main
优化分包资源下载逻辑,统一WebGL平台与其他平台的远程热更资源引用方式
2023-11-20 11:56:04 +08:00
Weekend
866c440479 add:初始化Package流程中增加webgl平台更新update配置 2023-11-19 02:01:15 +08:00
Weekend
48ff839d64 Merge branch 'main' of https://github.com/AlanWeekend/TEngine 2023-11-19 01:43:59 +08:00
Weekend
69be3cfa23 update:统一WebGL平台与其他平台的远程热更资源引用方式 2023-11-19 01:41:47 +08:00
Weekend
5f2c27ecf0 Merge branch 'ALEXTANGXIAO:main' into main 2023-11-18 21:46:00 +08:00
Weekend
ef17cd851b add:优化分包下载 2023-11-18 21:44:24 +08:00
ALEXTANG
f186d6b058 Merge pull request #58 from AlanWeekend/main
增加初始化指定资源包操作,单独下载指定地址的资源文件
2023-11-16 10:52:14 +08:00
Weekend
4385123976 add:设置图片资源支持从指定资源包中加载 2023-11-15 15:39:04 +08:00
Weekend
1334dc30f9 Merge branch 'main' of https://github.com/AlanWeekend/TEngine 2023-11-15 15:15:11 +08:00
Weekend
af822add2c add:下载资源包中指定地址的资源文件 2023-11-15 15:14:47 +08:00
Weekend
ffb1f214ad Merge branch 'ALEXTANGXIAO:main' into main 2023-11-15 14:41:45 +08:00
Weekend
213aaed426 add:初始化指定资源包 2023-11-15 14:40:35 +08:00
ALEXTANG
623d301e41 修正异步创建子Widget时SetParent的问题
修正异步创建子Widget时SetParent的问题
2023-11-15 14:06:49 +08:00
ALEXTANG
2870383afe Resource模块支持操作指定资源包的资源
Resource模块支持操作指定资源包的资源
2023-11-15 10:48:28 +08:00
ALEXTANG
1ad435958a Merge pull request #57 from AlanWeekend/main
add:Resource模块支持操作指定资源包的资源
2023-11-15 10:08:53 +08:00
Weekend
386787c6ec add:Resource模块支持操作指定资源包的资源 2023-11-15 00:14:07 +08:00
ALEXTANG
cd65dde4c3 ReleasePreLoadAssets修正在webgl模式下Shutdown的问题
ReleasePreLoadAssets修正在webgl模式下Shutdown的问题
2023-11-14 16:00:09 +08:00
ALEXTANG
8321e77421 Merge pull request #56 from AlanWeekend/main
fixed:looplistitem重复赋值问题
2023-11-13 13:09:25 +08:00
Weekend
1b6f80952e fixed:looplistitem重复赋值问题
fixed:looplistitem重复赋值问题
2023-11-12 19:49:02 +08:00
ALEXTANG
b52e655c30 更正错误注释
更正错误注释
2023-11-07 11:04:59 +08:00
ALEXTANG
8c0df95626 修正CancellationTokenSource重复Dispose问题
修正CancellationTokenSource重复Dispose问题
2023-11-03 16:58:42 +08:00
ALEXTANG
0d1e308f1c Update ResourceModule.cs 2023-11-03 10:07:25 +08:00
ALEXTANG
f8797538fd Update UIBase.cs 2023-11-03 09:55:36 +08:00
ALEXTANG
fe4e168041 Update ProcedurePreload.cs 2023-11-02 15:35:01 +08:00
ALEXTANG
8e9047d3a3 基于资源框架实现对标签WEBGL_PRELOAD、PRELOAD的预加载。 接口GameModule.Resource.GetPreLoadAsset<T>(location)
基于资源框架实现对标签WEBGL_PRELOAD、PRELOAD的预加载。 接口GameModule.Resource.GetPreLoadAsset<T>(location)
2023-11-02 13:16:05 +08:00
ALEXTANG
04bfaeccc8 示例CLI工作流
示例CLI工作流
2023-11-02 12:55:27 +08:00
ALEXTANG
d66c823c15 更新优化启用UpdateData时UILoadUpdate时序的问题
更新优化启用UpdateData时UILoadUpdate时序的问题
2023-11-02 11:48:47 +08:00
ALEXTANG
0ec1424f0a 升级HybridCLR 4.0.11=>4.0.12
升级HybridCLR 4.0.11=>4.0.12
2023-11-02 11:12:56 +08:00
ALEXTANG
01f8eb9d57 升级HybridCLR 4.0.10=>4.0.11 强烈建议升级,修复了若干bug
升级HybridCLR 4.0.10=>4.0.11 强烈建议升级,修复了若干bug
2023-11-02 10:01:30 +08:00
ALEXTANG
f5021a9688 修正Utility生命周期注入OnDestroy和OnDrawGizmos无效的问题
修正Utility生命周期注入OnDestroy和OnDrawGizmos无效的问题
2023-10-31 12:45:40 +08:00
ALEXTANG
a632f7a5ad Merge pull request #55 from AlanWeekend/main
修复demo流程的下载网速显示错误问题
2023-10-30 23:48:17 +08:00
Weekend
5f968f4154 优化网速计算
优化网速计算
2023-10-30 23:47:07 +08:00
Weekend
c9fe83c2bd Merge branch 'main' of https://github.com/AlanWeekend/TEngine 2023-10-30 23:04:05 +08:00
Weekend
2c00d103cb Update ProcedureDownloadFile.cs
fixed:demo流程的下载网速错误显示问题
2023-10-30 23:04:01 +08:00
ALEXTANG
1d56437d9f Update Utility.Http.cs 2023-10-30 11:15:52 +08:00
ALEXTANG
69db1ff977 修正音频模块音频代理类赋值问题
#54 修正音频模块音频代理类赋值问题
2023-10-30 10:40:22 +08:00
ALEXTANG
48887b1aee 框架支持Shudown不关闭游戏重启
框架支持Shudown不关闭游戏重启
2023-10-27 13:18:12 +08:00
ALEXTANG
381ea8bb8d 增加支持ComponentAutoBindTool自动绑定UI元素组件。
增加支持ComponentAutoBindTool自动绑定UI元素组件。
2023-10-27 10:48:21 +08:00
ALEXTANG
7401edac15 移除UIElement代码绑定工具,为后续AutoBind代码绑定工具做准备
移除UIElement代码绑定工具,为后续AutoBind代码绑定工具做准备
2023-10-27 00:13:04 +08:00
ALEXTANG
b1c7f30be9 ErrorLogger屏幕显示开启与DebugModule关联。
ErrorLogger屏幕显示开启与DebugModule关联。
2023-10-26 23:45:26 +08:00
ALEXTANG
cfaf82a623 释放资源判断资源是否有效
释放资源判断资源是否有效
2023-10-26 14:07:38 +08:00
ALEXTANG
6992d12c6c 修复循环列表主动GetItemByIndex和GetItemList的问题
修复循环列表主动GetItemByIndex和GetItemList的问题
2023-10-26 13:12:35 +08:00
ALEXTANG
119d9683ad Merge pull request #53 from AlanWeekend/main
修复UIListBase和UILoopListWidget赋值问题
2023-10-26 12:49:00 +08:00
ALEXTANG
9478868513 修正HttpDispose
修正HttpDispose
2023-10-26 12:28:06 +08:00
ALEXTANG
6ed32082e1 修正HttpDispose
修正HttpDispose
2023-10-26 11:43:32 +08:00
ALEXTANG
6ee515e8c5 增加局部单位事件分发器的封装。
增加局部单位事件分发器的封装。
2023-10-26 10:28:05 +08:00
ALEXTANG
b839afa76a 释放资源判断资源是否有效、支持YooAssets日志重定向
释放资源判断资源是否有效、支持YooAssets日志重定向
2023-10-26 00:22:02 +08:00
Weekend
d9605b348a 修复UILoopListWidget赋值问题 2023-10-25 22:34:02 +08:00
Weekend
dfef83919c 修复UIListBase和UIUILoopListWidget赋值问题 2023-10-25 22:18:57 +08:00
ALEXTANG
f5f983f220 移除资源模块加载场景,加载场景统一走场景管理模块。增加场景加载进度回调。
移除资源模块加载场景,加载场景统一走场景管理模块。增加场景加载进度回调。
2023-10-23 17:01:06 +08:00
159 changed files with 6564 additions and 2275 deletions

View File

@@ -0,0 +1,9 @@
cd /d %~dp0
call path_define.bat
%UNITYEDITOR_PATH%/Unity.exe %WORKSPACE% -logFile %BUILD_LOGFILE% -executeMethod TEngine.ReleaseTools.AutomationBuildAndroid -quit -batchmode -CustomArgs:Language=en_US; %WORKSPACE%
@REM for /f "delims=[" %%i in (%BUILD_LOGFILE%) do echo %%i
pause

6
BuildCLI/path_define.bat Normal file
View File

@@ -0,0 +1,6 @@
cd /d %~dp0
set WORKSPACE=G:/github/TEngine/UnityProject
set UNITYEDITOR_PATH=G:/UnityEditor/2021.3.20f1c1/Editor
set BUILD_DLL_LOGFILE=./build_dll.log
set BUILD_LOGFILE=./build.log

View File

@@ -42,8 +42,16 @@ public class ConfigSystem : Singleton<ConfigSystem>
/// <returns>ByteBuf</returns>
private ByteBuf LoadByteBuf(string file)
{
var textAssets = GameModule.Resource.LoadAsset<TextAsset>(file);
byte[] ret = textAssets.bytes;
return new ByteBuf(ret);
TextAsset textAsset = null;
textAsset = GameModule.Resource.GetPreLoadAsset<TextAsset>(file);
if (textAsset != null)
{
return new ByteBuf(textAsset.bytes);
}
else
{
textAsset = GameModule.Resource.LoadAsset<TextAsset>(file);
return new ByteBuf(textAsset.bytes);
}
}
}

View File

@@ -0,0 +1,16 @@
[
{
"ResPath": "Assets/AssetRaw/Effects",
"CacheTime": 300,
"MaxPoolCnt": 30,
"PoolGoFreeTime": 300,
"MinPoolCnt": 0
},
{
"ResPath": "Assets/AssetRaw/PoolObjects/",
"CacheTime": 300,
"MaxPoolCnt": 30,
"PoolGoFreeTime": 300,
"MinPoolCnt": 0
}
]

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c9f7d9280641e9a4b87697ace96a4315
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 40a878a415f34e7a855fc4916bbb8e6b
timeCreated: 1702479104

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1dcaa491f139438dbd963d8bbf0dba85
timeCreated: 1702385397

View File

@@ -0,0 +1,9 @@
using System;
namespace GameLogic
{
[AttributeUsage(AttributeTargets.Class)]
public class BaseAttribute: Attribute
{
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 819c4eaddddd4646a100da2e3f19c3c7
timeCreated: 1702385397

View File

@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace GameLogic
{
public class CodeTypes
{
private static CodeTypes _instance;
public static CodeTypes Instance => _instance ??= new CodeTypes();
private readonly Dictionary<string, Type> _allTypes = new();
private readonly UnOrderMultiMapSet<Type, Type> _types = new();
public void Init(Assembly[] assemblies)
{
Dictionary<string, Type> addTypes = GetAssemblyTypes(assemblies);
foreach ((string fullName, Type type) in addTypes)
{
_allTypes[fullName] = type;
if (type.IsAbstract)
{
continue;
}
// 记录所有的有BaseAttribute标记的的类型
object[] objects = type.GetCustomAttributes(typeof(BaseAttribute), true);
foreach (object o in objects)
{
_types.Add(o.GetType(), type);
}
}
}
public HashSet<Type> GetTypes(Type systemAttributeType)
{
if (!_types.ContainsKey(systemAttributeType))
{
return new HashSet<Type>();
}
return _types[systemAttributeType];
}
public Dictionary<string, Type> GetTypes()
{
return _allTypes;
}
public Type GetType(string typeName)
{
return _allTypes[typeName];
}
public static Dictionary<string, Type> GetAssemblyTypes(params Assembly[] args)
{
Dictionary<string, Type> types = new Dictionary<string, Type>();
foreach (Assembly ass in args)
{
foreach (Type type in ass.GetTypes())
{
if (type.FullName != null)
{
types[type.FullName] = type;
}
}
}
return types;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 01fdfc4515314c579523ac3716005210
timeCreated: 1702385429

View File

@@ -0,0 +1,80 @@
using System.Collections.Generic;
namespace GameLogic
{
public class UnOrderMultiMapSet<TKey, TValue>: Dictionary<TKey, HashSet<TValue>>
{
public new HashSet<TValue> this[TKey t]
{
get
{
HashSet<TValue> set;
if (!TryGetValue(t, out set))
{
set = new HashSet<TValue>();
}
return set;
}
}
public Dictionary<TKey, HashSet<TValue>> GetDictionary()
{
return this;
}
public void Add(TKey t, TValue k)
{
HashSet<TValue> set;
TryGetValue(t, out set);
if (set == null)
{
set = new HashSet<TValue>();
base[t] = set;
}
set.Add(k);
}
public bool Remove(TKey t, TValue k)
{
HashSet<TValue> set;
TryGetValue(t, out set);
if (set == null)
{
return false;
}
if (!set.Remove(k))
{
return false;
}
if (set.Count == 0)
{
Remove(t);
}
return true;
}
public bool Contains(TKey t, TValue k)
{
HashSet<TValue> set;
TryGetValue(t, out set);
if (set == null)
{
return false;
}
return set.Contains(k);
}
public new int Count
{
get
{
int count = 0;
foreach (KeyValuePair<TKey,HashSet<TValue>> kv in this)
{
count += kv.Value.Count;
}
return count;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b798f0c1317c4caf9ace168f07b51d4f
timeCreated: 1702385485

View File

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

View File

@@ -0,0 +1,49 @@
using UnityEngine;
namespace TEngine
{
/// <summary>
/// 封装一个角色可能用到的各种shader场景。
/// </summary>
class ActorShaderGroup
{
private readonly TShader[] _allShader = new TShader[(int)ActorShaderEnvType.EnvTypeMax];
/// <summary>
/// 增加Shader到角色Shader分组。
/// </summary>
/// <param name="shaderType">当前环境类型。</param>
/// <param name="shader">TShader。</param>
public void AddShader(ActorShaderEnvType shaderType, TShader shader)
{
_allShader[(int)shaderType] = shader;
}
/// <summary>
/// 根据当前环境获取Shader。
/// </summary>
/// <param name="type">当前环境类型。</param>
/// <returns>TShader。</returns>
public TShader GetShader(ActorShaderEnvType type)
{
return _allShader[(int)type];
}
/// <summary>
/// 判断是否符合shader集合。
/// </summary>
/// <param name="shader">Shader实例。</param>
/// <returns>是否符合。</returns>
public bool IsMatch(Shader shader)
{
foreach (var dodShader in _allShader)
{
if (dodShader != null && dodShader.Shader == shader)
{
return true;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 79b6e5be73e14c929b6a3b4a980976ac
timeCreated: 1701916950

View File

@@ -0,0 +1,117 @@
using GameBase;
using UnityEngine;
namespace TEngine
{
enum ActorShaderGroupType
{
/// <summary>
/// 通用的角色shader
/// </summary>
Brdf = 0,
/// <summary>
/// 眼睛
/// </summary>
BrdfEye,
///可能后面扩展,比如特效的特殊角色材质
GroupMax,
}
enum ActorShaderEnvType
{
/// <summary>
/// 游戏内场景默认模型不带阴影不带xray不透明效果
/// </summary>
EnvNormal = 0,
/// <summary>
/// 展示场景
/// </summary>
EnvShow,
/// <summary>
/// 带阴影
/// </summary>
EnvShadow,
/// <summary>
/// 带xray默认也带Shadow
/// </summary>
EnvXRay,
/// <summary>
/// 透明渐隐效果
/// </summary>
EnvAlphaFade,
/// <summary>
/// 展示场景没shadow
/// </summary>
EnvShow_NoShadow,
EnvTypeMax
}
/// <summary>
/// 角色Shader管理器。
/// </summary>
class ActorShaderMgr : Singleton<ActorShaderMgr>
{
private readonly ActorShaderGroup[] _allShaderGroup = new ActorShaderGroup[(int)ActorShaderGroupType.GroupMax];
public ActorShaderMgr()
{
CreateBrdfShader();
}
/// <summary>
/// 根据当前Render查找角色的Shader分组。
/// </summary>
/// <param name="render">Render。</param>
/// <returns>角色的Shader分组。</returns>
public ActorShaderGroup FindShaderGroup(Renderer render)
{
var sharedMat = render.sharedMaterial;
if (sharedMat == null)
{
return null;
}
var shader = sharedMat.shader;
foreach (var group in _allShaderGroup)
{
if (group != null && group.IsMatch(shader))
{
return group;
}
}
return null;
}
private void CreateBrdfShader()
{
//通用的效果
var actorShader = new ActorShaderGroup();
actorShader.AddShader(ActorShaderEnvType.EnvNormal, new TShader("TEngine/Actor/ActorBrdf",shaderLocation:"ActorBrdf"));
actorShader.AddShader(ActorShaderEnvType.EnvShow, new TShader("TEngine/Actor/Show/ActorBrdf",shaderLocation:"ActorBrdf_Show"));
actorShader.AddShader(ActorShaderEnvType.EnvShow_NoShadow, new TShader("TEngine/Actor/Show/ActorBrdf_NoShadow",shaderLocation:"ActorBrdf_NoShadow"));
actorShader.AddShader(ActorShaderEnvType.EnvShadow, new TShader("TEngine/Actor/ActorBrdf",shaderLocation:"ActorBrdf_Normal"));
actorShader.AddShader(ActorShaderEnvType.EnvXRay, new TShader("TEngine/Actor/X-Ray",shaderLocation:"X-Ray"));
actorShader.AddShader(ActorShaderEnvType.EnvAlphaFade, new TShader("TEngine/Actor/Fade/ActorBrdf",shaderLocation:"ActorBrdf_Fade"));
_allShaderGroup[(int)ActorShaderGroupType.Brdf] = actorShader;
//眼睛效果
actorShader = new ActorShaderGroup();
actorShader.AddShader(ActorShaderEnvType.EnvNormal, new TShader("TEngine/Actor/ActorEye",shaderLocation:"ActorEye"));
actorShader.AddShader(ActorShaderEnvType.EnvShow, new TShader("TEngine/Actor/Show/ActorEye",shaderLocation:"ActorEye_Show", "MRT_DISABLE", "MRT_ENABLE"));
actorShader.AddShader(ActorShaderEnvType.EnvShadow, new TShader("TEngine/Actor/ActorEye",shaderLocation:"ActorEye"));
actorShader.AddShader(ActorShaderEnvType.EnvXRay, new TShader("TEngine/Actor/ActorEye",shaderLocation:"ActorEye"));
actorShader.AddShader(ActorShaderEnvType.EnvAlphaFade, new TShader("TEngine/Actor/Fade/ActorEye",shaderLocation:"ActorEye_Fade"));
_allShaderGroup[(int)ActorShaderGroupType.BrdfEye] = actorShader;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5a38b9b4bee84fabb1ef8db5292a6db6
timeCreated: 1701916853

View File

@@ -0,0 +1,154 @@
using System.Collections.Generic;
using UnityEngine;
namespace TEngine
{
/// <summary>
/// TShader scripts used for all rendering.
/// <remarks>统一封装对shader的管理。</remarks>
/// </summary>
public class TShader
{
private bool _loaded;
private Shader _shader;
private readonly string _shaderName;
private readonly string _shaderLocation;
private readonly List<string> _keywordOn = new List<string>();
private readonly List<string> _keywordOff = new List<string>();
/// <summary>
/// Shader scripts used for all rendering.
/// </summary>
public Shader Shader
{
get
{
if (!_loaded)
{
_loaded = true;
_shader = FindShader(_shaderLocation,_shaderName);
if (_shader == null)
{
Log.Error($"invalid shader path: {_shaderLocation}, shader name {_shaderName}");
}
}
return _shader;
}
}
/// <summary>
/// 查找Shader。
/// </summary>
/// <param name="shaderLocation">Shader定位地址。</param>
/// <param name="shaderName">Shader名称。</param>
/// <returns>Shader实例。</returns>
public static Shader FindShader(string shaderLocation,string shaderName)
{
Shader shader = GameModule.Resource.LoadAsset<Shader>(shaderLocation);
if (shader != null)
{
return shader;
}
return Shader.Find(shaderName);
}
/// <summary>
/// TShader构造函数。
/// </summary>
/// <param name="shaderName">shader名称。</param>
/// <param name="shaderLocation">shader路径。</param>
public TShader(string shaderName, string shaderLocation)
{
_shaderName = shaderName;
_shaderLocation = shaderLocation;
_shader = null;
}
/// <summary>
/// TShader构造函数。
/// </summary>
/// <param name="shaderName">shader名称。</param>
/// <param name="shaderLocation">shader路径。</param>
/// <param name="keywordOn">开启选项。</param>
/// <param name="keywordOff">关闭选项。</param>
public TShader(string shaderName, string shaderLocation, string keywordOn, string keywordOff)
{
_shaderName = shaderName;
_shaderLocation = shaderLocation;
_shader = null;
_keywordOn.Add(keywordOn);
_keywordOff.Add(keywordOff);
}
/// <summary>
/// TShader构造函数。
/// </summary>
/// <param name="shaderName">shader名称。</param>
/// <param name="shaderLocation">shader路径。</param>
/// <param name="keywordOn">开启选项。</param>
/// <param name="keywordOff">关闭选项。</param>
public TShader(string shaderName, string shaderLocation, string[] keywordOn, string[] keywordOff)
{
_shaderName = shaderName;
_shaderLocation = shaderLocation;
_shader = null;
_keywordOn.AddRange(keywordOn);
_keywordOff.AddRange(keywordOff);
}
/// <summary>
/// 设置Shader效果。
/// </summary>
/// <param name="render">渲染对象。</param>
public void ApplyRender(Renderer render)
{
var sharedMat = render.sharedMaterial;
if (sharedMat != null)
{
//copy一份材质
sharedMat = render.material;
sharedMat.shader = Shader;
foreach (var keyword in _keywordOff)
{
sharedMat.DisableKeyword(keyword);
}
foreach (var keyword in _keywordOn)
{
sharedMat.EnableKeyword(keyword);
}
}
}
/// <summary>
/// 清除shader。
/// </summary>
/// <param name="render">渲染对象。</param>
public void ClearRender(Renderer render)
{
if (_keywordOff.Count <= 0 && _keywordOn.Count <= 0)
{
return;
}
var sharedMat = render.sharedMaterial;
if (sharedMat != null)
{
//copy一份材质。
sharedMat = render.material;
for (int k = 0; k < _keywordOn.Count; k++)
{
sharedMat.DisableKeyword(_keywordOn[k]);
}
for (int k = 0; k < _keywordOff.Count; k++)
{
sharedMat.EnableKeyword(_keywordOff[k]);
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e219233984c14f7d97bc744c07fe13d0
timeCreated: 1698115491

View File

@@ -9,10 +9,10 @@ namespace GameLogic
/// <summary>
/// UI列表Item
/// </summary>
/// <typeparam name="DataT"></typeparam>
public interface IListDataItem<in DataT>
/// <typeparam name="TData"></typeparam>
public interface IListDataItem<in TData>
{
void SetItemData(DataT d);
void SetItemData(TData d);
}
/// <summary>
@@ -180,8 +180,7 @@ namespace GameLogic
/// <param name="n"></param>
public void SetDatas(List<DataT> dataList, int n = -1)
{
AdjustItemNum(Mathf.Max(0, n >= 0 ? n : (dataList == null ? 0 : (dataList.Count - dataStartOffset))),
dataList);
AdjustItemNum(Mathf.Max(0, n >= 0 ? n : (dataList == null ? 0 : (dataList.Count - dataStartOffset))), dataList);
}
/// <summary>
@@ -215,8 +214,7 @@ namespace GameLogic
return;
}
var listDataItem = item as IListDataItem<DataT>;
if (listDataItem != null)
if (item is IListDataItem<DataT> listDataItem)
{
listDataItem.SetItemData(GetData(i));
}
@@ -271,8 +269,7 @@ namespace GameLogic
var preIndex = selectIndex;
m_selectIndex = i;
var item = GetItem(preIndex) as IListSelectItem;
if (item != null)
if (GetItem(preIndex) is IListSelectItem item)
{
item.SetSelected(false);
}
@@ -282,12 +279,19 @@ namespace GameLogic
{
item.SetSelected(true);
}
UpdateSnapTargetItem();
if (triggerEvt && funcOnSelectChange != null)
{
funcOnSelectChange.Invoke();
}
}
/// <summary>
/// 刷新Snap
/// </summary>
protected virtual void UpdateSnapTargetItem()
{
}
/// <summary>
/// 获取当前选中的数据
@@ -318,6 +322,11 @@ namespace GameLogic
{
return null;
}
/// <summary>
/// 点击选择
/// </summary>
public bool SelectByClick = true;
/// <summary>
/// item被点击
@@ -331,7 +340,10 @@ namespace GameLogic
funcOnItemClick.Invoke(i);
}
selectIndex = i;
if (SelectByClick)
{
selectIndex = i;
}
}
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using TEngine;
namespace GameLogic
{
/// <summary>
/// 普通UI列表。
/// </summary>
public class UIListWidget<TItem, TData> : UIListBase<TItem, TData> where TItem : UIWidget, new()
{
/// <summary>
/// item列表。
/// </summary>
protected List<TItem> m_items = new List<TItem>();
/// <summary>
/// item列表。
/// </summary>
public List<TItem> items => m_items;
/// <summary>
/// 设置显示数据。
/// </summary>
/// <param name="n"></param>
/// <param name="datas"></param>
/// <param name="funcItem"></param>
protected override void AdjustItemNum(int n, List<TData> datas = null, Action<TItem, int> funcItem = null)
{
base.AdjustItemNum(n, datas, funcItem);
AdjustIconNum(m_items, n, gameObject.transform, itemBase);
UpdateList(funcItem);
}
/// <summary>
/// 刷新列表。
/// </summary>
/// <param name="funcItem"></param>
protected void UpdateList(Action<TItem, int> funcItem = null)
{
for (var i = 0; i < m_items.Count; i++)
{
UpdateListItem(m_items[i], i, funcItem);
}
}
/// <summary>
/// 获取item
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
public override TItem GetItem(int i)
{
return i >= 0 && i < m_items.Count ? m_items[i] : null;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 96f732d895e94fbc99c904d66ca844ca
timeCreated: 1701844130

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using TEngine;
using UnityEngine;
namespace GameLogic
@@ -17,7 +18,7 @@ namespace GameLogic
/// <summary>
/// Item字典
/// </summary>
private Dictionary<int, TItem> m_itemCache = new Dictionary<int, TItem>();
private GameFrameworkDictionary<int, TItem> m_itemCache = new GameFrameworkDictionary<int, TItem>();
/// <summary>
/// 计算偏差后的ItemList
@@ -65,6 +66,7 @@ namespace GameLogic
LoopRectView.SetListItemCount(n);
LoopRectView.RefreshAllShownItem();
m_tpFuncItem = null;
UpdateAllItemSelect();
}
/// <summary>
@@ -147,11 +149,20 @@ namespace GameLogic
/// <summary>
/// 获取item
/// </summary>
/// <param name="i"></param>
/// <param name="index"></param>
/// <returns></returns>
public override TItem GetItem(int i)
public override TItem GetItem(int index)
{
return i >= 0 && i < m_items.Count ? m_items[i] : null;
for (var i = 0; i < m_itemCache.Count; i++)
{
var item = m_itemCache.GetValueByIndex(i);
if (item.GetItemIndex() == index)
{
return item;
}
}
return null;
}
/// <summary>
@@ -163,9 +174,35 @@ namespace GameLogic
m_items.Clear();
for (int i = 0; i < m_itemCache.Count; i++)
{
m_items.Add(m_itemCache[i]);
m_items.Add(m_itemCache.GetValueByIndex(i));
}
return m_items;
}
/// <summary>
/// 获取Item。
/// </summary>
/// <param name="index">索引。</param>
/// <returns>TItem。</returns>
public TItem GetItemByIndex(int index)
{
return m_itemCache.GetValueByIndex(index);
}
/// <summary>
/// 刷新所有item选中状态
/// </summary>
/// <returns></returns>
public void UpdateAllItemSelect()
{
var index = selectIndex;
for (var i = 0; i < m_itemCache.Count; i++)
{
if (m_itemCache.GetValueByIndex(i) is IListSelectItem item)
{
item.SetSelected(item.GetItemIndex() == index);
}
}
}
}
}

View File

@@ -8,7 +8,7 @@ namespace GameLogic
{
public LoopListView LoopRectView { private set; get; }
private Dictionary<int, T> m_itemCache = new Dictionary<int, T>();
private GameFrameworkDictionary<int, T> m_itemCache = new GameFrameworkDictionary<int, T>();
public override void BindMemberProperty()
{
@@ -71,9 +71,8 @@ namespace GameLogic
List<T> list = new List<T>();
for (int i = 0; i < m_itemCache.Count; i++)
{
list.Add(m_itemCache[i]);
list.Add(m_itemCache.GetValueByIndex(i));
}
return list;
}
@@ -85,11 +84,11 @@ namespace GameLogic
/// <summary>
/// 获取Item。
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
/// <param name="index">索引。</param>
/// <returns>TItem。</returns>
public T GetItemByIndex(int index)
{
return m_itemCache[index];
return m_itemCache.GetValueByIndex(index);
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using TEngine;
using UnityEngine;
namespace GameLogic
@@ -16,8 +17,9 @@ namespace GameLogic
/// <summary>
/// Item字典
/// <remarks>Key => GameObjectHashCode | Value => TItem.</remarks>
/// </summary>
private Dictionary<int, TItem> m_itemCache = new Dictionary<int, TItem>();
private GameFrameworkDictionary<int, TItem> m_itemCache = new GameFrameworkDictionary<int, TItem>();
/// <summary>
/// 计算偏差后的ItemList
@@ -65,6 +67,7 @@ namespace GameLogic
LoopRectView.SetListItemCount(n);
LoopRectView.RefreshAllShownItem();
m_tpFuncItem = null;
UpdateAllItemSelect();
}
/// <summary>
@@ -145,11 +148,20 @@ namespace GameLogic
/// <summary>
/// 获取item
/// </summary>
/// <param name="i"></param>
/// <param name="index"></param>
/// <returns></returns>
public override TItem GetItem(int i)
public override TItem GetItem(int index)
{
return i >= 0 && i < m_items.Count ? m_items[i] : null;
for (var i = 0; i < m_itemCache.Count; i++)
{
var item = m_itemCache.GetValueByIndex(i);
if (item.GetItemIndex() == index)
{
return item;
}
}
return null;
}
/// <summary>
@@ -161,7 +173,7 @@ namespace GameLogic
m_items.Clear();
for (int i = 0; i < m_itemCache.Count; i++)
{
m_items.Add(m_itemCache[i]);
m_items.Add(m_itemCache.GetValueByIndex(i));
}
return m_items;
}
@@ -174,5 +186,40 @@ namespace GameLogic
{
return LoopRectView.GetItemStartIndex();
}
/// <summary>
/// 获取Item。
/// </summary>
/// <param name="index">索引。</param>
/// <returns>TItem。</returns>
public TItem GetItemByIndex(int index)
{
return m_itemCache.GetValueByIndex(index);
}
/// <summary>
/// 刷新所有item选中状态
/// </summary>
/// <returns></returns>
public void UpdateAllItemSelect()
{
var index = selectIndex;
for (var i = 0; i < m_itemCache.Count; i++)
{
if (m_itemCache.GetValueByIndex(i) is IListSelectItem item)
{
item.SetSelected(item.GetItemIndex() == index);
}
}
}
protected override void UpdateSnapTargetItem()
{
base.UpdateSnapTargetItem();
if (LoopRectView != null && LoopRectView.ItemSnapEnable)
{
LoopRectView.SetSnapTargetItemIndex(selectIndex);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d1f693ff76ae490fbe194855d94e8266
timeCreated: 1702479172

View File

@@ -0,0 +1,20 @@
using System;
using TEngine;
namespace GameLogic
{
/// <summary>
/// 事件接口帮助类。
/// </summary>
internal class EventInterfaceHelper
{
/// <summary>
/// 初始化。
/// </summary>
public static void Init()
{
RegisterEventInterface_Logic.Register(GameEvent.EventMgr);
RegisterEventInterface_UI.Register(GameEvent.EventMgr);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9afaf331ee7249adb5cc0953dfd3413c
timeCreated: 1702379658

View File

@@ -0,0 +1,16 @@
using TEngine;
namespace GameLogic
{
[System.AttributeUsage(System.AttributeTargets.Class)]
internal class EventInterfaceImpAttribute : BaseAttribute
{
private EEventGroup _eGroup;
public EEventGroup EventGroup => _eGroup;
public EventInterfaceImpAttribute(EEventGroup group)
{
_eGroup = group;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8bbf40942b0e4470bb8d8a82577f713c
timeCreated: 1702479403

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: de49bf2e9f0a4fac85851a582e2fb4ed
timeCreated: 1702379835

View File

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

View File

@@ -0,0 +1,70 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by autoBindTool.
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using UnityEngine;
using UnityEngine.UI;
using TEngine;
namespace GameLogic
{
public partial class IActorLogicEvent_Event
{
public static readonly int OnMainPlayerDataChange = RuntimeId.ToRuntimeId("IActorLogicEvent_Event.OnMainPlayerDataChange");
public static readonly int OnMainPlayerLevelChange = RuntimeId.ToRuntimeId("IActorLogicEvent_Event.OnMainPlayerLevelChange");
public static readonly int OnMainPlayerGoldChange = RuntimeId.ToRuntimeId("IActorLogicEvent_Event.OnMainPlayerGoldChange");
public static readonly int OnMainPlayerDiamondChange = RuntimeId.ToRuntimeId("IActorLogicEvent_Event.OnMainPlayerDiamondChange");
public static readonly int OnMainPlayerBindDiamondChange = RuntimeId.ToRuntimeId("IActorLogicEvent_Event.OnMainPlayerBindDiamondChange");
public static readonly int OnMainPlayerCurrencyChange = RuntimeId.ToRuntimeId("IActorLogicEvent_Event.OnMainPlayerCurrencyChange");
public static readonly int OnMainPlayerExpChange = RuntimeId.ToRuntimeId("IActorLogicEvent_Event.OnMainPlayerExpChange");
}
[EventInterfaceImp(EEventGroup.GroupLogic)]
public partial class IActorLogicEvent_Gen : IActorLogicEvent
{
private EventDispatcher _dispatcher;
public IActorLogicEvent_Gen(EventDispatcher dispatcher)
{
_dispatcher = dispatcher;
}
public void OnMainPlayerDataChange()
{
_dispatcher.Send(IActorLogicEvent_Event.OnMainPlayerDataChange);
}
public void OnMainPlayerLevelChange()
{
_dispatcher.Send(IActorLogicEvent_Event.OnMainPlayerLevelChange);
}
public void OnMainPlayerGoldChange(System.UInt32 oldVal,System.UInt32 newVal)
{
_dispatcher.Send(IActorLogicEvent_Event.OnMainPlayerGoldChange,oldVal,newVal);
}
public void OnMainPlayerDiamondChange(System.UInt32 oldVal,System.UInt32 newVal)
{
_dispatcher.Send(IActorLogicEvent_Event.OnMainPlayerDiamondChange,oldVal,newVal);
}
public void OnMainPlayerBindDiamondChange(System.UInt32 oldVal,System.UInt32 newVal)
{
_dispatcher.Send(IActorLogicEvent_Event.OnMainPlayerBindDiamondChange,oldVal,newVal);
}
public void OnMainPlayerCurrencyChange(GameLogic.CurrencyType type,System.UInt32 oldVal,System.UInt32 newVal)
{
_dispatcher.Send(IActorLogicEvent_Event.OnMainPlayerCurrencyChange,type,oldVal,newVal);
}
public void OnMainPlayerExpChange(System.UInt64 oldVal,System.UInt64 newVal)
{
_dispatcher.Send(IActorLogicEvent_Event.OnMainPlayerExpChange,oldVal,newVal);
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,40 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by autoBindTool.
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using UnityEngine;
using UnityEngine.UI;
using TEngine;
namespace GameLogic
{
public partial class ILoginUI_Event
{
public static readonly int OnRoleLogin = RuntimeId.ToRuntimeId("ILoginUI_Event.OnRoleLogin");
public static readonly int OnRoleLoginOut = RuntimeId.ToRuntimeId("ILoginUI_Event.OnRoleLoginOut");
}
[EventInterfaceImp(EEventGroup.GroupUI)]
public partial class ILoginUI_Gen : ILoginUI
{
private EventDispatcher _dispatcher;
public ILoginUI_Gen(EventDispatcher dispatcher)
{
_dispatcher = dispatcher;
}
public void OnRoleLogin(System.Boolean isReconnect)
{
_dispatcher.Send(ILoginUI_Event.OnRoleLogin,isReconnect);
}
public void OnRoleLoginOut()
{
_dispatcher.Send(ILoginUI_Event.OnRoleLoginOut);
}
}
}

View File

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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7cf3381dedbf4daeb53e710a5c544204
timeCreated: 1702433587

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 610229edeca4417685ffd07f18b2b9f1
timeCreated: 1702379817

View File

@@ -0,0 +1,38 @@
using System;
using TEngine;
namespace GameLogic
{
/// <summary>
/// 示例货币枚举。
/// </summary>
public enum CurrencyType
{
None,
Gold,
Diamond,
}
/// <summary>
/// 示意逻辑层事件。
/// <remarks> 优化抛出事件,通过接口约束事件参数。</remarks>
/// <remarks> example: GameEvent.Get<IActorLogicEvent>().OnMainPlayerCurrencyChange(CurrencyType.Gold,oldVal,newVal); </remarks>
/// </summary>
[EventInterface(EEventGroup.GroupLogic)]
interface IActorLogicEvent
{
void OnMainPlayerDataChange();
void OnMainPlayerLevelChange();
void OnMainPlayerGoldChange(uint oldVal, uint newVal);
void OnMainPlayerDiamondChange(uint oldVal, uint newVal);
void OnMainPlayerBindDiamondChange(uint oldVal, uint newVal);
void OnMainPlayerCurrencyChange(CurrencyType type, uint oldVal, uint newVal);
void OnMainPlayerExpChange(ulong oldVal, ulong newVal);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8d4558cb74e8462a86f0ee3461f6b7c9
timeCreated: 1702383645

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 90e13cc92c5d42f28b4f5fab599f472a
timeCreated: 1702379805

View File

@@ -0,0 +1,17 @@
using TEngine;
namespace GameLogic
{
/// <summary>
/// 示意UI层事件。
/// <remarks> 优化抛出事件,通过接口约束事件参数。</remarks>
/// <remarks> example: GameEvent.Get<ILoginUI>().OnRoleLogin(isReconnect); </remarks>
/// </summary>
[EventInterface(EEventGroup.GroupUI)]
public interface ILoginUI
{
public void OnRoleLogin(bool isReconnect);
public void OnRoleLoginOut();
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 33b45e62bd3447498acfe874017b9a35
timeCreated: 1702433755

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using TEngine;
namespace GameLogic
{
/// <summary>
/// 逻辑层事件接口。
/// </summary>
internal class RegisterEventInterface_Logic
{
/// <summary>
/// 注册逻辑层事件接口。
/// </summary>
/// <param name="mgr">事件管理器。</param>
public static void Register(EventMgr mgr)
{
HashSet<Type> types = CodeTypes.Instance.GetTypes(typeof(EventInterfaceImpAttribute));
foreach (Type type in types)
{
object[] attrs = type.GetCustomAttributes(typeof(EventInterfaceImpAttribute), false);
if (attrs.Length == 0)
{
continue;
}
EventInterfaceImpAttribute httpHandlerAttribute = (EventInterfaceImpAttribute)attrs[0];
if (httpHandlerAttribute.EventGroup != EEventGroup.GroupLogic)
{
continue;
}
object obj = Activator.CreateInstance(type, mgr.Dispatcher);
mgr.RegWrapInterface(obj.GetType().GetInterfaces()[0]?.FullName, obj);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b8bdf6c139b44758aa16db2e1837f5d9
timeCreated: 1702379518

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using TEngine;
namespace GameLogic
{
/// <summary>
/// UI层事件接口。
/// </summary>
internal class RegisterEventInterface_UI
{
/// <summary>
/// 注册UI层事件接口。
/// </summary>
/// <param name="mgr">事件管理器。</param>
public static void Register(EventMgr mgr)
{
HashSet<Type> types = CodeTypes.Instance.GetTypes(typeof(EventInterfaceImpAttribute));
foreach (Type type in types)
{
object[] attrs = type.GetCustomAttributes(typeof(EventInterfaceImpAttribute), false);
if (attrs.Length == 0)
{
continue;
}
EventInterfaceImpAttribute httpHandlerAttribute = (EventInterfaceImpAttribute)attrs[0];
if (httpHandlerAttribute.EventGroup != EEventGroup.GroupUI)
{
continue;
}
object obj = Activator.CreateInstance(type, mgr.Dispatcher);
mgr.RegWrapInterface(obj.GetType().GetInterfaces()[0]?.FullName, obj);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f53b67f2cfbe4912bffee9593cd60970
timeCreated: 1702379505

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using GameLogic;
using TEngine;
using UnityEngine;
@@ -8,6 +9,8 @@ public partial class GameApp
private void Init()
{
CodeTypes.Instance.Init(_hotfixAssembly.ToArray());
EventInterfaceHelper.Init();
_listLogicMgr = new List<ILogicSys>();
RegisterAllSystem();
InitSystemSetting();

View File

@@ -812,7 +812,6 @@ GameObject:
- component: {fileID: 4070374929253206932}
- component: {fileID: 4872533144352319846}
- component: {fileID: 3352775805385032060}
- component: {fileID: 3859027068210555860}
m_Layer: 5
m_Name: UILoadTip
m_TagString: Untagged
@@ -880,31 +879,6 @@ MonoBehaviour:
m_BlockingMask:
serializedVersion: 2
m_Bits: 55
--- !u!114 &3859027068210555860
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7666412045263395013}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bcd11033283847ee8f7c71eedd9a4771, type: 3}
m_Name:
m_EditorClassIdentifier:
elements:
m_keys:
- m_btnUpdate
- m_btnIgnore
- m_textInfo
- m_textTittle
- m_btnPackage
m_values:
- {fileID: 2745714441875214452}
- {fileID: 467775921333773033}
- {fileID: 3862717357071106210}
- {fileID: 9127528276671758327}
- {fileID: 1387175525974173601}
--- !u!1 &8012535748721374403
GameObject:
m_ObjectHideFlags: 0

View File

@@ -773,7 +773,6 @@ GameObject:
- component: {fileID: 1633508802563447727}
- component: {fileID: 5827342734203288403}
- component: {fileID: 4835021223508371640}
- component: {fileID: 903919243524269039}
m_Layer: 5
m_Name: UILoadUpdate
m_TagString: Untagged
@@ -843,33 +842,6 @@ MonoBehaviour:
m_BlockingMask:
serializedVersion: 2
m_Bits: 55
--- !u!114 &903919243524269039
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9130266365217219149}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bcd11033283847ee8f7c71eedd9a4771, type: 3}
m_Name:
m_EditorClassIdentifier:
elements:
m_keys:
- m_imgBackGround
- m_scrollbarProgress
- m_textDesc
- m_btnClear
- m_textAppid
- m_textResid
m_values:
- {fileID: 4652061626151979521}
- {fileID: 2347891492826839465}
- {fileID: 8666815445422661327}
- {fileID: 4232232858152633415}
- {fileID: 3038352660368000718}
- {fileID: 8143980099109665604}
--- !u!1 &9157096376857424144
GameObject:
m_ObjectHideFlags: 0

View File

@@ -20,26 +20,22 @@ namespace GameMain
public MessageShowType ShowType = MessageShowType.None;
#region
private Button m_btnPackage;
private Text m_textTittle;
private Text m_textInfo;
private Button m_btnIgnore;
private Button m_btnUpdate;
public override void ScriptGenerator()
{
CheckUIElement();
m_btnPackage = FChild<Button>("m_btnPackage");
m_textTittle = FChild<Text>("m_textTittle");
m_textInfo = FChild<Text>("m_textInfo");
m_btnIgnore = FChild<Button>("m_btnIgnore");
m_btnUpdate = FChild<Button>("m_btnUpdate");
m_btnPackage = FindChildComponent<Button>("BgImage/m_btnPackage");
m_textTittle = FindChildComponent<Text>("BgImage/m_textTittle");
m_textInfo = FindChildComponent<Text>("BgImage/m_textInfo");
m_btnIgnore = FindChildComponent<Button>("BgImage/Group/m_btnIgnore");
m_btnUpdate = FindChildComponent<Button>("BgImage/Group/m_btnUpdate");
m_btnPackage.onClick.AddListener(OnClickPackageBtn);
m_btnIgnore.onClick.AddListener(OnClickIgnoreBtn);
m_btnUpdate.onClick.AddListener(OnClickUpdateBtn);
}
#endregion
#region

View File

@@ -8,22 +8,22 @@ namespace GameMain
[Window(UILayer.UI, fromResources: true, location: "AssetLoad/UILoadUpdate",fullScreen:true)]
public class UILoadUpdate : UIWindow
{
private Scrollbar m_scrollbarProgress;
#region
private Image m_imgBackGround;
private Scrollbar m_scrollbarProgress;
private Text m_textDesc;
private Button m_btnClear;
private Text m_textAppid;
private Text m_textResid;
public override void ScriptGenerator()
{
CheckUIElement();
m_imgBackGround = FChild<Image>("m_imgBackGround");
m_scrollbarProgress = FChild<Scrollbar>("m_scrollbarProgress");
m_textDesc = FChild<Text>("m_textDesc");
m_btnClear = FChild<Button>("m_btnClear");
m_textAppid = FChild<Text>("m_textAppid");
m_textResid = FChild<Text>("m_textResid");
m_imgBackGround = FindChildComponent<Image>("m_imgBackGround");
m_textDesc = FindChildComponent<Text>("m_textDesc");
m_btnClear = FindChildComponent<Button>("TopNode/m_btnClear");
m_textAppid = FindChildComponent<Text>("TopNode/m_textAppid");
m_textResid = FindChildComponent<Text>("TopNode/m_textResid");
m_scrollbarProgress = FindChildComponent<Scrollbar>("m_scrollbarProgress");
m_btnClear.onClick.AddListener(OnClickClearBtn);
}
#endregion
@@ -38,10 +38,15 @@ namespace GameMain
m_btnClear.gameObject.SetActive(true);
}
public override void RegisterEvent()
{
base.RegisterEvent();
AddUIEvent(RuntimeId.ToRuntimeId("RefreshVersion"),RefreshVersion);
}
public override void OnRefresh()
{
base.OnRefresh();
RefreshVersion();
}
#region
@@ -118,12 +123,12 @@ namespace GameMain
m_scrollbarProgress.size = progress;
}
protected override void Close()
public override void OnDestroy()
{
base.OnDestroy();
OnStop(null);
LoadUpdateLogic.Instance.DownloadCompleteAction -= DownLoad_Complete_Action;
LoadUpdateLogic.Instance.DownProgressAction -= DownLoad_Progress_Action;
base.Close();
}
}
}

View File

@@ -13,10 +13,18 @@ namespace GameMain
private ProcedureOwner _procedureOwner;
private float _currentDownloadTime;
private float CurrentSpeed =>
(GameModule.Resource.Downloader.TotalDownloadBytes -
GameModule.Resource.Downloader.CurrentDownloadBytes) / _currentDownloadTime;
private float _lastUpdateDownloadedSize;
private float CurrentSpeed
{
get
{
float interval = GameTime.deltaTime;
var sizeDiff = GameModule.Resource.Downloader.CurrentDownloadBytes - _lastUpdateDownloadedSize;
_lastUpdateDownloadedSize = GameModule.Resource.Downloader.CurrentDownloadBytes;
var speed = (float)Math.Floor(sizeDiff / interval);
return speed;
}
}
protected override void OnEnter(ProcedureOwner procedureOwner)
{
@@ -64,7 +72,7 @@ namespace GameMain
Utility.File.GetByteLengthString(currentDownloadBytes),
Utility.File.GetByteLengthString(totalDownloadBytes),
GameModule.Resource.Downloader.Progress,
Utility.File.GetByteLengthString((int)CurrentSpeed));
Utility.File.GetLengthString((int)CurrentSpeed));
LoadUpdateLogic.Instance.DownProgressAction?.Invoke(GameModule.Resource.Downloader.Progress);
UILoadMgr.Show(UIDefine.UILoadUpdate,descriptionText);

View File

@@ -29,7 +29,8 @@ namespace GameMain
private async UniTaskVoid InitPackage(ProcedureOwner procedureOwner)
{
if (GameModule.Resource.PlayMode == EPlayMode.HostPlayMode)
if (GameModule.Resource.PlayMode == EPlayMode.HostPlayMode ||
GameModule.Resource.PlayMode == EPlayMode.WebPlayMode)
{
if (SettingsUtils.EnableUpdateData())
{
@@ -44,7 +45,8 @@ namespace GameMain
if (!string.IsNullOrEmpty(updateData.FallbackHostServerURL))
{
SettingsUtils.FrameworkGlobalSettings.FallbackHostServerURL = updateData.FallbackHostServerURL;
SettingsUtils.FrameworkGlobalSettings.FallbackHostServerURL =
updateData.FallbackHostServerURL;
}
}
}
@@ -60,9 +62,9 @@ namespace GameMain
{
//热更新阶段文本初始化
LoadText.Instance.InitConfigData(null);
//热更新UI初始化
UILoadMgr.Initialize();
GameEvent.Send(RuntimeId.ToRuntimeId("RefreshVersion"));
EPlayMode playMode = GameModule.Resource.PlayMode;
// 编辑器模式。
@@ -107,7 +109,9 @@ namespace GameMain
// 打开启动UI。
UILoadMgr.Show(UIDefine.UILoadUpdate, $"资源初始化失败!");
UILoadTip.ShowMessageBox($"资源初始化失败!点击确认重试 \n \n <color=#FF0000>原因{initializationOperation.Error}</color>", MessageShowType.TwoButton,
UILoadTip.ShowMessageBox(
$"资源初始化失败!点击确认重试 \n \n <color=#FF0000>原因{initializationOperation.Error}</color>",
MessageShowType.TwoButton,
LoadStyle.StyleEnum.Style_Retry
, () => { Retry(procedureOwner); }, UnityEngine.Application.Quit);
}

View File

@@ -14,6 +14,9 @@ namespace GameMain
protected override void OnEnter(ProcedureOwner procedureOwner)
{
base.OnEnter(procedureOwner);
//热更新UI初始化
UILoadMgr.Initialize();
// 语言配置:设置当前使用的语言,如果不设置,则默认使用操作系统语言
InitLanguageSettings();

View File

@@ -16,23 +16,23 @@ namespace GameMain
{
private float _progress = 0f;
private Dictionary<string, bool> m_LoadedFlag = new Dictionary<string, bool>();
private readonly Dictionary<string, bool> _loadedFlag = new Dictionary<string, bool>();
public override bool UseNativeDialog => true;
private bool m_needProLoadConfig = false;
private readonly bool _needProLoadConfig = true;
private bool m_InitConfigXml = false;
private bool _hadInitConfigXml = false;
protected override void OnEnter(ProcedureOwner procedureOwner)
{
base.OnEnter(procedureOwner);
m_LoadedFlag.Clear();
_loadedFlag.Clear();
if (GameModule.Resource.PlayMode == EPlayMode.EditorSimulateMode)
{
m_InitConfigXml = true;
_hadInitConfigXml = true;
}
UILoadMgr.Show(UIDefine.UILoadUpdate, Utility.Text.Format(LoadText.Instance.Label_Load_Load_Progress, 0));
@@ -46,11 +46,11 @@ namespace GameMain
{
base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
var totalCount = m_LoadedFlag.Count <= 0 ? 1 : m_LoadedFlag.Count;
var totalCount = _loadedFlag.Count <= 0 ? 1 : _loadedFlag.Count;
var loadCount = m_LoadedFlag.Count <= 0 ? 1 : 0;
var loadCount = _loadedFlag.Count <= 0 ? 1 : 0;
foreach (KeyValuePair<string, bool> loadedFlag in m_LoadedFlag)
foreach (KeyValuePair<string, bool> loadedFlag in _loadedFlag)
{
if (!loadedFlag.Value)
{
@@ -62,7 +62,7 @@ namespace GameMain
}
}
if (m_LoadedFlag.Count != 0)
if (_loadedFlag.Count != 0)
{
UILoadMgr.Show(UIDefine.UILoadUpdate, Utility.Text.Format(LoadText.Instance.Label_Load_Load_Progress, (float)loadCount / totalCount * 100));
}
@@ -87,7 +87,7 @@ namespace GameMain
return;
}
if (m_InitConfigXml == false)
if (_hadInitConfigXml == false)
{
return;
}
@@ -116,13 +116,13 @@ namespace GameMain
await UniTask.Delay(TimeSpan.FromSeconds(2.5f));
if (m_needProLoadConfig)
if (_needProLoadConfig)
{
LoadAllConfig();
}
else
{
m_InitConfigXml = true;
_hadInitConfigXml = true;
}
}
@@ -130,14 +130,27 @@ namespace GameMain
{
if (GameModule.Resource.PlayMode == EPlayMode.EditorSimulateMode)
{
m_InitConfigXml = true;
_hadInitConfigXml = true;
return;
}
AssetInfo[] assetInfos = GameModule.Resource.GetAssetInfos("PRELOAD");
foreach (var assetInfo in assetInfos)
{
LoadConfig(assetInfo.Address);
}
#if UNITY_WEBGL
AssetInfo[] webAssetInfos = GameModule.Resource.GetAssetInfos("WEBGL_PRELOAD");
foreach (var assetInfo in webAssetInfos)
{
LoadConfig(assetInfo.Address);
}
#endif
_hadInitConfigXml = true;
}
private void LoadConfig(string configName)
{
m_LoadedFlag.Add(configName, false);
_loadedFlag.Add(configName, false);
GameModule.Resource.LoadAssetAsync<TextAsset>(configName, OnLoadSuccess);
}
@@ -147,10 +160,11 @@ namespace GameMain
{
return;
}
var name = assetOperationHandle.GetAssetInfo().Address;
m_LoadedFlag[name] = true;
Log.Info("Load config '{0}' OK.", name);
var location = assetOperationHandle.GetAssetInfo().Address;
_loadedFlag[location] = true;
GameModule.Resource.PushPreLoadAsset(location, assetOperationHandle.AssetObject);
Log.Info("Load config '{0}' OK.", location);
assetOperationHandle.Dispose();
}
}
}

View File

@@ -15,14 +15,14 @@ namespace GameMain
public override bool UseNativeDialog => true;
private ProcedureOwner _procedureOwner;
protected override void OnEnter(ProcedureOwner procedureOwner)
{
_procedureOwner = procedureOwner;
base.OnEnter(procedureOwner);
UILoadMgr.Show(UIDefine.UILoadUpdate,$"更新静态版本文件...");
UILoadMgr.Show(UIDefine.UILoadUpdate, $"更新静态版本文件...");
//检查设备是否能够访问互联网
if (Application.internetReachability == NetworkReachability.NotReachable)
@@ -34,6 +34,7 @@ namespace GameMain
GetStaticVersion().Forget,
() => { ChangeState<ProcedureInitResources>(procedureOwner); });
}
UILoadMgr.Show(UIDefine.UILoadUpdate, LoadText.Instance.Label_RequestVersionIng);
// 用户尝试更新静态版本。
@@ -49,23 +50,35 @@ namespace GameMain
var operation = GameModule.Resource.UpdatePackageVersionAsync();
await operation.ToUniTask();
try
{
await operation.ToUniTask();
if (operation.Status == EOperationStatus.Succeed)
{
//线上最新版本operation.PackageVersion
GameModule.Resource.PackageVersion = operation.PackageVersion;
Log.Debug($"Updated package Version : from {GameModule.Resource.GetPackageVersion()} to {operation.PackageVersion}");
ChangeState<ProcedureUpdateManifest>(_procedureOwner);
if (operation.Status == EOperationStatus.Succeed)
{
//线上最新版本operation.PackageVersion
GameModule.Resource.PackageVersion = operation.PackageVersion;
Log.Debug($"Updated package Version : from {GameModule.Resource.GetPackageVersion()} to {operation.PackageVersion}");
ChangeState<ProcedureUpdateManifest>(_procedureOwner);
}
else
{
OnGetStaticVersionError(operation.Error);
}
}
else
catch (Exception e)
{
Log.Error(operation.Error);
UILoadTip.ShowMessageBox($"用户尝试更新静态版本失败!点击确认重试 \n \n <color=#FF0000>原因{operation.Error}</color>", MessageShowType.TwoButton,
LoadStyle.StyleEnum.Style_Retry
, () => { ChangeState<ProcedureUpdateVersion>(_procedureOwner); }, UnityEngine.Application.Quit);
OnGetStaticVersionError(e.Message);
}
}
private void OnGetStaticVersionError(string error)
{
Log.Error(error);
UILoadTip.ShowMessageBox($"用户尝试更新静态版本失败!点击确认重试 \n \n <color=#FF0000>原因{error}</color>", MessageShowType.TwoButton,
LoadStyle.StyleEnum.Style_Retry
, () => { ChangeState<ProcedureUpdateVersion>(_procedureOwner); }, UnityEngine.Application.Quit);
}
}
}

View File

@@ -153,7 +153,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 709048975}
m_RootOrder: 10
m_RootOrder: 11
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &450845954
MonoBehaviour:
@@ -381,7 +381,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 709048975}
m_RootOrder: 6
m_RootOrder: 7
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &683825228
MonoBehaviour:
@@ -441,6 +441,7 @@ Transform:
m_Children:
- {fileID: 964133197}
- {fileID: 1751957488}
- {fileID: 1029867562}
- {fileID: 877336934}
- {fileID: 803382966}
- {fileID: 790894654}
@@ -505,7 +506,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 709048975}
m_RootOrder: 4
m_RootOrder: 5
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &790894655
MonoBehaviour:
@@ -571,7 +572,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 709048975}
m_RootOrder: 3
m_RootOrder: 4
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &803382967
MonoBehaviour:
@@ -617,7 +618,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 709048975}
m_RootOrder: 2
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &877336935
MonoBehaviour:
@@ -696,7 +697,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 709048975}
m_RootOrder: 9
m_RootOrder: 10
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &914171639
MonoBehaviour:
@@ -790,7 +791,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 709048975}
m_RootOrder: 5
m_RootOrder: 6
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &965975542
MonoBehaviour:
@@ -814,6 +815,50 @@ MonoBehaviour:
downloadingMaxNum: 3
failedTryAgain: 3
adaptiveReplacementCacheCapacity: 32
--- !u!1 &1029867561
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1029867562}
- component: {fileID: 1029867563}
m_Layer: 0
m_Name: Timer
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1029867562
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1029867561}
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: 709048975}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1029867563
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1029867561}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5e79c115d5054209810f42dc6e25cf94, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1047779123
GameObject:
m_ObjectHideFlags: 0
@@ -844,7 +889,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 709048975}
m_RootOrder: 11
m_RootOrder: 12
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1047779125
MonoBehaviour:
@@ -967,7 +1012,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 709048975}
m_RootOrder: 7
m_RootOrder: 8
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1666908678
MonoBehaviour:
@@ -1055,7 +1100,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 709048975}
m_RootOrder: 8
m_RootOrder: 9
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1863338242
MonoBehaviour:

View File

@@ -14,6 +14,8 @@ MonoBehaviour:
m_EditorClassIdentifier:
ShowPackageView: 0
EnableAddressable: 1
LocationToLower: 0
IncludeAssetGUID: 0
UniqueBundleName: 0
ShowEditorAlias: 0
Packages:
@@ -78,7 +80,7 @@ MonoBehaviour:
AddressRuleName: AddressByFileName
PackRuleName: PackDirectory
FilterRuleName: CollectAll
AssetTags:
AssetTags: WEBGL_PRELOAD
UserData:
- GroupName: DLL
GroupDesc: "\u4EE3\u7801"

View File

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

View File

@@ -0,0 +1,227 @@
#region Class Documentation
/************************************************************************************************************
Class Name: EventInterfaceGenerate.cs
Type: Editor, Generator, Util, Static
Definition:
用法,在目录"Assets/GameScripts/HotFix/GameLogic/Event/Interface/"下分组照示例声明Interface 模块待抛出事件的接口。编译后自动生成接口实现抛出的脚本。
Example:
旧版抛出事件方式: GameEvent.Send(RuntimeId.ToRuntimeId("OnMainPlayerCurrencyChange"),CurrencyType.Gold,oldVal,newVal);
新版抛出事件方式 GameEvent.Get<IActorLogicEvent>().OnMainPlayerCurrencyChange(CurrencyType.Gold,oldVal,newVal);
************************************************************************************************************/
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using TEngine;
using Unity.EditorCoroutines.Editor;
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
public static class EventInterfaceGenerate
{
public static string NameSpace = @"GameLogic";
public const string EventInterfacePath = "Assets/GameScripts/HotFix/GameLogic/Event/Interface/";
public static bool BOpenAutoGenerate = false;
static EventInterfaceGenerate()
{
BOpenAutoGenerate = EditorPrefs.GetBool("EventInterfaceGenerate.BOpenAutoGenerate", true);
if (BOpenAutoGenerate)
{
Generate();
}
}
[MenuItem("TEngine/EventInterface/OpenAutoGenerate", false, 300)]
public static void OpenAutoGenerate()
{
EditorPrefs.SetBool("EventInterfaceGenerate.BOpenAutoGenerate", true);
Debug.Log("OpenAutoGenerate");
}
[MenuItem("TEngine/EventInterface/CloseAutoGenerate", false, 301)]
public static void CloseAutoGenerate()
{
EditorPrefs.SetBool("EventInterfaceGenerate.BOpenAutoGenerate", false);
Debug.Log("CloseAutoGenerate");
}
[MenuItem("TEngine/EventInterface/Generate EventInterface", false, 302)]
public static void Generate()
{
if (EventInterfaceGenerateTag.HadGenerate)
{
return;
}
EventInterfaceGenerateTag.HadGenerate = true;
// 加载程序集
Assembly assembly = typeof(GameApp).Assembly;
// 获取程序集中的所有类型
Type[] types = assembly.GetTypes();
// 遍历每个类型
foreach (Type type in types)
{
// 检查类型是否是接口
if (!type.IsInterface)
{
continue;
}
var attribute = type.GetCustomAttributes(typeof(EventInterfaceAttribute), false).FirstOrDefault();
if (attribute != null)
{
EventInterfaceAttribute eventInterfaceAttribute = attribute as EventInterfaceAttribute;
GenAutoBindCode(type, eventInterfaceAttribute);
}
}
AssetDatabase.Refresh();
Debug.Log("Generate EventInterface Complete");
// EditorUtility.DisplayDialog("提示", "代码生成完毕", "OK");
EditorCoroutineUtility.StartCoroutine(EventInterfaceGenerateTag.Reset(), null);
}
/// <summary>
/// 生成自动绑定代码
/// </summary>
private static void GenAutoBindCode(Type interfaceType, EventInterfaceAttribute eventInterfaceAttribute)
{
string interfaceName = interfaceType.Name;
string className = $"{interfaceName}_Gen";
string codePath = $"{Application.dataPath}/GameScripts/HotFix/GameLogic/Event/Gen/{eventInterfaceAttribute.EventGroup}";
if (!Directory.Exists(codePath))
{
Directory.CreateDirectory(codePath);
}
using (StreamWriter sw = new StreamWriter($"{codePath}/{className}.cs"))
{
sw.WriteLine(
$"//------------------------------------------------------------------------------\n//\t<auto-generated>\n//\t\tThis code was generated by autoBindTool.\n//\t\tChanges to this file may cause incorrect behavior and will be lost if\n//\t\tthe code is regenerated.\n//\t</auto-generated>\n//------------------------------------------------------------------------------");
sw.WriteLine("using UnityEngine;");
sw.WriteLine("using UnityEngine.UI;");
sw.WriteLine("using TEngine;");
sw.WriteLine("");
if (!string.IsNullOrEmpty(NameSpace))
{
//命名空间
sw.WriteLine("namespace " + NameSpace);
sw.WriteLine("{");
}
#region EventId生成
sw.WriteLine($"\tpublic partial class {interfaceName}_Event");
sw.WriteLine("\t{");
// 获取接口中的所有方法
MethodInfo[] methods = interfaceType.GetMethods();
HashSet<string> hadGenerate = new HashSet<string>();
//组件字段
foreach (MethodInfo method in methods)
{
if (hadGenerate.Contains(method.Name))
{
continue;
}
sw.WriteLine($"\t\tpublic static readonly int {method.Name} = RuntimeId.ToRuntimeId(\"{interfaceName}_Event.{method.Name}\");");
hadGenerate.Add(method.Name);
}
sw.WriteLine("\t}");
sw.WriteLine("");
#endregion
//类名
sw.WriteLine($"\t[EventInterfaceImp(EEventGroup.{eventInterfaceAttribute.EventGroup})]");
sw.WriteLine($"\tpublic partial class {className} : {interfaceName}");
sw.WriteLine("\t{");
sw.WriteLine("\t\tprivate EventDispatcher _dispatcher;");
sw.WriteLine($"\t\tpublic {className}(EventDispatcher dispatcher)");
sw.WriteLine("\t\t{");
sw.WriteLine($"\t\t\t_dispatcher = dispatcher;");
sw.WriteLine("\t\t}");
sw.WriteLine("");
//组件字段
foreach (MethodInfo methodInfo in methods)
{
ParameterInfo[] parameterInfos = methodInfo.GetParameters(); //得到指定方法的参数列表
if (parameterInfos.Length <= 0)
{
sw.WriteLine(
$" public void {methodInfo.Name}()\n {{\n _dispatcher.Send({interfaceName}_Event.{methodInfo.Name});\n }}");
}
else
{
string paramStr = "";
string paramStr2 = "";
for (int i = 0; i < parameterInfos.Length; i++)
{
var parameterInfo = parameterInfos[i];
Type type = parameterInfo.ParameterType;
string paramName = parameterInfo.Name;
if (i == parameterInfos.Length - 1)
{
paramStr += $"{type.FullName} {paramName}";
paramStr2 += $"{paramName}";
}
else
{
paramStr += $"{type.FullName} {paramName},";
paramStr2 += $"{paramName},";
}
}
sw.WriteLine(
$" public void {methodInfo.Name}({paramStr})\n {{\n _dispatcher.Send({interfaceName}_Event.{methodInfo.Name},{paramStr2});\n }}");
}
sw.WriteLine("");
}
sw.WriteLine("\t}");
if (!string.IsNullOrEmpty(NameSpace))
{
sw.WriteLine("}");
}
}
}
}
public static class EventInterfaceGenerateTag
{
public static bool HadGenerate = false;
public static IEnumerator Reset()
{
yield return new WaitForSeconds(10f);
HadGenerate = false;
}
}

View File

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

View File

@@ -4,7 +4,7 @@ using TEngine.Editor;
using UnityEditor;
using UnityEngine;
public static class BuildAssetsCommand
public static class BuildDLLCommand
{
private const string EnableHybridClrScriptingDefineSymbol = "ENABLE_HYBRIDCLR";
@@ -35,6 +35,12 @@ public static class BuildAssetsCommand
CopyAOTHotUpdateDlls(target);
}
public static void BuildAndCopyDlls(BuildTarget target)
{
CompileDllCommand.CompileDll(target);
CopyAOTHotUpdateDlls(target);
}
public static void CopyAOTHotUpdateDlls(BuildTarget target)
{
CopyAOTAssembliesToAssetPath();

View File

@@ -4,6 +4,7 @@ using System.IO;
using UnityEditor;
using UnityEditor.U2D;
using UnityEngine;
using UnityEngine.U2D;
using Object = UnityEngine.Object;
/// <summary>
@@ -55,6 +56,33 @@ public static class EditorSpriteSaveInfo
}
EditorApplication.update += CheckDirty;
//读取所有图集信息
string[] findAssets = AssetDatabase.FindAssets("t:SpriteAtlas", new[] { NormalAtlasDir });
foreach (var findAsset in findAssets)
{
var path = AssetDatabase.GUIDToAssetPath(findAsset);
SpriteAtlas sa = AssetDatabase.LoadAssetAtPath(path, typeof(SpriteAtlas)) as SpriteAtlas;
if (sa == null)
{
Debug.LogError($"加载图集数据{path}失败");
continue;
}
string atlasName = Path.GetFileNameWithoutExtension(path);
var objects = sa.GetPackables();
foreach (var o in objects)
{
if (!m_allASprites.TryGetValue(atlasName, out var list))
{
list = new List<string>();
m_allASprites.Add(atlasName, list);
}
list.Add(AssetDatabase.GetAssetPath(o));
}
}
m_inited = true;
}
public static void CheckDirty()

View File

@@ -1,42 +1,119 @@
using UnityEditor;
using System;
using UnityEditor;
using UnityEditor.Build.Reporting;
using UnityEngine;
using YooAsset.Editor;
using BuildResult = UnityEditor.Build.Reporting.BuildResult;
namespace TEngine
{
/// <summary>
/// 打包工具类。
/// <remarks>通过CommandLineReader可以不前台开启Unity实现静默打包详见CommandLineReader.cs example1</remarks>
/// <remarks>通过CommandLineReader可以不前台开启Unity实现静默打包以及CLI工作流详见CommandLineReader.cs example1</remarks>
/// </summary>
public static class ReleaseTools
{
public static void BuildPackage()
public static void BuildDll()
{
string platform = CommandLineReader.GetCustomArgument("platform");
if (string.IsNullOrEmpty(platform))
{
Debug.LogError($"Build Asset Bundle Errorplatform is null");
return;
}
BuildTarget target = GetBuildTarget(platform);
BuildDLLCommand.BuildAndCopyDlls(target);
}
public static void BuildAssetBundle()
{
string outputRoot = CommandLineReader.GetCustomArgument("outputRoot");
BuildTarget target = BuildTarget.StandaloneWindows64;
BuildInternal(target,outputRoot);
if (string.IsNullOrEmpty(outputRoot))
{
Debug.LogError($"Build Asset Bundle ErroroutputRoot is null");
return;
}
string packageVersion = CommandLineReader.GetCustomArgument("packageVersion");
if (string.IsNullOrEmpty(packageVersion))
{
Debug.LogError($"Build Asset Bundle ErrorpackageVersion is null");
return;
}
string platform = CommandLineReader.GetCustomArgument("platform");
if (string.IsNullOrEmpty(platform))
{
Debug.LogError($"Build Asset Bundle Errorplatform is null");
return;
}
BuildTarget target = GetBuildTarget(platform);
BuildInternal(target, outputRoot);
Debug.LogWarning($"Start BuildPackage BuildTarget:{target} outputPath:{outputRoot}");
}
private static void BuildInternal(BuildTarget buildTarget,string outputRoot)
private static BuildTarget GetBuildTarget(string platform)
{
BuildTarget target = BuildTarget.NoTarget;
switch (platform)
{
case "Android":
target = BuildTarget.Android;
break;
case "IOS":
target = BuildTarget.iOS;
break;
case "Windows":
target = BuildTarget.StandaloneWindows64;
break;
case "MacOS":
target = BuildTarget.StandaloneOSX;
break;
case "Linux":
target = BuildTarget.StandaloneLinux64;
break;
case "WebGL":
target = BuildTarget.WebGL;
break;
case "Switch":
target = BuildTarget.Switch;
break;
case "PS4":
target = BuildTarget.PS4;
break;
case "PS5":
target = BuildTarget.PS5;
break;
}
return target;
}
private static void BuildInternal(BuildTarget buildTarget, string outputRoot, string packageVersion = "1.0")
{
Debug.Log($"开始构建 : {buildTarget}");
BuildParameters.SBPBuildParameters sbpBuildParameters = new BuildParameters.SBPBuildParameters();
sbpBuildParameters.WriteLinkXML = true;
// 构建参数
BuildParameters buildParameters = new BuildParameters();
buildParameters.StreamingAssetsRoot = AssetBundleBuilderHelper.GetDefaultStreamingAssetsRoot();
buildParameters.BuildOutputRoot = outputRoot;//AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
buildParameters.BuildOutputRoot = outputRoot; //AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
buildParameters.BuildTarget = buildTarget;
buildParameters.BuildPipeline = EBuildPipeline.BuiltinBuildPipeline;
buildParameters.BuildMode = EBuildMode.ForceRebuild;
buildParameters.BuildPipeline = EBuildPipeline.ScriptableBuildPipeline;
buildParameters.BuildMode = EBuildMode.IncrementalBuild;
buildParameters.PackageName = "DefaultPackage";
buildParameters.PackageVersion = "1.0";
buildParameters.PackageVersion = packageVersion;
buildParameters.VerifyBuildingResult = true;
buildParameters.SharedPackRule = new ZeroRedundancySharedPackRule();
buildParameters.CompressOption = ECompressOption.LZ4;
buildParameters.CompressOption = ECompressOption.LZMA;
buildParameters.OutputNameStyle = EOutputNameStyle.HashName;
buildParameters.CopyBuildinFileOption = ECopyBuildinFileOption.None;
buildParameters.CopyBuildinFileOption = ECopyBuildinFileOption.ClearAndCopyAll;
buildParameters.SBPParameters = sbpBuildParameters;
// 执行构建
AssetBundleBuilder builder = new AssetBundleBuilder();
var buildResult = builder.Run(buildParameters);
@@ -50,15 +127,66 @@ namespace TEngine
}
}
// 从构建命令里获取参数示例
private static string GetBuildPackageName()
[MenuItem("TEngine/Build/一键打包Windows", false, 30)]
public static void AutomationBuild()
{
foreach (string arg in System.Environment.GetCommandLineArgs())
BuildDLLCommand.BuildAndCopyDlls(BuildTarget.StandaloneWindows64);
AssetDatabase.Refresh();
BuildInternal(BuildTarget.StandaloneWindows64, Application.dataPath + "/../Builds/Windows", "1.0");
AssetDatabase.Refresh();
BuildImp(BuildTargetGroup.Standalone, BuildTarget.StandaloneWindows64, $"{Application.dataPath}/../Builds/Windows/{GetBuildPackageVersion()}Windows.exe");
}
// 构建版本相关
private static string GetBuildPackageVersion()
{
int totalMinutes = DateTime.Now.Hour * 60 + DateTime.Now.Minute;
return DateTime.Now.ToString("yyyy-MM-dd") + "-" + totalMinutes;
}
[MenuItem("TEngine/Build/一键打包Android", false, 30)]
public static void AutomationBuildAndroid()
{
BuildDLLCommand.BuildAndCopyDlls(BuildTarget.Android);
AssetDatabase.Refresh();
BuildInternal(BuildTarget.Android, outputRoot:Application.dataPath + "/../Bundles",packageVersion: GetBuildPackageVersion());
AssetDatabase.Refresh();
BuildImp(BuildTargetGroup.Android, BuildTarget.Android, $"{Application.dataPath}/../Build/Android/{GetBuildPackageVersion()}Android.apk");
}
[MenuItem("TEngine/Build/一键打包IOS", false, 30)]
public static void AutomationBuildIOS()
{
BuildDLLCommand.BuildAndCopyDlls(BuildTarget.iOS);
AssetDatabase.Refresh();
BuildInternal(BuildTarget.iOS, outputRoot:Application.dataPath + "/../Bundles",packageVersion: GetBuildPackageVersion());
AssetDatabase.Refresh();
BuildImp(BuildTargetGroup.iOS, BuildTarget.iOS, $"{Application.dataPath}/../Build/IOS/XCode_Project");
}
public static void BuildImp(BuildTargetGroup buildTargetGroup, BuildTarget buildTarget, string locationPathName)
{
EditorUserBuildSettings.SwitchActiveBuildTarget(buildTargetGroup, BuildTarget.StandaloneWindows64);
AssetDatabase.Refresh();
BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions
{
if (arg.StartsWith("buildPackage"))
return arg.Split("="[0])[1];
scenes = new[] { "Assets/Scenes/main.unity" },
locationPathName = locationPathName,
targetGroup = buildTargetGroup,
target = buildTarget,
options = BuildOptions.None
};
var report = BuildPipeline.BuildPlayer(buildPlayerOptions);
BuildSummary summary = report.summary;
if (summary.result == BuildResult.Succeeded)
{
Debug.Log($"Build success: {summary.totalSize / 1024 / 1024} MB");
}
else
{
Debug.Log($"Build Failed" + summary.result);
}
return string.Empty;
}
}
}

View File

@@ -5,7 +5,9 @@
"GUID:24c092aee38482f4e80715eaa8148782",
"GUID:e34a5702dd353724aa315fb8011f08c3",
"GUID:4d1926c9df5b052469a1c63448b7609a",
"GUID:2373f786d14518f44b0f475db77ba4de"
"GUID:2373f786d14518f44b0f475db77ba4de",
"GUID:6e76b07590314a543b982daed6af2509",
"GUID:478a2357cc57436488a56e564b08d223"
],
"includePlatforms": [
"Editor"

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bf1e53a3963b4dbf8c5f139ee8d80c3d
timeCreated: 1698301726

View File

@@ -0,0 +1,45 @@
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEditor;
/// <summary>
/// 自动绑定全局设置
/// </summary>
public class AutoBindGlobalSetting : ScriptableObject
{
[FolderPath]
[LabelText("默认组件代码保存路径")]
[SerializeField]
private string m_CodePath;
[LabelText("绑定代码命名空间")]
[SerializeField]
private string m_Namespace;
[LabelText("子组件名称(不会往下继续遍历)")]
[SerializeField]
private string m_WidgetName = "m_item";
public string CodePath => m_CodePath;
public string Namespace => m_Namespace;
public string WidgetName => m_WidgetName;
[MenuItem("TEngine/CreateAutoBindGlobalSetting")]
private static void CreateAutoBindGlobalSetting()
{
string[] paths = AssetDatabase.FindAssets("t:AutoBindGlobalSetting");
if (paths.Length >= 1)
{
string path = AssetDatabase.GUIDToAssetPath(paths[0]);
EditorUtility.DisplayDialog("警告", $"已存在AutoBindGlobalSetting路径:{path}", "确认");
return;
}
AutoBindGlobalSetting setting = CreateInstance<AutoBindGlobalSetting>();
AssetDatabase.CreateAsset(setting, "Assets/TEngine/ResRaw/AutoBindGlobalSetting.asset");
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3dac541dae7b4c4d8b5497057739cfb0
timeCreated: 1698304721

View File

@@ -0,0 +1,12 @@
using Sirenix.OdinInspector.Editor;
using UnityEditor;
[CustomEditor(typeof(AutoBindGlobalSetting))]
public class AutoBindGlobalSettingInspector : OdinEditor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.ApplyModifiedProperties();
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 020e5781e8c44c90bfbdf2cb12441e79
timeCreated: 1698304745

View File

@@ -0,0 +1,534 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using BindData = ComponentAutoBindTool.BindData;
using System.Reflection;
using System.IO;
[CustomEditor(typeof(ComponentAutoBindTool))]
public class ComponentAutoBindToolInspector : Editor
{
private ComponentAutoBindTool m_Target;
private SerializedProperty m_BindDatas;
private SerializedProperty m_BindComs;
private List<BindData> m_TempList = new List<BindData>();
private List<string> m_TempFiledNames = new List<string>();
private List<string> m_TempComponentTypeNames = new List<string>();
private string[] s_AssemblyNames = { "Assembly-CSharp", "TEngine.Runtime" };
private string[] m_HelperTypeNames;
private string m_HelperTypeName;
private int m_HelperTypeNameIndex;
private AutoBindGlobalSetting m_Setting;
private SerializedProperty m_Namespace;
private SerializedProperty m_ClassName;
private SerializedProperty m_CodePath;
private SerializedProperty m_IsWidget;
private void OnEnable()
{
m_Target = (ComponentAutoBindTool)target;
m_BindDatas = serializedObject.FindProperty("BindDatas");
m_BindComs = serializedObject.FindProperty("bindComponents");
m_HelperTypeNames = GetTypeNames(typeof(IAutoBindRuleHelper), s_AssemblyNames);
string[] paths = AssetDatabase.FindAssets("t:AutoBindGlobalSetting");
if (paths.Length == 0)
{
Debug.LogError("不存在AutoBindGlobalSetting");
return;
}
if (paths.Length > 1)
{
Debug.LogError("AutoBindGlobalSetting数量大于1");
return;
}
string path = AssetDatabase.GUIDToAssetPath(paths[0]);
m_Setting = AssetDatabase.LoadAssetAtPath<AutoBindGlobalSetting>(path);
m_Namespace = serializedObject.FindProperty("m_Namespace");
m_ClassName = serializedObject.FindProperty("m_ClassName");
m_CodePath = serializedObject.FindProperty("m_CodePath");
m_IsWidget = serializedObject.FindProperty("m_IsWidget");
m_Namespace.stringValue = string.IsNullOrEmpty(m_Namespace.stringValue) ? m_Setting.Namespace : m_Namespace.stringValue;
m_ClassName.stringValue = string.IsNullOrEmpty(m_ClassName.stringValue) ? m_Target.gameObject.name : m_ClassName.stringValue;
m_CodePath.stringValue = string.IsNullOrEmpty(m_CodePath.stringValue) ? m_Setting.CodePath : m_CodePath.stringValue;
serializedObject.ApplyModifiedProperties();
}
public override void OnInspectorGUI()
{
serializedObject.Update();
DrawTopButton();
DrawHelperSelect();
DrawSetting();
DrawKvData();
serializedObject.ApplyModifiedProperties();
}
/// <summary>
/// 绘制顶部按钮
/// </summary>
private void DrawTopButton()
{
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("排序"))
{
Sort();
}
if (GUILayout.Button("全部删除"))
{
RemoveAll();
}
if (GUILayout.Button("删除空引用"))
{
RemoveNull();
}
if (GUILayout.Button("自动绑定组件"))
{
AutoBindComponent();
}
if (GUILayout.Button("生成绑定代码"))
{
GenAutoBindCode();
}
EditorGUILayout.EndHorizontal();
}
/// <summary>
/// 排序
/// </summary>
private void Sort()
{
m_TempList.Clear();
foreach (BindData data in m_Target.BindDatas)
{
m_TempList.Add(new BindData(data.Name, data.BindCom, data.IsGameObject));
}
m_TempList.Sort((x, y) => string.Compare(x.Name, y.Name, StringComparison.Ordinal));
m_BindDatas.ClearArray();
foreach (BindData data in m_TempList)
{
AddBindData(data.Name, data.BindCom, data.IsGameObject);
}
SyncBindComs();
}
/// <summary>
/// 全部删除
/// </summary>
private void RemoveAll()
{
m_BindDatas.ClearArray();
SyncBindComs();
}
/// <summary>
/// 删除空引用
/// </summary>
private void RemoveNull()
{
for (int i = m_BindDatas.arraySize - 1; i >= 0; i--)
{
SerializedProperty element = m_BindDatas.GetArrayElementAtIndex(i).FindPropertyRelative("BindCom");
if (element.objectReferenceValue == null)
{
m_BindDatas.DeleteArrayElementAtIndex(i);
}
}
SyncBindComs();
}
/// <summary>
/// 自动绑定组件
/// </summary>
private void AutoBindComponent()
{
m_BindDatas.ClearArray();
var transform = m_Target.transform;
Ergodic(transform, transform);
SyncBindComs();
}
private void Ergodic(Transform rootTransform, Transform currentTransform)
{
for (int i = 0; i < currentTransform.childCount; ++i)
{
Transform child = currentTransform.GetChild(i);
m_TempFiledNames.Clear();
m_TempComponentTypeNames.Clear();
if (m_Target.RuleHelper.IsValidBind(child, m_TempFiledNames, m_TempComponentTypeNames))
{
for (int index = 0; index < m_TempFiledNames.Count; index++)
{
string componentName = m_TempComponentTypeNames[index];
bool isGameObject = componentName.Equals("GameObject");
componentName = isGameObject ? "Transform" : componentName;
Component com = child.GetComponent(componentName);
if (com == null)
{
Debug.LogError($"{child.name}上不存在{componentName}的组件");
}
else
{
AddBindData(m_TempFiledNames[index], child.GetComponent(componentName), isGameObject);
}
}
}
if (!child.name.StartsWith(m_Setting.WidgetName))
{
Ergodic(rootTransform, child);
}
}
}
/// <summary>
/// 绘制辅助器选择框
/// </summary>
private void DrawHelperSelect()
{
m_HelperTypeName = m_HelperTypeNames[0];
if (m_Target.RuleHelper != null)
{
m_HelperTypeName = m_Target.RuleHelper.GetType().Name;
for (int i = 0; i < m_HelperTypeNames.Length; i++)
{
if (m_HelperTypeName == m_HelperTypeNames[i])
{
m_HelperTypeNameIndex = i;
}
}
}
else
{
IAutoBindRuleHelper helper = (IAutoBindRuleHelper)CreateHelperInstance(m_HelperTypeName, s_AssemblyNames);
m_Target.RuleHelper = helper;
}
foreach (GameObject go in Selection.gameObjects)
{
ComponentAutoBindTool autoBindTool = go.GetComponent<ComponentAutoBindTool>();
if (autoBindTool.RuleHelper == null)
{
IAutoBindRuleHelper helper = (IAutoBindRuleHelper)CreateHelperInstance(m_HelperTypeName, s_AssemblyNames);
autoBindTool.RuleHelper = helper;
}
}
int selectedIndex = EditorGUILayout.Popup("AutoBindRuleHelper", m_HelperTypeNameIndex, m_HelperTypeNames);
if (selectedIndex != m_HelperTypeNameIndex)
{
m_HelperTypeNameIndex = selectedIndex;
m_HelperTypeName = m_HelperTypeNames[selectedIndex];
IAutoBindRuleHelper helper = (IAutoBindRuleHelper)CreateHelperInstance(m_HelperTypeName, s_AssemblyNames);
m_Target.RuleHelper = helper;
}
}
/// <summary>
/// 绘制设置项
/// </summary>
private void DrawSetting()
{
EditorGUILayout.BeginHorizontal();
m_Namespace.stringValue = EditorGUILayout.TextField(new GUIContent("命名空间:"), m_Namespace.stringValue);
if (GUILayout.Button("默认设置"))
{
m_Namespace.stringValue = m_Setting.Namespace;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
m_ClassName.stringValue = EditorGUILayout.TextField(new GUIContent("类名:"), m_ClassName.stringValue);
if (GUILayout.Button("物体名"))
{
m_ClassName.stringValue = m_Target.gameObject.name;
}
EditorGUILayout.EndHorizontal();
bool isWidget = EditorGUILayout.Toggle("是否是组件", m_IsWidget.boolValue);
if (isWidget != m_IsWidget.boolValue)
{
m_IsWidget.boolValue = isWidget;
}
EditorGUILayout.LabelField("代码保存路径:");
EditorGUILayout.LabelField(m_CodePath.stringValue);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("选择路径"))
{
string temp = m_CodePath.stringValue;
m_CodePath.stringValue = EditorUtility.OpenFolderPanel("选择代码保存路径", Application.dataPath, "");
if (string.IsNullOrEmpty(m_CodePath.stringValue))
{
m_CodePath.stringValue = temp;
}
}
if (GUILayout.Button("默认设置"))
{
m_CodePath.stringValue = m_Setting.CodePath;
}
EditorGUILayout.EndHorizontal();
}
/// <summary>
/// 绘制键值对数据
/// </summary>
private void DrawKvData()
{
//绘制key value数据
int needDeleteIndex = -1;
EditorGUILayout.BeginVertical();
SerializedProperty property;
for (int i = 0; i < m_BindDatas.arraySize; i++)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField($"[{i}]", GUILayout.Width(25));
property = m_BindDatas.GetArrayElementAtIndex(i).FindPropertyRelative("Name");
property.stringValue = EditorGUILayout.TextField(property.stringValue, GUILayout.Width(150));
property = m_BindDatas.GetArrayElementAtIndex(i).FindPropertyRelative("BindCom");
property.objectReferenceValue = EditorGUILayout.ObjectField(property.objectReferenceValue, typeof(Component), true);
if (GUILayout.Button("X"))
{
//将元素下标添加进删除list
needDeleteIndex = i;
}
EditorGUILayout.EndHorizontal();
}
//删除data
if (needDeleteIndex != -1)
{
m_BindDatas.DeleteArrayElementAtIndex(needDeleteIndex);
SyncBindComs();
}
EditorGUILayout.EndVertical();
}
/// <summary>
/// 添加绑定数据
/// </summary>
private void AddBindData(string name, Component bindCom, bool isGameObject = false)
{
int index = m_BindDatas.arraySize;
m_BindDatas.InsertArrayElementAtIndex(index);
SerializedProperty element = m_BindDatas.GetArrayElementAtIndex(index);
element.FindPropertyRelative("Name").stringValue = name;
element.FindPropertyRelative("BindCom").objectReferenceValue = bindCom;
element.FindPropertyRelative("IsGameObject").boolValue = isGameObject;
}
/// <summary>
/// 同步绑定数据
/// </summary>
private void SyncBindComs()
{
m_BindComs.ClearArray();
for (int i = 0; i < m_BindDatas.arraySize; i++)
{
SerializedProperty property = m_BindDatas.GetArrayElementAtIndex(i).FindPropertyRelative("BindCom");
m_BindComs.InsertArrayElementAtIndex(i);
m_BindComs.GetArrayElementAtIndex(i).objectReferenceValue = property.objectReferenceValue;
}
}
/// <summary>
/// 获取指定基类在指定程序集中的所有子类名称
/// </summary>
private string[] GetTypeNames(Type typeBase, string[] assemblyNames)
{
List<string> typeNames = new List<string>();
foreach (string assemblyName in assemblyNames)
{
Assembly assembly = null;
try
{
assembly = Assembly.Load(assemblyName);
}
catch
{
continue;
}
if (assembly == null)
{
continue;
}
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
if (type.IsClass && !type.IsAbstract && typeBase.IsAssignableFrom(type))
{
typeNames.Add(type.FullName);
}
}
}
typeNames.Sort();
return typeNames.ToArray();
}
/// <summary>
/// 创建辅助器实例
/// </summary>
private object CreateHelperInstance(string helperTypeName, string[] assemblyNames)
{
foreach (string assemblyName in assemblyNames)
{
Assembly assembly = Assembly.Load(assemblyName);
object instance = assembly.CreateInstance(helperTypeName);
if (instance != null)
{
return instance;
}
}
return null;
}
/// <summary>
/// 生成自动绑定代码
/// </summary>
private void GenAutoBindCode()
{
GameObject go = m_Target.gameObject;
string className = !string.IsNullOrEmpty(m_Target.ClassName) ? m_Target.ClassName : go.name;
string codePath = !string.IsNullOrEmpty(m_Target.CodePath) ? m_Target.CodePath : m_Setting.CodePath;
if (!Directory.Exists(codePath))
{
Debug.LogError($"{go.name}的代码保存路径{codePath}无效");
}
using (StreamWriter sw = new StreamWriter($"{codePath}/{className}.BindComponents.cs"))
{
sw.WriteLine(
"//------------------------------------------------------------------------------\n//\t<auto-generated>\n//\t\tTime:[" + DateTime.Now +
"].\n//\t\tThis code was generated by autoBindTool.\n//\t\tChanges to this file may cause incorrect behavior and will be lost if\n//\t\tthe code is regenerated.\n//\t</auto-generated>\n//------------------------------------------------------------------------------");
sw.WriteLine("using UnityEngine;");
sw.WriteLine("using UnityEngine.UI;");
sw.WriteLine("using TEngine;");
sw.WriteLine("");
if (!string.IsNullOrEmpty(m_Target.Namespace))
{
//命名空间
sw.WriteLine("namespace " + m_Target.Namespace);
sw.WriteLine("{");
}
//类名
// if (!m_Target.IsWidget)
// {
// sw.WriteLine($"\tpublic partial class {className} : UIWindow");
// }
// else
// {
// sw.WriteLine($"\tpublic partial class {className} : UIWidget");
// }
sw.WriteLine($"\tpublic partial class {className}");
sw.WriteLine("\t{");
//组件字段
foreach (BindData data in m_Target.BindDatas)
{
if (data.IsGameObject)
{
sw.WriteLine($"\t\tprivate GameObject m_{data.Name};");
}
else
{
sw.WriteLine($"\t\tprivate {data.BindCom.GetType().Name} m_{data.Name};");
}
}
sw.WriteLine("");
// sw.WriteLine(
// "\t\tpublic override void ScriptGenerator()\n\t\t{\n\t\t\tbase.ScriptGenerator();\n\t\t\tGetBindComponents(transform.gameObject);\n\t\t}");
sw.WriteLine("\t\tprivate void GetBindComponents(GameObject go)");
sw.WriteLine("\t\t{");
//获取autoBindTool上的Component
sw.WriteLine($"\t\t\tComponentAutoBindTool autoBindTool = go.GetComponent<ComponentAutoBindTool>();");
sw.WriteLine("");
//根据索引获取
for (int i = 0; i < m_Target.BindDatas.Count; i++)
{
BindData data = m_Target.BindDatas[i];
string filedName = $"m_{data.Name}";
if (data.IsGameObject)
{
sw.WriteLine($"\t\t\t{filedName} = autoBindTool.GetBindComponent<{data.BindCom.GetType().Name}>({i}).gameObject;");
}
else
{
sw.WriteLine($"\t\t\t{filedName} = autoBindTool.GetBindComponent<{data.BindCom.GetType().Name}>({i});");
}
}
sw.WriteLine("\t\t}");
sw.WriteLine("\t}");
if (!string.IsNullOrEmpty(m_Target.Namespace))
{
sw.WriteLine("}");
}
}
AssetDatabase.Refresh();
EditorUtility.DisplayDialog("提示", "代码生成完毕", "OK");
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 77f2df681a094ff5a14e92e380ba90e7
timeCreated: 1698304775

View File

@@ -1,179 +0,0 @@
using System.Collections.Generic;
using System.Text;
using Sirenix.OdinInspector.Editor;
using TEngine.Editor.UI;
using UnityEditor;
using UnityEngine;
#if UNITY_EDITOR
namespace TEngine
{
[CanEditMultipleObjects]
[CustomEditor(typeof(UIElement), true)]
public class UIElementEditor : OdinEditor
{
protected UIElement Element;
protected override void OnEnable()
{
base.OnEnable();
Element = target as UIElement;
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUI.BeginChangeCheck();
if (GUILayout.Button("Generate", GUILayout.Width(130)))
{
CheckUiItems();
}
serializedObject.ApplyModifiedProperties();
if (EditorGUI.EndChangeCheck())
{
EditorUtility.SetDirty(Element);
}
base.OnInspectorGUI();
}
protected void CheckUiItems()
{
if (Element == null) return;
ClearUnusedItems();
var root = Element.transform;
StringBuilder strVar = new StringBuilder();
StringBuilder strBind = new StringBuilder();
StringBuilder strOnCreate = new StringBuilder();
StringBuilder strOnCreateRedNote = new StringBuilder();
StringBuilder strCallback = new StringBuilder();
Ergodic(root, root, ref strVar, ref strBind, ref strOnCreate, ref strOnCreateRedNote, ref strCallback);
StringBuilder strFile = new StringBuilder();
// 脚本工具生成的代码
strFile.Append("\t\t#region 脚本工具生成的代码\n");
strFile.Append(strVar);
strFile.Append("\t\tpublic override void ScriptGenerator()\n");
strFile.Append("\t\t{\n");
strFile.Append("\t\t\tCheckUIElement();\n");
strFile.Append(strBind);
strFile.Append(strOnCreate);
strFile.Append(strOnCreateRedNote);
strFile.Append("\t\t}\n");
strFile.Append("\t\t#endregion");
TextEditor te = new TextEditor();
te.text = strFile.ToString();
te.SelectAll();
te.Copy();
}
private void ClearUnusedItems()
{
if (Element == null || Element.Elements == null) return;
List<string> ids = new List<string>();
foreach (var kv in Element.Elements)
{
if (kv.Value == null || !string.IsNullOrEmpty(GetVerType(kv.Key)))
{
ids.Add(kv.Key);
}
}
foreach (var id in ids)
{
Element.Elements.Remove(id);
}
}
private void Ergodic(Transform root, Transform transform, ref StringBuilder strVar, ref StringBuilder strBind, ref StringBuilder strOnCreate,
ref StringBuilder strOnCreateRedNote, ref StringBuilder strCallback)
{
for (int i = 0; i < transform.childCount; ++i)
{
Transform child = transform.GetChild(i);
WriteScript(root, child, ref strVar, ref strBind, ref strOnCreate, ref strOnCreateRedNote, ref strCallback);
if (child.name.StartsWith("m_item"))
{
continue;
}
Ergodic(root, child, ref strVar, ref strBind, ref strOnCreate, ref strOnCreateRedNote, ref strCallback);
}
}
private void WriteScript(Transform root, Transform child, ref StringBuilder strVar, ref StringBuilder strBind, ref StringBuilder strOnCreate,
ref StringBuilder strOnCreateRedNote, ref StringBuilder strCallback)
{
var varName = child.name;
var varType = GetVerType(varName);
if (varType == string.Empty) return;
if (Element.Elements.Contains(varName))
{
Debug.LogError("有重复的key:" + varName);
return;
}
Element.Elements[varName] = child;
if (!string.IsNullOrEmpty(varName))
{
strVar.Append("\t\tprivate " + varType + " " + varName + ";\n");
switch (varType)
{
case "Transform":
strBind.Append($"\t\t\t{varName} = FChild(\"{varName}\");\n");
break;
case "GameObject":
strBind.Append($"\t\t\t{varName} = FChild(\"{varName}\").gameObject;\n");
break;
case "RichItemIcon":
strBind.Append($"\t\t\t{varName} = CreateWidgetByType<{varType}>(FChild(\"{varName}\"));\n");
break;
case "RedNoteWidget":
break;
case "TextButtonItem":
case "SwitchTabItem":
case "UIActorWidget":
case "UIEffectWidget":
case "UISpineWidget":
case "UIMainPlayerWidget":
strBind.Append($"\t\t\t{varName} = CreateWidget<{varType}>(FChild(\"{varName}\").gameObject);\n");
break;
default:
strBind.Append($"\t\t\t{varName} = FChild<{varType}>(\"{varName}\");\n");
break;
}
if (varType == "Button")
{
string varFuncName = ScriptGenerator.GetBtnFuncName(varName);
strOnCreate.Append($"\t\t\t{varName}.onClick.AddListener({varFuncName});\n");
strCallback.Append($"\t\tprivate void {varFuncName}()\n");
strCallback.Append("\t\t{\n\t\t}\n");
}
else if (varType == "Toggle")
{
string varFuncName = ScriptGenerator.GetToggleFuncName(varName);
strOnCreate.Append($"\t\t\t{varName}.onValueChanged.AddListener({varFuncName});\n");
strCallback.Append($"\t\tprivate void {varFuncName}(bool isOn)\n");
strCallback.Append("\t\t{\n\t\t}\n");
}
}
}
protected string GetVerType(string uiName)
{
foreach (var pair in SettingsUtils.GetScriptGenerateRule())
{
if (uiName.StartsWith(pair.uiElementRegex))
{
return pair.componentName;
}
}
return string.Empty;
}
}
}
#endif

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 02ba9976b78c4a079e16aa9302c1b43e
timeCreated: 1696659319

View File

@@ -19,6 +19,21 @@ namespace TEngine.Editor
{
return false;
}
// 获取资源路径
string assetPath = AssetDatabase.GetAssetPath(instanceID);
// 判断资源类型
if (!assetPath.EndsWith(".cs"))
{
return false;
}
bool autoFirstMatch = assetPath.Contains("Logger.cs") ||
assetPath.Contains("DefaultLogHelper.cs") ||
assetPath.Contains("GameFrameworkLog.cs") ||
assetPath.Contains("AssetsLogger.cs") ||
assetPath.Contains("Log.cs");
var stackTrace = GetStackTrace();
if (!string.IsNullOrEmpty(stackTrace) && (stackTrace.Contains("[Debug]") ||
stackTrace.Contains("[INFO]") ||
@@ -28,6 +43,15 @@ namespace TEngine.Editor
stackTrace.Contains("[EXCEPTION]")))
{
if (!autoFirstMatch)
{
var fullPath = UnityEngine.Application.dataPath.Substring(0, UnityEngine.Application.dataPath.LastIndexOf("Assets", StringComparison.Ordinal));
fullPath = $"{fullPath}{assetPath}";
// 跳转到目标代码的特定行
InternalEditorUtility.OpenFileAtLineExternal(fullPath.Replace('/', '\\'), line);
return true;
}
// 使用正则表达式匹配at的哪个脚本的哪一行
var matches = Regex.Match(stackTrace, @"\(at (.+)\)",
RegexOptions.IgnoreCase);

View File

@@ -0,0 +1,17 @@
%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: 3dac541dae7b4c4d8b5497057739cfb0, type: 3}
m_Name: AutoBindGlobalSetting
m_EditorClassIdentifier:
m_CodePath: Assets/GameScripts
m_Namespace: GameLogic
m_WidgetName: m_item

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: eb33bb9d9cdf9484997cc91b0517ba4d
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,120 @@
using System.Collections.Generic;
namespace TEngine
{
/// <summary>
/// 游戏框架字典类。
/// </summary>
/// <typeparam name="TKey">指定字典Key的元素类型。</typeparam>
/// <typeparam name="TValue">指定字典Value的元素类型。</typeparam>
public class GameFrameworkDictionary<TKey, TValue>
{
protected readonly List<TKey> KeyList = new List<TKey>();
protected readonly Dictionary<TKey, TValue> Dictionary = new Dictionary<TKey, TValue>();
/// <summary>
/// 存储键的列表。
/// </summary>
public List<TKey> Keys => KeyList;
/// <summary>
/// 存储字典实例。
/// </summary>
public int Count => KeyList.Count;
/// <summary>
/// 通过KEY的数组下标获取元素。
/// </summary>
/// <param name="index">下标。</param>
/// <returns>TValue。</returns>
public TValue GetValueByIndex(int index)
{
return Dictionary[KeyList[index]];
}
/// <summary>
/// 通过KEY的数组下标设置元素。
/// </summary>
/// <param name="index">下标。</param>
/// <param name="item">TValue。</param>
public void SetValue(int index, TValue item)
{
Dictionary[KeyList[index]] = item;
}
/// <summary>
/// 字典索引器。
/// </summary>
/// <param name="key">TKey。</param>
public TValue this[TKey key]
{
get => Dictionary[key];
set
{
if (!ContainsKey(key))
{
Add(key, value);
}
else
{
Dictionary[key] = value;
}
}
}
/// <summary>Removes all keys and values from the <see cref="T:TEngine.GameFrameworkDictionary`2" />.</summary>
public void Clear()
{
KeyList.Clear();
Dictionary.Clear();
}
/// <summary>Adds the specified key and value to the dictionary.</summary>
/// <param name="key">The key of the element to add.</param>
/// <param name="item">The value of the element to add. The value can be <see langword="null" /> for reference types.</param>
public virtual void Add(TKey key, TValue item)
{
KeyList.Add(key);
Dictionary.Add(key, item);
}
/// <summary>Gets the value associated with the specified key.</summary>
/// <param name="key">The key of the value to get.</param>
/// <param name="value">When this method returns, contains the value associated with the specified key, if the key is found; otherwise, the default value for the type of the <paramref name="value" /> parameter. This parameter is passed uninitialized.</param>
public bool TryGetValue(TKey key, out TValue value)
{
return Dictionary.TryGetValue(key, out value);
}
/// <summary>Determines whether the <see cref="T:System.Collections.Generic.Dictionary`2" /> contains the specified key.</summary>
/// <param name="key">The key to locate in the </param>
public bool ContainsKey(TKey key)
{
return Dictionary.ContainsKey(key);
}
public TKey GetKey(int index)
{
return KeyList[index];
}
public bool Remove(TKey key)
{
return KeyList.Remove(key) && Dictionary.Remove(key);
}
}
/// <summary>
/// 游戏框架顺序字典类。
/// </summary>
/// <typeparam name="TKey">指定字典Key的元素类型。</typeparam>
/// <typeparam name="TValue">指定字典Value的元素类型。</typeparam>
public class GameFrameworkSortedDictionary<TKey, TValue> : GameFrameworkDictionary<TKey, TValue>
{
public override void Add(TKey key, TValue item)
{
base.Add(key, item);
KeyList.Sort();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3df785fede30420dbfa6acb2ff48c166
timeCreated: 1698296076

View File

@@ -0,0 +1,644 @@
using System;
using System.Collections.Generic;
#region Class Documentation
/************************************************************************************************************
Class Name: ActorEventDispatcher.cs 局部单位事件分发器。
Type: Actor, Event
Example:
private ActorEventDispatcher _event;
/// <summary>
/// 局部事件管理器。
/// <remark>只分发和监听这个Event内部的事件</remark>
/// </summary>
public ActorEventDispatcher Event => _event ??= MemoryPool.Acquire<ActorEventDispatcher>();
// owner局部发送事件。
owner.Event.Send(eventId,xxx);
// owner监听自身事件并绑定持有对象为owner。 比如是组件的情况下。移除时调用RemoveAllListenerByOwner(owner)会根据持有对象(组件)移除。
owner.Event.AddEventListener(eventId,xxx,owner);
************************************************************************************************************/
#endregion
namespace TEngine
{
/// <summary>
/// 局部单位事件分发器。
/// </summary>
public class ActorEventDispatcher : IMemory
{
/// <summary>
/// 所有事件。
/// </summary>
private readonly Dictionary<int, List<EventRegInfo>> _allEventListenerMap;
/// <summary>
/// 用于标记一个事件是不是正在处理。
/// </summary>
private readonly List<int> _processEventList;
/// <summary>
/// 用于标记一个事件是不是被移除。
/// </summary>
private readonly List<int> _delayDeleteEventList;
public ActorEventDispatcher()
{
_processEventList = new List<int>();
_delayDeleteEventList = new List<int>();
_allEventListenerMap = new Dictionary<int, List<EventRegInfo>>();
}
/// <summary>
/// 移除所有事件监听。
/// </summary>
public void DestroyAllEventListener()
{
var itr = _allEventListenerMap.GetEnumerator();
while (itr.MoveNext())
{
var kv = itr.Current;
List<EventRegInfo> list = kv.Value;
foreach (var eventRegInfo in list)
{
EventRegInfo.Release(eventRegInfo);
}
kv.Value.Clear();
}
_processEventList.Clear();
_delayDeleteEventList.Clear();
itr.Dispose();
}
/// <summary>
/// 延迟移除事件。
/// </summary>
/// <param name="eventId"></param>
private void AddDelayDelete(int eventId)
{
if (!_delayDeleteEventList.Contains(eventId))
{
_delayDeleteEventList.Add(eventId);
Log.Info("delay delete eventId[{0}]", eventId);
}
}
/// <summary>
/// 如果找到eventId对应的监听删除所有标记为delete的监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
private void CheckDelayDelete(int eventId)
{
if (_delayDeleteEventList.Contains(eventId))
{
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
{
for (int i = 0; i < listListener.Count; i++)
{
if (listListener[i].IsDeleted)
{
Log.Info("remove delay delete eventId[{0}]", eventId);
listListener[i] = listListener[^1];
EventRegInfo.Release(listListener[i]);
listListener.RemoveAt(listListener.Count - 1);
i--;
}
}
}
_delayDeleteEventList.Remove(eventId);
}
}
/// <summary>
/// 发送事件。
/// </summary>
/// <param name="eventId">事件Id。</param>
public void SendEvent(int eventId)
{
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
{
_processEventList.Add(eventId);
#if UNITY_EDITOR
int iEventCnt = _processEventList.Count;
#endif
var count = listListener.Count;
for (int i = 0; i < count; i++)
{
var node = listListener[i];
if (node.IsDeleted)
{
continue;
}
if (listListener[i].Callback is Action callBack)
{
callBack();
}
else
{
Log.Fatal("Invalid event data type: {0}", eventId);
}
}
#if UNITY_EDITOR
Log.Assert(iEventCnt == _processEventList.Count);
Log.Assert(eventId == _processEventList[^1]);
#endif
_processEventList.RemoveAt(_processEventList.Count - 1);
CheckDelayDelete(eventId);
}
}
/// <summary>
/// 发送事件。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="arg1">事件参数。</param>
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
public void SendEvent<TArg1>(int eventId, TArg1 arg1)
{
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
{
_processEventList.Add(eventId);
#if UNITY_EDITOR
int iEventCnt = _processEventList.Count;
#endif
var count = listListener.Count;
for (int i = 0; i < count; i++)
{
var node = listListener[i];
if (node.IsDeleted)
{
continue;
}
if (listListener[i].Callback is Action<TArg1> callBack)
{
callBack(arg1);
}
else
{
Log.Fatal("Invalid event data type: {0}", eventId);
}
}
#if UNITY_EDITOR
Log.Assert(iEventCnt == _processEventList.Count);
Log.Assert(eventId == _processEventList[^1]);
#endif
_processEventList.RemoveAt(_processEventList.Count - 1);
CheckDelayDelete(eventId);
}
}
/// <summary>
/// 发送事件。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="arg1">事件参数1。</param>
/// <param name="arg2">事件参数2。</param>
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
/// <typeparam name="TArg2">事件参数类型2。</typeparam>
public void SendEvent<TArg1, TArg2>(int eventId, TArg1 arg1, TArg2 arg2)
{
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
{
_processEventList.Add(eventId);
#if UNITY_EDITOR
int iEventCnt = _processEventList.Count;
#endif
var count = listListener.Count;
for (int i = 0; i < count; i++)
{
var node = listListener[i];
if (node.IsDeleted)
{
continue;
}
if (listListener[i].Callback is Action<TArg1, TArg2> callBack)
{
callBack(arg1, arg2);
}
else
{
Log.Fatal("Invalid event data type: {0}", eventId);
}
}
#if UNITY_EDITOR
Log.Assert(iEventCnt == _processEventList.Count);
Log.Assert(eventId == _processEventList[^1]);
#endif
_processEventList.RemoveAt(_processEventList.Count - 1);
CheckDelayDelete(eventId);
}
}
/// <summary>
/// 发送事件。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="arg1">事件参数1。</param>
/// <param name="arg2">事件参数2。</param>
/// <param name="arg3">事件参数3。</param>
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
/// <typeparam name="TArg2">事件参数类型2。</typeparam>
/// <typeparam name="TArg3">事件参数类型3。</typeparam>
public void SendEvent<TArg1, TArg2, TArg3>(int eventId, TArg1 arg1, TArg2 arg2, TArg3 arg3)
{
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
{
_processEventList.Add(eventId);
#if UNITY_EDITOR
int iEventCnt = _processEventList.Count;
#endif
var count = listListener.Count;
for (int i = 0; i < count; i++)
{
var node = listListener[i];
if (node.IsDeleted)
{
continue;
}
if (node.Callback is Action<TArg1, TArg2, TArg3> callBack)
{
callBack(arg1, arg2, arg3);
}
else
{
Log.Fatal("Invalid event data type: {0}", eventId);
}
}
#if UNITY_EDITOR
Log.Assert(iEventCnt == _processEventList.Count);
Log.Assert(eventId == _processEventList[^1]);
#endif
_processEventList.RemoveAt(_processEventList.Count - 1);
CheckDelayDelete(eventId);
}
}
/// <summary>
/// 发送事件。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="arg1">事件参数1。</param>
/// <param name="arg2">事件参数2。</param>
/// <param name="arg3">事件参数3。</param>
/// <param name="arg4">事件参数4。</param>
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
/// <typeparam name="TArg2">事件参数类型2。</typeparam>
/// <typeparam name="TArg3">事件参数类型3。</typeparam>
/// <typeparam name="TArg4">事件参数类型4。</typeparam>
public void SendEvent<TArg1, TArg2, TArg3, TArg4>(int eventId, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4)
{
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
{
_processEventList.Add(eventId);
#if UNITY_EDITOR
int iEventCnt = _processEventList.Count;
#endif
var count = listListener.Count;
for (int i = 0; i < count; i++)
{
var node = listListener[i];
if (node.IsDeleted)
{
continue;
}
if (listListener[i].Callback is Action<TArg1, TArg2, TArg3, TArg4> callBack)
{
callBack(arg1, arg2, arg3, arg4);
}
else
{
Log.Fatal("Invalid event data type: {0}", eventId);
}
}
#if UNITY_EDITOR
Log.Assert(iEventCnt == _processEventList.Count);
Log.Assert(eventId == _processEventList[^1]);
#endif
_processEventList.RemoveAt(_processEventList.Count - 1);
CheckDelayDelete(eventId);
}
}
/// <summary>
/// 增加事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">事件回调。</param>
/// <param name="owner">持有者Tag。</param>
public void AddEventListener(int eventId, Action eventCallback, object owner)
{
AddEventListenerImp(eventId, eventCallback, owner);
}
/// <summary>
/// 增加事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">事件回调。</param>
/// <param name="owner">持有者Tag。</param>
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
public void AddEventListener<TArg1>(int eventId, Action<TArg1> eventCallback, object owner)
{
AddEventListenerImp(eventId, eventCallback, owner);
}
/// <summary>
/// 增加事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">事件回调。</param>
/// <param name="owner">持有者Tag。</param>
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
/// <typeparam name="TArg2">事件参数类型2。</typeparam>
public void AddEventListener<TArg1, TArg2>(int eventId, Action<TArg1, TArg2> eventCallback, object owner)
{
AddEventListenerImp(eventId, eventCallback, owner);
}
/// <summary>
/// 增加事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">事件回调。</param>
/// <param name="owner">持有者Tag。</param>
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
/// <typeparam name="TArg2">事件参数类型2。</typeparam>
/// <typeparam name="TArg3">事件参数类型3。</typeparam>
public void AddEventListener<TArg1, TArg2, TArg3>(int eventId, Action<TArg1, TArg2, TArg3> eventCallback, object owner)
{
AddEventListenerImp(eventId, eventCallback, owner);
}
/// <summary>
/// 增加事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">事件回调。</param>
/// <param name="owner">持有者Tag。</param>
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
/// <typeparam name="TArg2">事件参数类型2。</typeparam>
/// <typeparam name="TArg3">事件参数类型3。</typeparam>
/// <typeparam name="TArg4">事件参数类型4。</typeparam>
public void AddEventListener<TArg1, TArg2, TArg3, TArg4>(int eventId, Action<TArg1, TArg2, TArg3, TArg4> eventCallback, object owner)
{
AddEventListenerImp(eventId, eventCallback, owner);
}
/// <summary>
/// 增加事件监听具体实现。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="listener">事件回调。</param>
/// <param name="owner">持有者Tag。</param>
private void AddEventListenerImp(int eventId, Delegate listener, object owner)
{
if (!_allEventListenerMap.TryGetValue(eventId, out var listListener))
{
listListener = new List<EventRegInfo>();
_allEventListenerMap.Add(eventId, listListener);
}
var existNode = listListener.Find((node) => node.Callback == listener);
if (existNode != null)
{
if (existNode.IsDeleted)
{
existNode.IsDeleted = false;
Log.Warning("AddEvent hashId deleted, repeat add: {0}", eventId);
return;
}
Log.Fatal("AddEvent hashId repeated: {0}", eventId);
return;
}
listListener.Add(EventRegInfo.Alloc(listener, owner));
}
/// <summary>
/// 通过持有者Tag移除监听。
/// </summary>
/// <param name="owner">持有者Tag。</param>
public void RemoveAllListenerByOwner(object owner)
{
var itr = _allEventListenerMap.GetEnumerator();
while (itr.MoveNext())
{
var kv = itr.Current;
var list = kv.Value;
int eventId = kv.Key;
bool isProcessing = _processEventList.Contains(eventId);
bool delayDeleted = false;
for (int i = 0; i < list.Count; i++)
{
var regInfo = list[i];
if (regInfo.Owner == owner)
{
if (isProcessing)
{
regInfo.IsDeleted = true;
delayDeleted = true;
}
else
{
list[i] = list[^1];
EventRegInfo.Release(list[i]);
list.RemoveAt(list.Count - 1);
i--;
}
}
}
if (delayDeleted)
{
AddDelayDelete(eventId);
}
}
itr.Dispose();
}
/// <summary>
/// 移除事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">消息回调。</param>
public void RemoveEventListener(int eventId, Action eventCallback)
{
RemoveEventListenerImp(eventId, eventCallback);
}
/// <summary>
/// 移除事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">消息回调。</param>
/// <typeparam name="TArg1">参数类型1。</typeparam>
public void RemoveEventListener<TArg1>(int eventId, Action<TArg1> eventCallback)
{
RemoveEventListenerImp(eventId, eventCallback);
}
/// <summary>
/// 移除事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">消息回调。</param>
/// <typeparam name="TArg1">参数类型1。</typeparam>
/// <typeparam name="TArg2">参数类型2。</typeparam>
public void RemoveEventListener<TArg1, TArg2>(int eventId, Action<TArg1, TArg2> eventCallback)
{
RemoveEventListenerImp(eventId, eventCallback);
}
/// <summary>
/// 移除事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">消息回调。</param>
/// <typeparam name="TArg1">参数类型1。</typeparam>
/// <typeparam name="TArg2">参数类型2。</typeparam>
/// <typeparam name="TArg3">参数类型3。</typeparam>
public void RemoveEventListener<TArg1, TArg2, TArg3>(int eventId, Action<TArg1, TArg2, TArg3> eventCallback)
{
RemoveEventListenerImp(eventId, eventCallback);
}
/// <summary>
/// 移除事件监听。
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="eventCallback">消息回调。</param>
/// <typeparam name="TArg1">参数类型1。</typeparam>
/// <typeparam name="TArg2">参数类型2。</typeparam>
/// <typeparam name="TArg3">参数类型3。</typeparam>
/// <typeparam name="TArg4">参数类型4。</typeparam>
public void RemoveEventListener<TArg1, TArg2, TArg3, TArg4>(int eventId, Action<TArg1, TArg2, TArg3, TArg4> eventCallback)
{
RemoveEventListenerImp(eventId, eventCallback);
}
/// <summary>
/// 删除监听,如果是正在处理的监听则标记为删除
/// </summary>
/// <param name="eventId">事件Id。</param>
/// <param name="listener">事件监听。</param>
protected void RemoveEventListenerImp(int eventId, Delegate listener)
{
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
{
bool isProcessing = _processEventList.Contains(eventId);
if (!isProcessing)
{
listListener.RemoveAll(node => node.Callback == listener);
}
else
{
int listenCnt = listListener.Count;
for (int i = 0; i < listenCnt; i++)
{
var node = listListener[i];
if (node.Callback == listener)
{
node.IsDeleted = true;
AddDelayDelete(eventId);
break;
}
}
}
}
}
/// <summary>
/// 清除回收接口。
/// </summary>
public void Clear()
{
DestroyAllEventListener();
}
}
/// <summary>
/// 事件注册信息。
/// </summary>
public class EventRegInfo : IMemory
{
/// <summary>
/// 事件回调。
/// </summary>
public Delegate Callback;
/// <summary>
/// 事件持有者。
/// </summary>
public object Owner;
/// <summary>
/// 事件是否删除。
/// </summary>
public bool IsDeleted;
public EventRegInfo(Delegate callback, object owner)
{
this.Callback = callback;
Owner = owner;
IsDeleted = false;
}
public EventRegInfo() { }
public void Clear()
{
Callback = null;
Owner = null;
IsDeleted = false;
}
public static EventRegInfo Alloc(Delegate callback, object owner)
{
EventRegInfo ret = MemoryPool.Acquire<EventRegInfo>();
ret.Callback = callback;
ret.Owner = owner;
ret.IsDeleted = false;
return ret;
}
public static void Release(EventRegInfo eventRegInfo)
{
MemoryPool.Release(eventRegInfo);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 222c2a26f3b14d42950d0e9a10b61b38
timeCreated: 1673511406

View File

@@ -19,10 +19,11 @@ namespace TEngine
}
[System.AttributeUsage(System.AttributeTargets.Interface)]
public class EventInterface : Attribute
public class EventInterfaceAttribute : Attribute
{
private EEventGroup _eGroup;
public EventInterface(EEventGroup group)
public EEventGroup EventGroup => _eGroup;
public EventInterfaceAttribute(EEventGroup group)
{
_eGroup = group;
}

View File

@@ -50,6 +50,21 @@ namespace TEngine
_eventEntryMap.Add(typeName, entry);
}
}
/// <summary>
/// 注册wrap的函数。
/// </summary>
/// <param name="typeName">类型名称。</param>
/// <param name="callerWrap">调用接口名。</param>
public void RegWrapInterface(string typeName,object callerWrap)
{
var entry = new EventEntryData();
entry.InterfaceWrap = callerWrap;
if (typeName != null)
{
_eventEntryMap.Add(typeName, entry);
}
}
/// <summary>
/// 分发注册器。

View File

@@ -12,6 +12,7 @@ namespace TEngine
/// </summary>
private static readonly EventMgr _eventMgr = new EventMgr();
public static EventMgr EventMgr => _eventMgr;
#region
/// <summary>

View File

@@ -0,0 +1,57 @@
using System;
namespace TEngine
{
/// <summary>
/// 内存池对象基类。
/// </summary>
public abstract class MemoryObject : IMemory
{
/// <summary>
/// 清理内存对象回收入池。
/// </summary>
public virtual void Clear()
{
}
/// <summary>
/// 从内存池中初始化。
/// </summary>
public abstract void InitFromPool();
/// <summary>
/// 回收到内存池。
/// </summary>
public abstract void RecycleToPool();
}
public static partial class MemoryPool
{
/// <summary>
/// 从内存池获取内存对象。
/// </summary>
/// <typeparam name="T">内存对象类型。</typeparam>
/// <returns>内存对象。</returns>
public static T Alloc<T>() where T : MemoryObject, new()
{
T memory = Acquire<T>();
memory.InitFromPool();
return memory;
}
/// <summary>
/// 将内存对象归还内存池。
/// </summary>
/// <param name="memory">内存对象。</param>
public static void Dealloc(MemoryObject memory)
{
if (memory == null)
{
throw new Exception("Memory is invalid.");
}
memory.RecycleToPool();
Release(memory);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ad13ef73c22340058c4420733a22b580
timeCreated: 1701273442

View File

@@ -1,7 +1,9 @@
using System;
using System.IO;
using System.Text;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
namespace TEngine

View File

@@ -25,7 +25,7 @@ namespace TEngine
var cts = new CancellationTokenSource();
cts.CancelAfterSlim(TimeSpan.FromSeconds(timeout));
UnityWebRequest unityWebRequest = UnityWebRequest.Get(url);
using UnityWebRequest unityWebRequest = UnityWebRequest.Get(url);
return await SendWebRequest(unityWebRequest, cts);
}
@@ -41,7 +41,7 @@ namespace TEngine
var cts = new CancellationTokenSource();
cts.CancelAfterSlim(TimeSpan.FromSeconds(timeout));
UnityWebRequest unityWebRequest = UnityWebRequest.Post(url, postData);
using UnityWebRequest unityWebRequest = UnityWebRequest.Post(url, postData);
return await SendWebRequest(unityWebRequest, cts);
}
@@ -57,7 +57,7 @@ namespace TEngine
var cts = new CancellationTokenSource();
cts.CancelAfterSlim(TimeSpan.FromSeconds(timeout));
UnityWebRequest unityWebRequest = UnityWebRequest.Post(url, formFields);
using UnityWebRequest unityWebRequest = UnityWebRequest.Post(url, formFields);
return await SendWebRequest(unityWebRequest, cts);
}
@@ -73,7 +73,7 @@ namespace TEngine
var cts = new CancellationTokenSource();
cts.CancelAfterSlim(TimeSpan.FromSeconds(timeout));
UnityWebRequest unityWebRequest = UnityWebRequest.Post(url, formData);
using UnityWebRequest unityWebRequest = UnityWebRequest.Post(url, formData);
return await SendWebRequest(unityWebRequest, cts);
}
@@ -91,6 +91,8 @@ namespace TEngine
if (isCanceled)
{
Log.Warning($"HttpPost {unityWebRequest.url} be canceled!");
unityWebRequest.Dispose();
return string.Empty;
}
}
catch (OperationCanceledException ex)
@@ -98,11 +100,14 @@ namespace TEngine
if (ex.CancellationToken == cts.Token)
{
Log.Warning("HttpPost Timeout");
unityWebRequest.Dispose();
return string.Empty;
}
}
return unityWebRequest.downloadHandler.text;
string ret = unityWebRequest.downloadHandler.text;
unityWebRequest.Dispose();
return ret;
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Internal;
@@ -108,6 +109,12 @@ namespace TEngine
public static void AddUpdateListener(UnityAction fun)
{
_MakeEntity();
AddUpdateListenerImp(fun).Forget();
}
private static async UniTaskVoid AddUpdateListenerImp(UnityAction fun)
{
await UniTask.Yield(/*PlayerLoopTiming.LastPreUpdate*/);
_behaviour.AddUpdateListener(fun);
}
@@ -118,6 +125,12 @@ namespace TEngine
public static void AddFixedUpdateListener(UnityAction fun)
{
_MakeEntity();
AddFixedUpdateListenerImp(fun).Forget();
}
private static async UniTaskVoid AddFixedUpdateListenerImp(UnityAction fun)
{
await UniTask.Yield(PlayerLoopTiming.LastEarlyUpdate);
_behaviour.AddFixedUpdateListener(fun);
}
@@ -128,6 +141,12 @@ namespace TEngine
public static void AddLateUpdateListener(UnityAction fun)
{
_MakeEntity();
AddLateUpdateListenerImp(fun).Forget();
}
private static async UniTaskVoid AddLateUpdateListenerImp(UnityAction fun)
{
await UniTask.Yield(/*PlayerLoopTiming.LastPreLateUpdate*/);
_behaviour.AddLateUpdateListener(fun);
}
@@ -225,15 +244,6 @@ namespace TEngine
}
#endregion
/// <summary>
/// 释放Behaviour生命周期。
/// </summary>
public static void Release()
{
_MakeEntity();
_behaviour.Release();
}
private static void _MakeEntity()
{
if (_entity != null)
@@ -241,23 +251,30 @@ namespace TEngine
return;
}
_entity = new GameObject("__MonoUtility__")
{
hideFlags = HideFlags.HideAndDontSave
};
_entity = new GameObject("[Unity.Utility]");
_entity.SetActive(true);
#if UNITY_EDITOR
if (Application.isPlaying)
#endif
{
Object.DontDestroyOnLoad(_entity);
}
_entity.transform.SetParent(GameModule.Base.transform);
UnityEngine.Assertions.Assert.IsFalse(_behaviour);
_behaviour = _entity.AddComponent<MainBehaviour>();
}
/// <summary>
/// 释放Behaviour生命周期。
/// </summary>
public static void Shutdown()
{
if (_behaviour != null)
{
_behaviour.Release();
}
if (_entity != null)
{
Object.Destroy(_entity);
}
_entity = null;
}
private class MainBehaviour : MonoBehaviour
{
private event UnityAction UpdateEvent;

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngineInternal;
@@ -132,7 +133,10 @@ namespace TEngine
/// <param name="spriteName">图片名称。</param>
/// <param name="isSetNativeSize">是否使用原生分辨率。</param>
/// <param name="isAsync">是否使用异步加载。</param>
public static void SetSprite(this UnityEngine.UI.Image image, string spriteName, bool isSetNativeSize = false, bool isAsync = false)
/// <param name="customPackageName">指定资源包的名称。不传使用默认资源包</param>
/// <param name="assetReference">指定资源引用组。</param>
public static void SetSprite(this UnityEngine.UI.Image image, string spriteName, bool isSetNativeSize = false,
bool isAsync = false, string customPackageName = "",AssetReference assetReference = null)
{
if (image == null)
{
@@ -147,11 +151,21 @@ namespace TEngine
{
if (!isAsync)
{
image.sprite = GameModule.Resource.LoadAsset<Sprite>(spriteName);
var operation = GameModule.Resource.LoadAssetGetOperation<Sprite>(spriteName, customPackageName: customPackageName);
image.sprite = operation.AssetObject as Sprite;
if (isSetNativeSize)
{
image.SetNativeSize();
}
if (assetReference != null)
{
assetReference.Reference(operation, spriteName);
}
else
{
image.gameObject.GetOrAddComponent<AssetReference>().Reference(operation, spriteName);
}
}
else
{
@@ -159,6 +173,8 @@ namespace TEngine
{
if (image == null)
{
operation.Dispose();
operation = null;
return;
}
@@ -167,7 +183,17 @@ namespace TEngine
{
image.SetNativeSize();
}
});
image.sprite = operation.AssetObject as Sprite;
if (assetReference != null)
{
assetReference.Reference(operation, spriteName);
}
else
{
image.gameObject.GetOrAddComponent<AssetReference>().Reference(operation, spriteName);
}
}, customPackageName: customPackageName);
}
}
}
@@ -178,7 +204,10 @@ namespace TEngine
/// <param name="spriteRenderer">Image组件。</param>
/// <param name="spriteName">图片名称。</param>
/// <param name="isAsync">是否使用异步加载。</param>
public static void SetSprite(this SpriteRenderer spriteRenderer, string spriteName, bool isAsync = false)
/// <param name="customPackageName">指定资源包的名称。不传使用默认资源包</param>
/// <param name="assetReference">指定资源引用组。</param>
public static void SetSprite(this SpriteRenderer spriteRenderer, string spriteName, bool isAsync = false,
string customPackageName = "",AssetReference assetReference = null)
{
if (spriteRenderer == null)
{
@@ -193,7 +222,17 @@ namespace TEngine
{
if (!isAsync)
{
spriteRenderer.sprite = GameModule.Resource.LoadAsset<Sprite>(spriteName);
var operation = GameModule.Resource.LoadAssetGetOperation<Sprite>(spriteName, customPackageName: customPackageName);
spriteRenderer.sprite = operation.AssetObject as Sprite;
if (assetReference != null)
{
assetReference.Reference(operation, spriteName);
}
else
{
spriteRenderer.gameObject.GetOrAddComponent<AssetReference>().Reference(operation, spriteName);
}
}
else
{
@@ -201,15 +240,25 @@ namespace TEngine
{
if (spriteRenderer == null)
{
operation.Dispose();
operation = null;
return;
}
spriteRenderer.sprite = operation.AssetObject as Sprite;
});
if (assetReference != null)
{
assetReference.Reference(operation, spriteName);
}
else
{
spriteRenderer.gameObject.GetOrAddComponent<AssetReference>().Reference(operation, spriteName);
}
}, customPackageName: customPackageName);
}
}
}
/// <summary>
/// 查找子节点。
/// </summary>
@@ -221,7 +270,7 @@ namespace TEngine
var findTrans = transform.Find(path);
return findTrans != null ? findTrans : null;
}
/// <summary>
/// 根据名字找到子节点主要用于dummy接口。
/// </summary>
@@ -252,7 +301,7 @@ namespace TEngine
return null;
}
[TypeInferenceRule(TypeInferenceRules.TypeReferencedByFirstArgument)]
public static Component FindChildComponent(this Type type, Transform transform, string path)
{
@@ -264,7 +313,7 @@ namespace TEngine
return null;
}
public static T FindChildComponent<T>(this Transform transform, string path) where T : Component
{
var findTrans = transform.Find(path);
@@ -275,5 +324,72 @@ namespace TEngine
return null;
}
public static AssetReference GetAssetReference(this GameObject gameObject)
{
if (gameObject == null)
{
return null;
}
return gameObject.GetComponent<AssetReference>();
}
/// <summary>
/// 加载资源并绑定资源引用到GameObject上。
/// </summary>
/// <param name="gameObject">GameObject。</param>
/// <param name="location">资源定位地址。</param>
/// <param name="callBack">加载完成回调。</param>
/// <param name="customPackageName">自定义包。</param>
/// <typeparam name="T">资源实例类型。</typeparam>
/// <returns>资源实例。</returns>
public static T LoadAsset<T>(this GameObject gameObject, string location, Action<T> callBack = null,
string customPackageName = "") where T : UnityEngine.Object
{
if (gameObject == null)
{
return null;
}
var operation = GameModule.Resource.LoadAssetGetOperation<T>(location, customPackageName: customPackageName);
var asset = operation.AssetObject as T;
gameObject.GetOrAddComponent<AssetReference>().Reference(operation, location);
callBack?.Invoke(asset);
return asset;
}
/// <summary>
/// 异步加载资源并绑定资源引用到GameObject上。
/// </summary>
/// <param name="gameObject">GameObject。</param>
/// <param name="location">资源定位地址。</param>
/// <param name="callBack">加载完成回调。</param>
/// <param name="customPackageName">自定义包。</param>
/// <typeparam name="T">资源实例类型。</typeparam>
/// <returns>资源实例。</returns>
public static async UniTask<T> LoadAssetAsync<T>(this GameObject gameObject, string location, Action<T> callBack = null,
string customPackageName = "") where T : UnityEngine.Object
{
if (gameObject == null)
{
return null;
}
var operation = GameModule.Resource.LoadAssetAsyncHandle<T>(location, customPackageName: customPackageName);
bool cancelOrFailed = await operation.ToUniTask().AttachExternalCancellation(gameObject.GetCancellationTokenOnDestroy())
.SuppressCancellationThrow();
if (cancelOrFailed)
{
return null;
}
gameObject.GetOrAddComponent<AssetReference>().Reference(operation, location);
var asset = operation.AssetObject as T;
callBack?.Invoke(asset);
return asset;
}
}
}

View File

@@ -4,6 +4,46 @@ using YooAsset;
namespace TEngine
{
public class AudioData : MemoryObject
{
public AssetOperationHandle AssetOperationHandle { private set; get; }
public bool InPool { private set; get; } = false;
public override void InitFromPool()
{
}
public override void RecycleToPool()
{
if (!InPool)
{
AssetOperationHandle.Dispose();
}
InPool = false;
AssetOperationHandle = null;
}
internal static AudioData Alloc(AssetOperationHandle assetOperationHandle, bool inPool)
{
AudioData ret = MemoryPool.Acquire<AudioData>();
ret.AssetOperationHandle = assetOperationHandle;
ret.InPool = inPool;
ret.InitFromPool();
return ret;
}
internal static void DeAlloc(AudioData audioData)
{
if (audioData != null)
{
MemoryPool.Release(audioData);
audioData.RecycleToPool();
}
}
}
/// <summary>
/// 音频代理辅助器。
/// </summary>
@@ -11,7 +51,7 @@ namespace TEngine
{
private int _instanceId;
private AudioSource _source;
private AssetOperationHandle _assetOperationHandle;
private AudioData _audioData;
private AudioModuleImp _audioModuleImp;
private Transform _transform;
float _volume = 1.0f;
@@ -32,6 +72,7 @@ namespace TEngine
{
public string Path;
public bool BAsync;
public bool BInPool;
}
/// <summary>
@@ -47,7 +88,7 @@ namespace TEngine
/// <summary>
/// 资源操作句柄。
/// </summary>
public AssetOperationHandle AssetOperationHandle => _assetOperationHandle;
public AudioData AudioData => _audioData;
/// <summary>
/// 音频代理辅助器音频大小。
@@ -175,10 +216,7 @@ namespace TEngine
/// <returns>音频代理辅助器。</returns>
public static AudioAgent Create(string path, bool bAsync, AudioCategory audioCategory, bool bInPool = false)
{
AudioAgent audioAgent = new AudioAgent
{
_audioModuleImp = ModuleImpSystem.GetModule<AudioModuleImp>()
};
AudioAgent audioAgent = new AudioAgent();
audioAgent.Init(audioCategory);
audioAgent.Load(path, bAsync, bInPool);
return audioAgent;
@@ -191,6 +229,7 @@ namespace TEngine
/// <param name="index">音频代理辅助器编号。</param>
public void Init(AudioCategory audioCategory, int index = 0)
{
_audioModuleImp = ModuleImpSystem.GetModule<AudioModuleImp>();
GameObject host = new GameObject(Utility.Text.Format("Audio Agent Helper - {0} - {1}", audioCategory.AudioMixerGroup.name, index));
host.transform.SetParent(audioCategory.InstanceRoot);
host.transform.localPosition = Vector3.zero;
@@ -198,7 +237,8 @@ namespace TEngine
_source = host.AddComponent<AudioSource>();
_source.playOnAwake = false;
AudioMixerGroup[] audioMixerGroups =
audioCategory.AudioMixer.FindMatchingGroups(Utility.Text.Format("Master/{0}/{1}", audioCategory.AudioMixerGroup.name, index));
audioCategory.AudioMixer.FindMatchingGroups(Utility.Text.Format("Master/{0}/{1}", audioCategory.AudioMixerGroup.name,
$"{audioCategory.AudioMixerGroup.name} - {index}"));
_source.outputAudioMixerGroup = audioMixerGroups.Length > 0 ? audioMixerGroups[0] : audioCategory.AudioMixerGroup;
_source.rolloffMode = audioCategory.AudioGroupConfig.audioRolloffMode;
_source.minDistance = audioCategory.AudioGroupConfig.minDistance;
@@ -220,7 +260,7 @@ namespace TEngine
_duration = 0;
if (!string.IsNullOrEmpty(path))
{
if (_audioModuleImp.AudioClipPool.TryGetValue(path, out var operationHandle))
if (bInPool && _audioModuleImp.AudioClipPool.TryGetValue(path, out var operationHandle))
{
OnAssetLoadComplete(operationHandle);
return;
@@ -241,7 +281,7 @@ namespace TEngine
}
else
{
_pendingLoad = new LoadRequest { Path = path, BAsync = bAsync };
_pendingLoad = new LoadRequest { Path = path, BAsync = bAsync, BInPool = bInPool };
if (_audioAgentRuntimeState == AudioAgentRuntimeState.Playing)
{
@@ -251,7 +291,7 @@ namespace TEngine
}
/// <summary>
/// 停音频代理辅助器。
/// 停止播放音频代理辅助器。
/// </summary>
/// <param name="fadeout">是否渐出。</param>
public void Stop(bool fadeout = false)
@@ -270,6 +310,28 @@ namespace TEngine
}
}
}
/// <summary>
/// 暂停音频代理辅助器。
/// </summary>
public void Pause()
{
if (_source != null)
{
_source.Pause();
}
}
/// <summary>
/// 取消暂停音频代理辅助器。
/// </summary>
public void UnPause()
{
if (_source != null)
{
_source.UnPause();
}
}
/// <summary>
/// 资源加载完成。
@@ -279,16 +341,15 @@ namespace TEngine
{
if (handle != null)
{
handle.Completed -= OnAssetLoadComplete;
if (_inPool)
{
_audioModuleImp.AudioClipPool.TryAdd(handle.GetAssetInfo().AssetPath, handle);
_audioModuleImp.AudioClipPool.TryAdd(handle.GetAssetInfo().Address, handle);
}
}
if (_pendingLoad != null)
{
if (handle != null)
if (!_inPool && handle != null)
{
handle.Dispose();
}
@@ -296,19 +357,21 @@ namespace TEngine
_audioAgentRuntimeState = AudioAgentRuntimeState.End;
string path = _pendingLoad.Path;
bool bAsync = _pendingLoad.BAsync;
bool bInPool = _pendingLoad.BInPool;
_pendingLoad = null;
Load(path, bAsync);
Load(path, bAsync, bInPool);
}
else if (handle != null)
{
if (_assetOperationHandle != null)
if (_audioData != null)
{
_assetOperationHandle.Dispose();
AudioData.DeAlloc(_audioData);
_audioData = null;
}
_assetOperationHandle = handle;
_audioData = AudioData.Alloc(handle, _inPool);
_source.clip = _assetOperationHandle.AssetObject as AudioClip;
_source.clip = handle.AssetObject as AudioClip;
if (_source.clip != null)
{
_source.Play();
@@ -352,8 +415,9 @@ namespace TEngine
{
string path = _pendingLoad.Path;
bool bAsync = _pendingLoad.BAsync;
bool bInPool = _pendingLoad.BInPool;
_pendingLoad = null;
Load(path, bAsync);
Load(path, bAsync, bInPool);
}
_source.volume = _volume;
@@ -373,9 +437,9 @@ namespace TEngine
Object.Destroy(_transform.gameObject);
}
if (_assetOperationHandle != null)
if (_audioData != null)
{
_assetOperationHandle.Dispose();
AudioData.DeAlloc(_audioData);
}
}
}

View File

@@ -127,7 +127,7 @@ namespace TEngine
for (int i = 0; i < AudioAgents.Count; i++)
{
if (AudioAgents[i].AssetOperationHandle == null || AudioAgents[i].IsFree)
if (AudioAgents[i].AudioData?.AssetOperationHandle == null || AudioAgents[i].IsFree)
{
freeChannel = i;
break;

View File

@@ -48,7 +48,7 @@ AudioMixerGroupController:
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: 2
m_Name: Sound - 2
m_AudioMixer: {fileID: 24100000}
m_GroupID: 039cd795affa7134a8d5f5d43d3b659d
m_Children: []
@@ -67,7 +67,7 @@ AudioMixerGroupController:
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: 1
m_Name: Sound - 1
m_AudioMixer: {fileID: 24100000}
m_GroupID: c0d40106c2ffb1a44bd48f50b210ee20
m_Children: []
@@ -100,7 +100,7 @@ AudioMixerGroupController:
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: 3
m_Name: Sound - 3
m_AudioMixer: {fileID: 24100000}
m_GroupID: 5f20d1b8f9ac1914dac8beae718e7d40
m_Children: []
@@ -153,7 +153,7 @@ AudioMixerGroupController:
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: 1
m_Name: UISound - 1
m_AudioMixer: {fileID: 24100000}
m_GroupID: e012b6d2e0501df43a88eb6beff8ae07
m_Children: []
@@ -192,7 +192,7 @@ AudioMixerGroupController:
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: 0
m_Name: Sound - 0
m_AudioMixer: {fileID: 24100000}
m_GroupID: 71c50c6b966d1f548a63193919ebfbad
m_Children: []
@@ -225,7 +225,7 @@ AudioMixerGroupController:
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: 0
m_Name: Voice - 0
m_AudioMixer: {fileID: 24100000}
m_GroupID: f46651e8ad3c6034b8764fd635dda3fd
m_Children: []
@@ -313,25 +313,25 @@ AudioMixerController:
m_UpdateMode: 0
m_ExposedParameters:
- guid: 7835f2c4248cb3e43a1a773bab1f8b9d
name: UISoundVolume
name: SoundVolume0
- guid: 41591fd4a32f4034f880ecbc14ee69f1
name: MusicVolume
name: MusicVolume0
- guid: 6e0d1a5935a802d41b27d9e2fad3ba2f
name: UISoundVolume
name: UISoundVolume0
- guid: 0bc64c1c6cebbeb40ba2f724fdcaa257
name: VoiceVolume
name: VoiceVolume0
- guid: f62a8b3fe89df00409532af739ee4e02
name: SoundVolume
name: SoundVolume1
- guid: 265eaf7c8910ab842a845c7bb5e570c4
name: UISoundVolume
name: UISoundVolume1
- guid: 2a8ce0f3383c3f0468a04fa3fc5e317d
name: SoundVolume
name: SoundVolume2
- guid: e83be6d6c4ae85142a51f584159c4ff6
name: UISoundVolume
name: UISoundVolume2
- guid: e54edf7c1bf7ee44297e65adce5b10b7
name: SoundVolume
name: SoundVolume3
- guid: 2dd26f9dadf160f4bbd77f307c3f4f2e
name: UISoundVolume
name: UISoundVolume3
- guid: ba83e724007d7e9459f157db3a54a741
name: MasterVolume
- guid: 6d4c2b8bc0ef38d44b2fbff2b3298ab4
@@ -409,10 +409,14 @@ AudioMixerSnapshotController:
m_AudioMixer: {fileID: 24100000}
m_SnapshotID: 91dee90f8902c804c9da7728ea355157
m_FloatValues:
b47f0c73299cd9b4fba9896e70683903: 1
ba83e724007d7e9459f157db3a54a741: 0
fe15a1b40c14ea646a13dacb15b6a73b: 0
77212647508232a458ac7d48fb55d037: 1
3bbd22597ed32714eb271cf06b098c63: 0
30975daa872456b41bc18e0277e301e6: 1
6d4c2b8bc0ef38d44b2fbff2b3298ab4: -0.03
8542b6bfd7b7bfc4d9b961ba97edf0d2: 1
m_TransitionOverrides: {}
--- !u!244 &246003612463095956
AudioMixerEffectController:
@@ -464,7 +468,7 @@ AudioMixerGroupController:
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: 0
m_Name: Music - 0
m_AudioMixer: {fileID: 24100000}
m_GroupID: 1cf576bd46399874d9494863d6502d94
m_Children: []
@@ -483,7 +487,7 @@ AudioMixerGroupController:
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: 3
m_Name: UISound - 3
m_AudioMixer: {fileID: 24100000}
m_GroupID: 98657376d4096a947953ee04d82830c1
m_Children: []
@@ -516,7 +520,7 @@ AudioMixerGroupController:
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: 2
m_Name: UISound - 2
m_AudioMixer: {fileID: 24100000}
m_GroupID: e84c25a476798ea43a2f6de217af7dba
m_Children: []
@@ -629,7 +633,7 @@ AudioMixerGroupController:
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: 0
m_Name: UISound - 0
m_AudioMixer: {fileID: 24100000}
m_GroupID: 29257697b1e6be546aa0558e342a15a6
m_Children: []

View File

@@ -38,6 +38,8 @@ namespace TEngine
[SerializeField]
private DebuggerActiveWindowType m_ActiveWindow = DebuggerActiveWindowType.AlwaysOpen;
public DebuggerActiveWindowType ActiveWindowType => m_ActiveWindow;
[SerializeField]
private bool m_ShowFullWindow = false;
@@ -393,7 +395,7 @@ namespace TEngine
DrawDebuggerWindowGroup(subDebuggerWindowGroup);
}
debuggerWindowGroup.SelectedWindow.OnDraw();
debuggerWindowGroup?.SelectedWindow?.OnDraw();
}
private void DrawDebuggerWindowIcon(int windowId)

View File

@@ -11,18 +11,29 @@ namespace TEngine
{
private static readonly Dictionary<Type, Module> _moduleMaps = new Dictionary<Type, Module>(ModuleImpSystem.DesignModuleCount);
private static GameObject _gameModuleRoot;
#region
/// <summary>
/// 获取游戏基础模块。
/// </summary>
public static RootModule Base => _base ??= Get<RootModule>();
public static RootModule Base
{
get => _base ??= Get<RootModule>();
private set => _base = value;
}
private static RootModule _base;
/// <summary>
/// 获取调试模块。
/// </summary>
public static DebuggerModule Debugger => _debugger ??= Get<DebuggerModule>();
public static DebuggerModule Debugger
{
get => _debugger ??= Get<DebuggerModule>();
private set => _debugger = value;
}
private static DebuggerModule _debugger;
@@ -88,6 +99,13 @@ namespace TEngine
public static SceneModule Scene => _scene ??= Get<SceneModule>();
private static SceneModule _scene;
/// <summary>
/// 获取计时器模块。
/// </summary>
public static TimerModule Timer => _timer ??= Get<TimerModule>();
private static TimerModule _timer;
#endregion
/// <summary>
@@ -117,7 +135,32 @@ namespace TEngine
{
Log.Info("GameModule Active");
gameObject.name = $"[{nameof(GameModule)}]";
_gameModuleRoot = gameObject;
DontDestroyOnLoad(gameObject);
}
public static void Shutdown(ShutdownType shutdownType)
{
Log.Info("GameModule Shutdown");
if (_gameModuleRoot != null)
{
Destroy(_gameModuleRoot);
_gameModuleRoot = null;
}
_moduleMaps.Clear();
_base = null;
_debugger = null;
_fsm = null;
_procedure = null;
_objectPool = null;
_resource = null;
_audio = null;
_setting = null;
_ui = null;
_localization = null;
_scene = null;
_timer = null;
}
}
}

View File

@@ -77,16 +77,17 @@ namespace TEngine
public static void Shutdown(ShutdownType shutdownType)
{
Log.Info("Shutdown Game Framework ({0})...", shutdownType);
Utility.Unity.Release();
Utility.Unity.Shutdown();
RootModule rootModule = GetModule<RootModule>();
if (rootModule != null)
{
rootModule.Shutdown();
rootModule = null;
}
_modules.Clear();
GameModule.Shutdown(shutdownType);
if (shutdownType == ShutdownType.None)
{
return;

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