mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
Compare commits
22 Commits
TEngine3.1
...
TEngine3.1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4c8c37ffd8 | ||
![]() |
5f694c2bed | ||
![]() |
7ff74bb747 | ||
![]() |
a5de63397a | ||
![]() |
13cc62f3f1 | ||
![]() |
95dfac5294 | ||
![]() |
14e95107c9 | ||
![]() |
caf5b2b54e | ||
![]() |
285483034e | ||
![]() |
1cdd8b63b4 | ||
![]() |
4c748df7ac | ||
![]() |
e1229b5a4b | ||
![]() |
b937fb1a37 | ||
![]() |
87ab99b363 | ||
![]() |
e3a47393f4 | ||
![]() |
75725314ad | ||
![]() |
d3ed2b21b9 | ||
![]() |
ec34dfbb16 | ||
![]() |
bd76e3a651 | ||
![]() |
278c8f23be | ||
![]() |
42568db2ab | ||
![]() |
b033c59b00 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -130,3 +130,4 @@ Bin/
|
||||
|
||||
#Server_Config
|
||||
DotNet/Config/GameConfig
|
||||
DotNet/Config/ProtoBuf/OpCode.Cache
|
||||
|
Binary file not shown.
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f3bcefaf67e76141a6d8edeb8354fea
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 25113973d38eb5a48b064863830539a4
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ef51ed54e72f97a4ab530b932680e08b
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 090163c612f34ac4fb80004ac5f057b4
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -70,6 +70,10 @@ public static class Define
|
||||
/// </summary>
|
||||
public static string ClientCustomExportDirectory;
|
||||
/// <summary>
|
||||
/// SceneConfig.xlsx的位置
|
||||
/// </summary>
|
||||
public static string SceneConfigPath;
|
||||
/// <summary>
|
||||
/// 自定义导出代码存放的程序集
|
||||
/// </summary>
|
||||
public static string CustomExportAssembly;
|
||||
|
@@ -1,12 +1,34 @@
|
||||
#if TENGINE_NET
|
||||
namespace TEngine.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 导出类型枚举,用于标识不同类型的导出操作。
|
||||
/// </summary>
|
||||
public enum ExportType
|
||||
{
|
||||
/// <summary>
|
||||
/// 无导出类型。
|
||||
/// </summary>
|
||||
None = 0,
|
||||
ProtoBuf = 1, // 导出ProtoBuf
|
||||
AllExcelIncrement = 2, // 所有-增量导出Excel
|
||||
AllExcel = 3, // 所有-全量导出Excel
|
||||
Max, // 这个一定放最后
|
||||
/// <summary>
|
||||
/// 导出ProtoBuf类型。
|
||||
/// </summary>
|
||||
ProtoBuf = 1,
|
||||
/// <summary>
|
||||
/// 导出网络协议并重新生成OpCode。
|
||||
/// </summary>
|
||||
ProtoBufAndOpCodeCache = 2,
|
||||
/// <summary>
|
||||
/// 所有数据的增量导出Excel类型。
|
||||
/// </summary>
|
||||
AllExcelIncrement = 3,
|
||||
/// <summary>
|
||||
/// 所有数据的全量导出Excel类型。
|
||||
/// </summary>
|
||||
AllExcel = 4,
|
||||
/// <summary>
|
||||
/// 导出类型枚举的最大值,一定要放在最后。
|
||||
/// </summary>
|
||||
Max,
|
||||
}
|
||||
#endif
|
||||
|
@@ -3,16 +3,21 @@ using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Loader;
|
||||
using System.Text;
|
||||
using TEngine.Core;
|
||||
using TEngine.Helper;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
#pragma warning disable CS8601
|
||||
|
||||
#pragma warning disable CS8618
|
||||
|
||||
namespace TEngine.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 数据导出器,用于执行导出操作。
|
||||
/// </summary>
|
||||
public sealed class Exporter
|
||||
{
|
||||
/// <summary>
|
||||
/// 开始执行数据导出操作。
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
Console.OutputEncoding = Encoding.UTF8;
|
||||
@@ -25,8 +30,9 @@ public sealed class Exporter
|
||||
|
||||
LogInfo("请输入你想要做的操作:");
|
||||
LogInfo("1:导出网络协议(ProtoBuf)");
|
||||
LogInfo("2:增量导出服务器启动Excel(包含常量枚举)");
|
||||
LogInfo("3:全量导出服务器启动Excel(包含常量枚举)");
|
||||
LogInfo("2:导出网络协议并重新生成OpCode(ProtoBuf)");
|
||||
LogInfo("3:增量导出Excel(包含常量枚举)");
|
||||
LogInfo("4:全量导出Excel(包含常量枚举)");
|
||||
|
||||
var keyChar = Console.ReadKey().KeyChar;
|
||||
|
||||
@@ -39,13 +45,17 @@ public sealed class Exporter
|
||||
|
||||
LogInfo("");
|
||||
exportType = (ExportType) key;
|
||||
// LoadConfig();
|
||||
|
||||
switch (exportType)
|
||||
{
|
||||
case ExportType.ProtoBuf:
|
||||
{
|
||||
_ = new ProtoBufExporter();
|
||||
_ = new ProtoBufExporter(false);
|
||||
break;
|
||||
}
|
||||
case ExportType.ProtoBufAndOpCodeCache:
|
||||
{
|
||||
_ = new ProtoBufExporter(true);
|
||||
break;
|
||||
}
|
||||
case ExportType.AllExcel:
|
||||
@@ -61,58 +71,19 @@ public sealed class Exporter
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
#if old
|
||||
// private void LoadConfig()
|
||||
// {
|
||||
// const string settingsName = "TEngineSettings.json";
|
||||
// var currentDirectory = Directory.GetCurrentDirectory();
|
||||
//
|
||||
// if (!File.Exists(Path.Combine(currentDirectory, settingsName)))
|
||||
// {
|
||||
// throw new FileNotFoundException($"not found {settingsName} in OutputDirectory");
|
||||
// }
|
||||
//
|
||||
// var configurationRoot = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory())
|
||||
// .AddJsonFile(settingsName)
|
||||
// .Build();
|
||||
// // ProtoBuf文件所在的位置文件夹位置
|
||||
// ProtoBufDefine.ProtoBufDirectory = configurationRoot["Export:ProtoBufDirectory:Value"];
|
||||
// // ProtoBuf生成到服务端的文件夹位置
|
||||
// ProtoBufDefine.ServerDirectory = configurationRoot["Export:ProtoBufServerDirectory:Value"];
|
||||
// // ProtoBuf生成到客户端的文件夹位置
|
||||
// ProtoBufDefine.ClientDirectory = configurationRoot["Export:ProtoBufClientDirectory:Value"];
|
||||
// // ProtoBuf生成代码模板的位置
|
||||
// ProtoBufDefine.ProtoBufTemplatePath = configurationRoot["Export:ProtoBufTemplatePath:Value"];
|
||||
// // Excel配置文件根目录
|
||||
// ExcelDefine.ProgramPath = configurationRoot["Export:ExcelProgramPath:Value"];
|
||||
// // Excel版本文件的位置
|
||||
// ExcelDefine.ExcelVersionFile = configurationRoot["Export:ExcelVersionFile:Value"];
|
||||
// // Excel生成服务器代码的文件夹位置
|
||||
// ExcelDefine.ServerFileDirectory = configurationRoot["Export:ExcelServerFileDirectory:Value"];
|
||||
// // Excel生成客户端代码文件夹位置
|
||||
// ExcelDefine.ClientFileDirectory = configurationRoot["Export:ExcelClientFileDirectory:Value"];
|
||||
// // Excel生成服务器二进制数据文件夹位置
|
||||
// ExcelDefine.ServerBinaryDirectory = configurationRoot["Export:ExcelServerBinaryDirectory:Value"];
|
||||
// // Excel生成客户端二进制数据文件夹位置
|
||||
// ExcelDefine.ClientBinaryDirectory = configurationRoot["Export:ExcelClientBinaryDirectory:Value"];
|
||||
// // Excel生成服务器Json数据文件夹位置
|
||||
// ExcelDefine.ServerJsonDirectory = configurationRoot["Export:ExcelServerJsonDirectory:Value"];
|
||||
// // Excel生成客户端Json数据文件夹位置
|
||||
// ExcelDefine.ClientJsonDirectory = configurationRoot["Export:ExcelClientJsonDirectory:Value"];
|
||||
// // Excel生成代码模板的位置
|
||||
// ExcelDefine.ExcelTemplatePath = configurationRoot["Export:ExcelTemplatePath:Value"];
|
||||
// // 服务器自定义导出代码文件夹位置
|
||||
// ExcelDefine.ServerCustomExportDirectory = configurationRoot["Export:ServerCustomExportDirectory:Value"];
|
||||
// // 客户端自定义导出代码文件夹位置
|
||||
// ExcelDefine.ClientCustomExportDirectory = configurationRoot["Export:ClientCustomExportDirectory:Value"];
|
||||
// }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// 输出信息到控制台。
|
||||
/// </summary>
|
||||
/// <param name="msg">要输出的信息。</param>
|
||||
public static void LogInfo(string msg)
|
||||
{
|
||||
Console.WriteLine(msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 输出错误信息到控制台。
|
||||
/// </summary>
|
||||
/// <param name="msg">要输出的错误信息。</param>
|
||||
public static void LogError(string msg)
|
||||
{
|
||||
ConsoleColor color = Console.ForegroundColor;
|
||||
@@ -121,6 +92,10 @@ public sealed class Exporter
|
||||
Console.ForegroundColor = color;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 输出异常信息到控制台。
|
||||
/// </summary>
|
||||
/// <param name="e">要输出的异常。</param>
|
||||
public static void LogError(Exception e)
|
||||
{
|
||||
ConsoleColor color = Console.ForegroundColor;
|
||||
|
@@ -0,0 +1,60 @@
|
||||
#if TENGINE_NET
|
||||
using TEngine.Helper;
|
||||
|
||||
namespace TEngine.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 网络协议操作码缓存。
|
||||
/// </summary>
|
||||
public class OpCodeCache
|
||||
{
|
||||
private readonly List<uint> _opCodes = new List<uint>();
|
||||
private readonly SortedDictionary<string, uint> _opcodeCache;
|
||||
private readonly SortedDictionary<string, uint> _saveOpCodeCache = new();
|
||||
private readonly string _opcodeCachePath = $"{Define.ProtoBufDirectory}OpCode.Cache";
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数,用于初始化网络协议操作码缓存。
|
||||
/// </summary>
|
||||
public OpCodeCache(bool regenerate)
|
||||
{
|
||||
if (File.Exists(_opcodeCachePath) && !regenerate)
|
||||
{
|
||||
var readAllText = File.ReadAllText(_opcodeCachePath);
|
||||
_opcodeCache = readAllText.Deserialize<SortedDictionary<string, uint>>();
|
||||
_opCodes.AddRange(_opcodeCache.Values);
|
||||
}
|
||||
else
|
||||
{
|
||||
_opcodeCache = new SortedDictionary<string, uint>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存网络协议操作码。
|
||||
/// </summary>
|
||||
public void Save()
|
||||
{
|
||||
File.WriteAllText(_opcodeCachePath, _saveOpCodeCache.ToJson());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据className获得OpCode、如果是新增的会产生一个新的OpCode。
|
||||
/// </summary>
|
||||
/// <param name="className">协议名。</param>
|
||||
/// <param name="opcode">操作码。</param>
|
||||
/// <returns></returns>
|
||||
public uint GetOpcodeCache(string className, ref uint opcode)
|
||||
{
|
||||
if (!_opcodeCache.TryGetValue(className, out var opCode))
|
||||
{
|
||||
while (_opCodes.Contains(++opcode)) { }
|
||||
opCode = opcode;
|
||||
_opCodes.Add(opCode);
|
||||
}
|
||||
|
||||
_saveOpCodeCache.Add(className, opCode);
|
||||
return opCode;
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e0f0d02da06c4ca981417bfe43162809
|
||||
timeCreated: 1693928511
|
@@ -1,28 +1,52 @@
|
||||
#if TENGINE_NET
|
||||
using System.Text;
|
||||
using TEngine.Core.Network;
|
||||
|
||||
#pragma warning disable CS8604
|
||||
#pragma warning disable CS8602
|
||||
#pragma warning disable CS8600
|
||||
#pragma warning disable CS8618
|
||||
using TEngine.Helper;
|
||||
|
||||
namespace TEngine.Core;
|
||||
|
||||
/// <summary>
|
||||
/// ProtoBuf操作码类型枚举
|
||||
/// </summary>
|
||||
public enum ProtoBufOpCodeType
|
||||
{
|
||||
/// <summary>
|
||||
/// 无
|
||||
/// </summary>
|
||||
None = 0,
|
||||
/// <summary>
|
||||
/// 外部操作码类型
|
||||
/// </summary>
|
||||
Outer = 1,
|
||||
/// <summary>
|
||||
/// 内部操作码类型
|
||||
/// </summary>
|
||||
Inner = 2,
|
||||
/// <summary>
|
||||
/// 使用BSON的内部操作码类型
|
||||
/// </summary>
|
||||
InnerBson = 3,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 操作码信息类
|
||||
/// </summary>
|
||||
public sealed class OpcodeInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 操作码
|
||||
/// </summary>
|
||||
public uint Code;
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public string Name;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// ProtoBuf导出器类
|
||||
/// </summary>
|
||||
public sealed class ProtoBufExporter
|
||||
{
|
||||
private uint _aMessage;
|
||||
@@ -33,10 +57,13 @@ public sealed class ProtoBufExporter
|
||||
private uint _aRouteResponse;
|
||||
private string _serverTemplate;
|
||||
private string _clientTemplate;
|
||||
|
||||
private readonly OpCodeCache _opCodeCache;
|
||||
private readonly List<OpcodeInfo> _opcodes = new();
|
||||
|
||||
public ProtoBufExporter()
|
||||
/// <summary>
|
||||
/// 构造函数,用于初始化导出器
|
||||
/// </summary>
|
||||
public ProtoBufExporter(bool regenerateOpCodeCache)
|
||||
{
|
||||
Console.OutputEncoding = Encoding.UTF8;
|
||||
|
||||
@@ -60,11 +87,13 @@ public sealed class ProtoBufExporter
|
||||
Directory.CreateDirectory($"{Define.ProtoBufDirectory}Inner");
|
||||
}
|
||||
|
||||
if (!Directory.Exists($"{Define.ProtoBufDirectory}Bson"))
|
||||
if (!Directory.Exists($"{Define.ProtoBufDirectory}InnerBosn"))
|
||||
{
|
||||
Directory.CreateDirectory($"{Define.ProtoBufDirectory}Bson");
|
||||
Directory.CreateDirectory($"{Define.ProtoBufDirectory}InnerBosn");
|
||||
}
|
||||
|
||||
_opCodeCache = new OpCodeCache(regenerateOpCodeCache);
|
||||
|
||||
var tasks = new Task[2];
|
||||
tasks[0] = Task.Run(RouteType);
|
||||
tasks[1] = Task.Run(async () =>
|
||||
@@ -75,6 +104,7 @@ public sealed class ProtoBufExporter
|
||||
await Start(ProtoBufOpCodeType.InnerBson);
|
||||
});
|
||||
Task.WaitAll(tasks);
|
||||
_opCodeCache.Save();
|
||||
}
|
||||
|
||||
private async Task Start(ProtoBufOpCodeType opCodeType)
|
||||
@@ -99,8 +129,9 @@ public sealed class ProtoBufExporter
|
||||
opCodeName = "OuterOpcode";
|
||||
saveDirectory.Add(Define.ProtoBufServerDirectory, _serverTemplate);
|
||||
saveDirectory.Add(Define.ProtoBufClientDirectory, _clientTemplate);
|
||||
files.Add($"{Define.ProtoBufDirectory}OuterMessage.proto");
|
||||
files.AddRange(Directory.GetFiles($"{Define.ProtoBufDirectory}Outer").ToList());
|
||||
var protoBufFiles = FileHelper.GetDirectoryFile(
|
||||
$"{Define.ProtoBufDirectory}Outer", "*.proto", SearchOption.AllDirectories);
|
||||
files.AddRange(protoBufFiles);
|
||||
break;
|
||||
}
|
||||
case ProtoBufOpCodeType.Inner:
|
||||
@@ -114,8 +145,8 @@ public sealed class ProtoBufExporter
|
||||
_aRouteResponse = Opcode.InnerRouteResponse + 1000;
|
||||
opCodeName = "InnerOpcode";
|
||||
saveDirectory.Add(Define.ProtoBufServerDirectory, _serverTemplate);
|
||||
files.Add($"{Define.ProtoBufDirectory}InnerMessage.proto");
|
||||
files.AddRange(Directory.GetFiles($"{Define.ProtoBufDirectory}Inner").ToList());
|
||||
var protoBufFiles = FileHelper.GetDirectoryFile($"{Define.ProtoBufDirectory}Inner", "*.proto", SearchOption.AllDirectories);
|
||||
files.AddRange(protoBufFiles);
|
||||
break;
|
||||
}
|
||||
case ProtoBufOpCodeType.InnerBson:
|
||||
@@ -129,8 +160,8 @@ public sealed class ProtoBufExporter
|
||||
_aRouteResponse = Opcode.InnerBsonRouteResponse + 1000;
|
||||
opCodeName = "InnerBsonOpcode";
|
||||
saveDirectory.Add(Define.ProtoBufServerDirectory, _serverTemplate);
|
||||
files.Add($"{Define.ProtoBufDirectory}InnerBsonMessage.proto");
|
||||
files.AddRange(Directory.GetFiles($"{Define.ProtoBufDirectory}Bson").ToList());
|
||||
var protoBufFiles = FileHelper.GetDirectoryFile($"{Define.ProtoBufDirectory}InnerBosn", "*.proto", SearchOption.AllDirectories);
|
||||
files.AddRange(protoBufFiles);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -143,10 +174,13 @@ public sealed class ProtoBufExporter
|
||||
var isMsgHead = false;
|
||||
string responseTypeStr = null;
|
||||
string customRouteType = null;
|
||||
|
||||
var protoFileText = await File.ReadAllTextAsync(filePath);
|
||||
|
||||
foreach (var line in protoFileText.Split('\n'))
|
||||
{
|
||||
bool hadOpCode = true;
|
||||
|
||||
var currentLine = line.Trim();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(currentLine))
|
||||
@@ -176,17 +210,20 @@ public sealed class ProtoBufExporter
|
||||
switch (parameterArray.Length)
|
||||
{
|
||||
case 2:
|
||||
responseTypeStr = parameterArray[1].Trim();
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
customRouteType = parameterArray[1].Trim();
|
||||
|
||||
if (parameterArray.Length == 3)
|
||||
if (parameter == "ICustomRouteMessage")
|
||||
{
|
||||
responseTypeStr = parameterArray[2].Trim();
|
||||
customRouteType = parameterArray[1].Trim();
|
||||
break;
|
||||
}
|
||||
|
||||
responseTypeStr = parameterArray[1].Trim();
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
responseTypeStr = parameterArray[1].Trim();
|
||||
customRouteType = parameterArray[2].Trim();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -197,8 +234,8 @@ public sealed class ProtoBufExporter
|
||||
}
|
||||
|
||||
file.Append(string.IsNullOrWhiteSpace(parameter)
|
||||
? $"\tpublic partial class {className} : AProto"
|
||||
: $"\tpublic partial class {className} : AProto, {parameter}");
|
||||
? $"\tpublic partial class {className} : AProto"
|
||||
: $"\tpublic partial class {className} : AProto, {parameter}");
|
||||
opcodeInfo.Name = className;
|
||||
continue;
|
||||
}
|
||||
@@ -214,9 +251,13 @@ public sealed class ProtoBufExporter
|
||||
{
|
||||
file.AppendLine("\n\t{");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(parameter) || parameter == "IMessage")
|
||||
if (string.IsNullOrWhiteSpace(parameter))
|
||||
{
|
||||
opcodeInfo.Code += ++_aMessage;
|
||||
hadOpCode = false;
|
||||
}
|
||||
else if(parameter == "IMessage")
|
||||
{
|
||||
opcodeInfo.Code = _opCodeCache.GetOpcodeCache(className, ref _aMessage);
|
||||
file.AppendLine($"\t\tpublic uint OpCode() {{ return {opCodeName}.{className}; }}");
|
||||
}
|
||||
else
|
||||
@@ -260,13 +301,13 @@ public sealed class ProtoBufExporter
|
||||
case "IRequest":
|
||||
case "IBsonRequest":
|
||||
{
|
||||
opcodeInfo.Code += ++_aRequest;
|
||||
opcodeInfo.Code = _opCodeCache.GetOpcodeCache(className, ref _aRequest);
|
||||
break;
|
||||
}
|
||||
case "IResponse":
|
||||
case "IBsonResponse":
|
||||
{
|
||||
opcodeInfo.Code += ++_aResponse;
|
||||
opcodeInfo.Code = _opCodeCache.GetOpcodeCache(className, ref _aResponse);
|
||||
file.AppendLine("\t\t[ProtoMember(91, IsRequired = true)]");
|
||||
file.AppendLine("\t\tpublic uint ErrorCode { get; set; }");
|
||||
break;
|
||||
@@ -275,15 +316,15 @@ public sealed class ProtoBufExporter
|
||||
{
|
||||
if (parameter.EndsWith("RouteMessage") || parameter == "IRouteMessage")
|
||||
{
|
||||
opcodeInfo.Code += ++_aRouteMessage;
|
||||
opcodeInfo.Code = _opCodeCache.GetOpcodeCache(className, ref _aRouteMessage);
|
||||
}
|
||||
else if (parameter.EndsWith("RouteRequest") || parameter == "IRouteRequest")
|
||||
{
|
||||
opcodeInfo.Code += ++_aRouteRequest;
|
||||
opcodeInfo.Code = _opCodeCache.GetOpcodeCache(className, ref _aRouteRequest);
|
||||
}
|
||||
else if (parameter.EndsWith("RouteResponse") || parameter == "IRouteResponse")
|
||||
{
|
||||
opcodeInfo.Code += ++_aRouteResponse;
|
||||
opcodeInfo.Code = _opCodeCache.GetOpcodeCache(className, ref _aRouteResponse);
|
||||
file.AppendLine("\t\t[ProtoMember(91, IsRequired = true)]");
|
||||
file.AppendLine("\t\tpublic uint ErrorCode { get; set; }");
|
||||
}
|
||||
@@ -293,7 +334,10 @@ public sealed class ProtoBufExporter
|
||||
}
|
||||
}
|
||||
|
||||
_opcodes.Add(opcodeInfo);
|
||||
if (hadOpCode)
|
||||
{
|
||||
_opcodes.Add(opcodeInfo);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case "}":
|
||||
@@ -359,7 +403,6 @@ public sealed class ProtoBufExporter
|
||||
var csFile = Path.Combine(directory, $"{opCodeName}.cs");
|
||||
await File.WriteAllTextAsync(csFile, file.ToString());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -381,7 +424,7 @@ public sealed class ProtoBufExporter
|
||||
continue;
|
||||
}
|
||||
|
||||
var splits = currentLine.Split(new[] { "//" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
var splits = currentLine.Split(new[] {"//"}, StringSplitOptions.RemoveEmptyEntries);
|
||||
var routeTypeStr = splits[0].Split("=", StringSplitOptions.RemoveEmptyEntries);
|
||||
routeTypeFileSb.Append($"\t\t{routeTypeStr[0].Trim()} = {routeTypeStr[1].Trim()},");
|
||||
|
||||
@@ -479,6 +522,9 @@ public sealed class ProtoBufExporter
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载模板
|
||||
/// </summary>
|
||||
private void LoadTemplate()
|
||||
{
|
||||
string[] lines = File.ReadAllLines(Define.ProtoBufTemplatePath, Encoding.UTF8);
|
||||
@@ -496,12 +542,12 @@ public sealed class ProtoBufExporter
|
||||
flag = 1;
|
||||
continue;
|
||||
}
|
||||
else if (trim.StartsWith("#else"))
|
||||
else if(trim.StartsWith("#else"))
|
||||
{
|
||||
flag = 2;
|
||||
continue;
|
||||
}
|
||||
else if (trim.StartsWith($"#endif"))
|
||||
else if(trim.StartsWith($"#endif"))
|
||||
{
|
||||
flag = 0;
|
||||
continue;
|
||||
|
@@ -1,26 +1,29 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace TEngine.Core
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件操作助手类,提供了各种文件操作方法。
|
||||
/// </summary>
|
||||
public static class FileHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取文件全路径。
|
||||
/// 获取相对路径的完整路径。
|
||||
/// </summary>
|
||||
/// <param name="relativePath"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="relativePath">相对路径。</param>
|
||||
/// <returns>完整路径。</returns>
|
||||
public static string GetFullPath(string relativePath)
|
||||
{
|
||||
return Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), relativePath));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拷贝文件到目标路径、如果目标目录不存在会自动创建目录
|
||||
/// 将文件复制到目标路径,如果目标目录不存在会自动创建目录。
|
||||
/// </summary>
|
||||
/// <param name="sourceFile"></param>
|
||||
/// <param name="destinationFile"></param>
|
||||
/// <param name="overwrite"></param>
|
||||
/// <param name="sourceFile">源文件路径。</param>
|
||||
/// <param name="destinationFile">目标文件路径。</param>
|
||||
/// <param name="overwrite">是否覆盖已存在的目标文件。</param>
|
||||
public static void Copy(string sourceFile, string destinationFile, bool overwrite)
|
||||
{
|
||||
var directoriesByFilePath = GetDirectoriesByFilePath(destinationFile);
|
||||
@@ -39,10 +42,10 @@ namespace TEngine.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取文件路径内的所有文件夹路径
|
||||
/// 获取文件路径内的所有文件夹路径。
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="filePath">文件路径。</param>
|
||||
/// <returns>文件夹路径列表。</returns>
|
||||
public static List<string> GetDirectoriesByFilePath(string filePath)
|
||||
{
|
||||
var dir = "";
|
||||
@@ -59,11 +62,11 @@ namespace TEngine.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 把文件夹里所有内容拷贝的目标位置
|
||||
/// 将文件夹内的所有内容复制到目标位置。
|
||||
/// </summary>
|
||||
/// <param name="sourceDirectory"></param>
|
||||
/// <param name="destinationDirectory"></param>
|
||||
/// <param name="overwrite"></param>
|
||||
/// <param name="sourceDirectory">源文件夹路径。</param>
|
||||
/// <param name="destinationDirectory">目标文件夹路径。</param>
|
||||
/// <param name="overwrite">是否覆盖已存在的文件。</param>
|
||||
public static void CopyDirectory(string sourceDirectory, string destinationDirectory, bool overwrite)
|
||||
{
|
||||
// 创建目标文件夹
|
||||
@@ -101,9 +104,21 @@ namespace TEngine.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除文件夹里的所有文件
|
||||
/// 获取目录下的所有文件
|
||||
/// </summary>
|
||||
/// <param name="folderPath"></param>
|
||||
/// <param name="folderPath">文件夹路径。</param>
|
||||
/// <param name="searchPattern">需要查找的文件通配符</param>
|
||||
/// <param name="searchOption">查找的类型</param>
|
||||
/// <returns></returns>
|
||||
public static string[] GetDirectoryFile(string folderPath, string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
return Directory.GetFiles(folderPath, searchPattern, searchOption);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空文件夹内的所有文件。
|
||||
/// </summary>
|
||||
/// <param name="folderPath">文件夹路径。</param>
|
||||
public static void ClearDirectoryFile(string folderPath)
|
||||
{
|
||||
if (!Directory.Exists(folderPath))
|
||||
|
191
Assets/GameScripts/DotNet/Core/Helper/StringHelper.cs
Normal file
191
Assets/GameScripts/DotNet/Core/Helper/StringHelper.cs
Normal file
@@ -0,0 +1,191 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public static class StringHelper
|
||||
{
|
||||
public static IEnumerable<byte> ToBytes(this string str)
|
||||
{
|
||||
byte[] byteArray = Encoding.Default.GetBytes(str);
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
public static byte[] ToByteArray(this string str)
|
||||
{
|
||||
byte[] byteArray = Encoding.Default.GetBytes(str);
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
public static byte[] ToUtf8(this string str)
|
||||
{
|
||||
byte[] byteArray = Encoding.UTF8.GetBytes(str);
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
public static byte[] HexToBytes(this string hexString)
|
||||
{
|
||||
if (hexString.Length % 2 != 0)
|
||||
{
|
||||
throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "The binary key cannot have an odd number of digits: {0}",
|
||||
hexString));
|
||||
}
|
||||
|
||||
var hexAsBytes = new byte[hexString.Length / 2];
|
||||
for (int index = 0; index < hexAsBytes.Length; index++)
|
||||
{
|
||||
string byteValue = "";
|
||||
byteValue += hexString[index * 2];
|
||||
byteValue += hexString[index * 2 + 1];
|
||||
hexAsBytes[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
return hexAsBytes;
|
||||
}
|
||||
|
||||
public static string Fmt(this string text, params object[] args)
|
||||
{
|
||||
return string.Format(text, args);
|
||||
}
|
||||
|
||||
public static string ListToString<T>(this List<T> list)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (T t in list)
|
||||
{
|
||||
sb.Append(t);
|
||||
sb.Append(",");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string ArrayToString<T>(this T[] args)
|
||||
{
|
||||
if (args == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
string argStr = " [";
|
||||
for (int arrIndex = 0; arrIndex < args.Length; arrIndex++)
|
||||
{
|
||||
argStr += args[arrIndex];
|
||||
if (arrIndex != args.Length - 1)
|
||||
{
|
||||
argStr += ", ";
|
||||
}
|
||||
}
|
||||
|
||||
argStr += "]";
|
||||
return argStr;
|
||||
}
|
||||
|
||||
public static string ArrayToString<T>(this T[] args, int index, int count)
|
||||
{
|
||||
if (args == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
string argStr = " [";
|
||||
for (int arrIndex = index; arrIndex < count + index; arrIndex++)
|
||||
{
|
||||
argStr += args[arrIndex];
|
||||
if (arrIndex != args.Length - 1)
|
||||
{
|
||||
argStr += ", ";
|
||||
}
|
||||
}
|
||||
|
||||
argStr += "]";
|
||||
return argStr;
|
||||
}
|
||||
|
||||
public static string PrintProto(this AProto proto, int stackIndex = 0, string propertyInfoName = "", bool isList = false, int listIndex = 0)
|
||||
{
|
||||
if (proto == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
StringBuilder _stringBuilder = new StringBuilder();
|
||||
_stringBuilder.Clear();
|
||||
|
||||
Type type = proto.GetType();
|
||||
_stringBuilder.Append($"\n");
|
||||
for (int i = 0; i < stackIndex; i++)
|
||||
{
|
||||
_stringBuilder.Append("\t");
|
||||
}
|
||||
|
||||
propertyInfoName = isList ? $"[{propertyInfoName}][{listIndex}]" : $"[{propertyInfoName}]";
|
||||
_stringBuilder.Append(stackIndex == 0? $"[{type.Name}]" : propertyInfoName);
|
||||
|
||||
var bindingFlags = BindingFlags.Public | BindingFlags.Instance;
|
||||
var propertyInfos = type.GetProperties(bindingFlags);
|
||||
for (var i = 0; i < propertyInfos.Length; ++i)
|
||||
{
|
||||
var propertyInfo = propertyInfos[i];
|
||||
|
||||
if (propertyInfo.PropertyType.BaseType == typeof (AProto))
|
||||
{
|
||||
_stringBuilder.Append(PrintProto((AProto)propertyInfo.GetValue(proto), stackIndex + 1, propertyInfo.Name));
|
||||
}
|
||||
else if (propertyInfo.PropertyType.IsList() && propertyInfo.PropertyType.IsGenericType)
|
||||
{
|
||||
object value = propertyInfo.GetValue(proto, null);
|
||||
if (value != null)
|
||||
{
|
||||
Type objType = value.GetType();
|
||||
int count = Convert.ToInt32(objType.GetProperty("Count").GetValue(value, null));
|
||||
for (int j = 0; j < count; j++)
|
||||
{
|
||||
object item = objType.GetProperty("Item").GetValue(value, new object[] { j });
|
||||
_stringBuilder.Append(PrintProto((AProto)item, stackIndex + 1, propertyInfo.Name, isList: true, listIndex: j));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_stringBuilder.Append($"\n");
|
||||
for (int j = 0; j < stackIndex + 1; j++)
|
||||
{
|
||||
_stringBuilder.Append("\t");
|
||||
}
|
||||
|
||||
_stringBuilder.Append($"[{propertyInfo.Name}]");
|
||||
_stringBuilder.Append(": ");
|
||||
_stringBuilder.Append(propertyInfo.GetValue(proto));
|
||||
}
|
||||
}
|
||||
|
||||
return _stringBuilder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断类型是否为可操作的列表类型
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsList(this Type type)
|
||||
{
|
||||
if (typeof (System.Collections.IList).IsAssignableFrom(type))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (var it in type.GetInterfaces())
|
||||
{
|
||||
if (it.IsGenericType && typeof (IList<>) == it.GetGenericTypeDefinition())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b7dfd2b954f77047a61bf4c505f8cc1
|
||||
guid: c253fa0108e29234f9198e6b720bdbf7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
@@ -9,6 +9,7 @@ namespace TEngine.Core.Network
|
||||
{
|
||||
try
|
||||
{
|
||||
DisposePackInfo = false;
|
||||
switch (packInfo.ProtocolCode)
|
||||
{
|
||||
case > Opcode.InnerRouteResponse:
|
||||
|
@@ -56,7 +56,6 @@ namespace TEngine.Core.Network
|
||||
ThreadSynchronizationContext.Main.Post(OnConnectDisconnect);
|
||||
}
|
||||
|
||||
_socket.Disconnect(false);
|
||||
_socket.Close();
|
||||
}
|
||||
|
||||
|
@@ -69,6 +69,8 @@ public static class TEngineSettingsHelper
|
||||
Define.ServerCustomExportDirectory = FileHelper.GetFullPath(root["Export:ServerCustomExportDirectory:Value"]);
|
||||
// 客户端自定义导出代码
|
||||
Define.ClientCustomExportDirectory = FileHelper.GetFullPath(root["Export:ClientCustomExportDirectory:Value"]);
|
||||
// SceneConfig.xlsx的位置
|
||||
Define.SceneConfigPath = FileHelper.GetFullPath(root["Export:SceneConfigPath:Value"]);
|
||||
// 自定义导出代码存放的程序集
|
||||
Define.CustomExportAssembly = FileHelper.GetFullPath(root["Export:CustomExportAssembly:Value"]);
|
||||
}
|
||||
|
@@ -25,17 +25,20 @@ namespace GameMain
|
||||
{
|
||||
if (GameModule.Resource.PlayMode == EPlayMode.HostPlayMode)
|
||||
{
|
||||
UpdateData updateData = await RequestUpdateData();
|
||||
|
||||
if (updateData!=null)
|
||||
if (SettingsUtils.EnableUpdateData())
|
||||
{
|
||||
if (!string.IsNullOrEmpty(updateData.HostServerURL))
|
||||
UpdateData updateData = await RequestUpdateData();
|
||||
|
||||
if (updateData!=null)
|
||||
{
|
||||
SettingsUtils.FrameworkGlobalSettings.HostServerURL = updateData.HostServerURL;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(updateData.FallbackHostServerURL))
|
||||
{
|
||||
SettingsUtils.FrameworkGlobalSettings.FallbackHostServerURL = updateData.FallbackHostServerURL;
|
||||
if (!string.IsNullOrEmpty(updateData.HostServerURL))
|
||||
{
|
||||
SettingsUtils.FrameworkGlobalSettings.HostServerURL = updateData.HostServerURL;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(updateData.FallbackHostServerURL))
|
||||
{
|
||||
SettingsUtils.FrameworkGlobalSettings.FallbackHostServerURL = updateData.FallbackHostServerURL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -14,10 +14,6 @@ namespace TEngine.Editor
|
||||
"Assembly-CSharp",
|
||||
"GameMain.Runtime",
|
||||
"GameMain",
|
||||
"GameBase",
|
||||
"GameLogic",
|
||||
"GameProto",
|
||||
"BattleCore.Runtime",
|
||||
};
|
||||
|
||||
private static readonly string[] RuntimeOrEditorAssemblyNames =
|
||||
@@ -27,11 +23,7 @@ namespace TEngine.Editor
|
||||
"TEngine.Editor",
|
||||
"Assembly-CSharp-Editor",
|
||||
"GameMain",
|
||||
"GameMain.Editor",
|
||||
"GameBase",
|
||||
"GameLogic",
|
||||
"GameProto",
|
||||
"BattleCore.Runtime",
|
||||
"GameMain.Editor"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
Binary file not shown.
@@ -0,0 +1,33 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4029d25cf768d5440b7366c5e62c963f
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,134 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using UnityEngine;
|
||||
|
||||
#if !ODIN_INSPECTOR
|
||||
namespace Sirenix.OdinInspector
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
public class ButtonAttribute : Attribute
|
||||
{
|
||||
public ButtonAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
public ButtonAttribute(string name)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
public sealed class ReadOnlyAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = false)]
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
public class ShowInInspectorAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
public sealed class HideIfAttribute : Attribute
|
||||
{
|
||||
public string MemberName;
|
||||
public object Value;
|
||||
public bool Animate;
|
||||
|
||||
public HideIfAttribute(string memberName, bool animate = true)
|
||||
{
|
||||
this.MemberName = memberName;
|
||||
this.Animate = animate;
|
||||
}
|
||||
}
|
||||
|
||||
[DontApplyToListElements]
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
public sealed class OnValueChangedAttribute : Attribute
|
||||
{
|
||||
public string MethodName;
|
||||
|
||||
public bool IncludeChildren;
|
||||
|
||||
public OnValueChangedAttribute(string methodName, bool includeChildren = false)
|
||||
{
|
||||
this.MethodName = methodName;
|
||||
this.IncludeChildren = includeChildren;
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = false)]
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
public class TableListAttribute : Attribute
|
||||
{
|
||||
public int DefaultMinColumnWidth = 40;
|
||||
public bool DrawScrollView = true;
|
||||
|
||||
public int MinScrollViewHeight = 350;
|
||||
|
||||
public int CellPadding = 2;
|
||||
|
||||
public int NumberOfItemsPerPage;
|
||||
|
||||
public bool IsReadOnly;
|
||||
|
||||
public bool ShowIndexLabels;
|
||||
|
||||
public int MaxScrollViewHeight;
|
||||
|
||||
public bool AlwaysExpanded;
|
||||
|
||||
public bool HideToolbar;
|
||||
|
||||
[SerializeField] [HideInInspector] private bool showPagingHasValue;
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class DontApplyToListElementsAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
|
||||
[DontApplyToListElements]
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
public class PropertySpaceAttribute : Attribute
|
||||
{
|
||||
public float SpaceBefore;
|
||||
public float SpaceAfter;
|
||||
|
||||
public PropertySpaceAttribute()
|
||||
{
|
||||
this.SpaceBefore = 8f;
|
||||
this.SpaceAfter = 0.0f;
|
||||
}
|
||||
|
||||
public PropertySpaceAttribute(float spaceBefore)
|
||||
{
|
||||
this.SpaceBefore = spaceBefore;
|
||||
this.SpaceAfter = 0.0f;
|
||||
}
|
||||
|
||||
public PropertySpaceAttribute(float spaceBefore, float spaceAfter)
|
||||
{
|
||||
this.SpaceBefore = spaceBefore;
|
||||
this.SpaceAfter = spaceAfter;
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
|
||||
[Conditional("UNITY_EDITOR")]
|
||||
public class LabelTextAttribute : Attribute
|
||||
{
|
||||
public string Text;
|
||||
|
||||
public LabelTextAttribute(string text)
|
||||
{
|
||||
this.Text = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -1,34 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public static partial class TransformExtension
|
||||
{
|
||||
public static float YDeg(this Transform tran)
|
||||
{
|
||||
return tran.eulerAngles.y;
|
||||
}
|
||||
|
||||
public static void RemoveAllChildren(this Transform tran)
|
||||
{
|
||||
var count = tran.childCount;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
GameObject.DestroyImmediate(tran.GetChild(0).gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Transform> GetAllChildren(this Transform tran)
|
||||
{
|
||||
var count = tran.childCount;
|
||||
List<Transform> allTrans = new List<Transform>();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
allTrans.Add(tran.GetChild(i));
|
||||
}
|
||||
|
||||
return allTrans;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 59821d6add0226e40a841e85a2cba8ec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -104,7 +104,7 @@ namespace TEngine
|
||||
|
||||
int renderWidth = src.width >> DownSampleNum;
|
||||
int renderHeight = src.height >> DownSampleNum;
|
||||
m_renderTexture = RenderTexture.GetTemporary(renderWidth, renderHeight, 0, RenderTextureFormat.RGB111110Float);
|
||||
m_renderTexture = RenderTexture.GetTemporary(renderWidth, renderHeight, 0, RenderTextureFormat.Default);
|
||||
m_renderTexture.filterMode = FilterMode.Bilinear;
|
||||
|
||||
Graphics.Blit(src, m_renderTexture, material, 0);
|
||||
@@ -117,7 +117,7 @@ namespace TEngine
|
||||
material.SetFloat(DownSampleValue, BlurSpreadSize * widthMod + iterationOffs);
|
||||
// 【2.2】处理Shader的通道1,垂直方向模糊处理 || Pass1,for vertical blur
|
||||
// 定义一个临时渲染的缓存tempBuffer
|
||||
RenderTexture tempBuffer = RenderTexture.GetTemporary(renderWidth, renderHeight, 0, RenderTextureFormat.RGB111110Float);
|
||||
RenderTexture tempBuffer = RenderTexture.GetTemporary(renderWidth, renderHeight, 0, RenderTextureFormat.Default);
|
||||
// 拷贝rawTexture中的渲染数据到tempBuffer,并仅绘制指定的pass1的纹理数据
|
||||
Graphics.Blit(m_renderTexture, tempBuffer, material, 1);
|
||||
// 清空rawTexture
|
||||
@@ -126,7 +126,7 @@ namespace TEngine
|
||||
m_renderTexture = tempBuffer;
|
||||
// 【2.3】处理Shader的通道2,竖直方向模糊处理 || Pass2,for horizontal blur
|
||||
// 获取临时渲染纹理
|
||||
tempBuffer = RenderTexture.GetTemporary(renderWidth, renderHeight, 0, RenderTextureFormat.RGB111110Float);
|
||||
tempBuffer = RenderTexture.GetTemporary(renderWidth, renderHeight, 0, RenderTextureFormat.Default);
|
||||
// 拷贝rawTexture中的渲染数据到tempBuffer,并仅绘制指定的pass2的纹理数据
|
||||
Graphics.Blit(m_renderTexture, tempBuffer, m_material, 2);
|
||||
//【2.4】得到pass0、pass1和pass2的数据都已经准备好的rawTexture
|
||||
|
@@ -23,7 +23,7 @@ namespace TEngine
|
||||
|
||||
private float _volume = 1f;
|
||||
private bool _enable = true;
|
||||
private AudioCategory[] _audioCategories = new AudioCategory[(int)AudioType.Max];
|
||||
private readonly AudioCategory[] _audioCategories = new AudioCategory[(int)AudioType.Max];
|
||||
private readonly float[] _categoriesVolume = new float[(int)AudioType.Max];
|
||||
public readonly Dictionary<string, AssetOperationHandle> AudioClipPool = new Dictionary<string, AssetOperationHandle>();
|
||||
public IResourceManager ResourceManager;
|
||||
@@ -392,19 +392,20 @@ namespace TEngine
|
||||
|
||||
for (int i = 0; i < (int)AudioType.Max; ++i)
|
||||
{
|
||||
if (_audioCategories[i] != null)
|
||||
var audioCategory = _audioCategories[i];
|
||||
if (audioCategory != null)
|
||||
{
|
||||
for (int j = 0; j < _audioCategories[i].AudioAgents.Count; ++j)
|
||||
for (int j = 0; j < audioCategory.AudioAgents.Count; ++j)
|
||||
{
|
||||
if (_audioCategories[i].AudioAgents[j] != null)
|
||||
var audioAgent = audioCategory.AudioAgents[j];
|
||||
if (audioAgent != null)
|
||||
{
|
||||
_audioCategories[i].AudioAgents[j].Destroy();
|
||||
_audioCategories[i].AudioAgents[j] = null;
|
||||
audioAgent.Destroy();
|
||||
audioAgent = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_audioCategories[i] = null;
|
||||
audioCategory = null;
|
||||
}
|
||||
|
||||
Initialize();
|
||||
@@ -538,11 +539,11 @@ namespace TEngine
|
||||
/// </summary>
|
||||
private void Update()
|
||||
{
|
||||
for (int i = 0; i < _audioCategories.Length; ++i)
|
||||
foreach (var audioCategory in _audioCategories)
|
||||
{
|
||||
if (_audioCategories[i] != null)
|
||||
if (audioCategory != null)
|
||||
{
|
||||
_audioCategories[i].Update(GameTime.deltaTime);
|
||||
audioCategory.Update(Time.deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -4,20 +4,38 @@ namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 游戏时间。
|
||||
/// <remarks>统一封装调用。</remarks>
|
||||
/// <remarks>提供从Unity获取时间信息的接口。</remarks>
|
||||
/// </summary>
|
||||
public static class GameTime
|
||||
{
|
||||
/// <summary>
|
||||
/// 此帧开始时的时间(只读)。
|
||||
/// </summary>
|
||||
public static float time;
|
||||
|
||||
/// <summary>
|
||||
/// 从上一帧到当前帧的间隔(秒)(只读)。
|
||||
/// </summary>
|
||||
public static float deltaTime;
|
||||
|
||||
/// <summary>
|
||||
/// timeScale从上一帧到当前帧的独立时间间隔(以秒为单位)(只读)。
|
||||
/// </summary>
|
||||
public static float unscaledDeltaTime;
|
||||
|
||||
/// <summary>
|
||||
/// 执行物理和其他固定帧速率更新(如MonoBehavior的MonoBehaviour.FixedUpdate)的时间间隔(以秒为单位)。
|
||||
/// </summary>
|
||||
public static float fixedDeltaTime;
|
||||
|
||||
/// <summary>
|
||||
/// 自游戏开始以来的总帧数(只读)。
|
||||
/// </summary>
|
||||
public static float frameCount;
|
||||
|
||||
/// <summary>
|
||||
/// timeScale此帧的独立时间(只读)。这是自游戏开始以来的时间(以秒为单位)。
|
||||
/// </summary>
|
||||
public static float unscaledTime;
|
||||
|
||||
public static void StartFrame()
|
||||
|
3
Assets/TEngine/Runtime/GameFramework/Resource/Pool.meta
Normal file
3
Assets/TEngine/Runtime/GameFramework/Resource/Pool.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62c8f710f3264758a89eaefc4ae88921
|
||||
timeCreated: 1693831262
|
@@ -0,0 +1,70 @@
|
||||
using YooAsset;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public class CreatePoolOperation : GameAsyncOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
Waiting,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly AssetOperationHandle _handle;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal CreatePoolOperation(AssetOperationHandle handle)
|
||||
{
|
||||
_handle = handle;
|
||||
}
|
||||
protected override void OnStart()
|
||||
{
|
||||
_steps = ESteps.Waiting;
|
||||
}
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.Waiting)
|
||||
{
|
||||
if (_handle.IsValid == false)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"{nameof(AssetOperationHandle)} is invalid.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (_handle.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_handle.AssetObject == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"{nameof(AssetOperationHandle.AssetObject)} is null.";
|
||||
return;
|
||||
}
|
||||
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 等待异步实例化结束。
|
||||
/// </summary>
|
||||
public void WaitForAsyncComplete()
|
||||
{
|
||||
if (_handle != null)
|
||||
{
|
||||
if (_steps == ESteps.Done)
|
||||
return;
|
||||
_handle.WaitForAsyncComplete();
|
||||
OnUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e1853e7ff624c639fba990079beeee5
|
||||
timeCreated: 1693831296
|
@@ -0,0 +1,234 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using YooAsset;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 游戏物体对象池。
|
||||
/// </summary>
|
||||
internal class GameObjectPool
|
||||
{
|
||||
private readonly GameObject _root;
|
||||
private readonly Queue<InstantiateOperation> _cacheOperations;
|
||||
private readonly bool _dontDestroy;
|
||||
private readonly int _initCapacity;
|
||||
private readonly int _maxCapacity;
|
||||
private readonly float _destroyTime;
|
||||
private float _lastRestoreRealTime = -1f;
|
||||
|
||||
/// <summary>
|
||||
/// 资源句柄。
|
||||
/// </summary>
|
||||
public AssetOperationHandle AssetHandle { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源定位地址。
|
||||
/// </summary>
|
||||
public string Location { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 内部缓存总数。
|
||||
/// </summary>
|
||||
public int CacheCount => _cacheOperations.Count;
|
||||
|
||||
/// <summary>
|
||||
/// 外部使用总数。
|
||||
/// </summary>
|
||||
public int SpawnCount { private set; get; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 是否常驻不销毁。
|
||||
/// </summary>
|
||||
public bool DontDestroy => _dontDestroy;
|
||||
|
||||
/// <summary>
|
||||
/// 游戏物体对象池。
|
||||
/// </summary>
|
||||
/// <param name="poolingRoot">对象池根节点。</param>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="dontDestroy">是否常驻不销毁。</param>
|
||||
/// <param name="initCapacity">初始容量。</param>
|
||||
/// <param name="maxCapacity">最大容量。</param>
|
||||
/// <param name="destroyTime">对象池销毁时间。</param>
|
||||
public GameObjectPool(GameObject poolingRoot, string location, bool dontDestroy, int initCapacity, int maxCapacity, float destroyTime)
|
||||
{
|
||||
_root = new GameObject(location);
|
||||
_root.transform.parent = poolingRoot.transform;
|
||||
Location = location;
|
||||
|
||||
_dontDestroy = dontDestroy;
|
||||
_initCapacity = initCapacity;
|
||||
_maxCapacity = maxCapacity;
|
||||
_destroyTime = destroyTime;
|
||||
|
||||
// 创建缓存池
|
||||
_cacheOperations = new Queue<InstantiateOperation>(initCapacity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建对象池。
|
||||
/// </summary>
|
||||
/// <param name="package">资源包。</param>
|
||||
public void CreatePool(ResourcePackage package)
|
||||
{
|
||||
// 加载游戏对象
|
||||
AssetHandle = package.LoadAssetAsync<GameObject>(Location);
|
||||
|
||||
// 创建初始对象
|
||||
for (int i = 0; i < _initCapacity; i++)
|
||||
{
|
||||
var operation = AssetHandle.InstantiateAsync(_root.transform);
|
||||
operation.Completed += Operation_Completed;
|
||||
_cacheOperations.Enqueue(operation);
|
||||
}
|
||||
}
|
||||
private void Operation_Completed(AsyncOperationBase obj)
|
||||
{
|
||||
if (obj.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
var op = obj as InstantiateOperation;
|
||||
if (op.Result != null)
|
||||
op.Result.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁游戏对象池。
|
||||
/// </summary>
|
||||
public void DestroyPool()
|
||||
{
|
||||
// 卸载资源对象
|
||||
AssetHandle.Release();
|
||||
AssetHandle = null;
|
||||
|
||||
// 销毁游戏对象
|
||||
Object.Destroy(_root);
|
||||
_cacheOperations.Clear();
|
||||
|
||||
SpawnCount = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询静默时间内是否可以销毁。
|
||||
/// </summary>
|
||||
public bool CanAutoDestroy()
|
||||
{
|
||||
if (_dontDestroy)
|
||||
return false;
|
||||
if (_destroyTime < 0)
|
||||
return false;
|
||||
|
||||
if (_lastRestoreRealTime > 0 && SpawnCount <= 0)
|
||||
return (Time.realtimeSinceStartup - _lastRestoreRealTime) > _destroyTime;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 游戏对象池是否已经销毁。
|
||||
/// </summary>
|
||||
public bool IsDestroyed()
|
||||
{
|
||||
return AssetHandle == null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收操作。
|
||||
/// </summary>
|
||||
/// <param name="operation">资源实例化操作句柄。</param>
|
||||
public void Restore(InstantiateOperation operation)
|
||||
{
|
||||
if (IsDestroyed())
|
||||
{
|
||||
DestroyInstantiateOperation(operation);
|
||||
return;
|
||||
}
|
||||
|
||||
SpawnCount--;
|
||||
if (SpawnCount <= 0)
|
||||
_lastRestoreRealTime = Time.realtimeSinceStartup;
|
||||
|
||||
// 如果外部逻辑销毁了游戏对象
|
||||
if (operation.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
if (operation.Result == null)
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果缓存池还未满员
|
||||
if (_cacheOperations.Count < _maxCapacity)
|
||||
{
|
||||
SetRestoreGameObject(operation.Result);
|
||||
_cacheOperations.Enqueue(operation);
|
||||
}
|
||||
else
|
||||
{
|
||||
DestroyInstantiateOperation(operation);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 丢弃操作。
|
||||
/// </summary>
|
||||
/// <param name="operation">资源实例化操作句柄。</param>
|
||||
public void Discard(InstantiateOperation operation)
|
||||
{
|
||||
if (IsDestroyed())
|
||||
{
|
||||
DestroyInstantiateOperation(operation);
|
||||
return;
|
||||
}
|
||||
|
||||
SpawnCount--;
|
||||
if (SpawnCount <= 0)
|
||||
_lastRestoreRealTime = Time.realtimeSinceStartup;
|
||||
|
||||
DestroyInstantiateOperation(operation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个游戏对象。
|
||||
/// </summary>
|
||||
/// <param name="parent">父节点位置。</param>
|
||||
/// <param name="position">位置。</param>
|
||||
/// <param name="rotation">旋转。</param>
|
||||
/// <param name="forceClone">是否强制克隆。</param>
|
||||
/// <param name="userDatas">用户自定义数据。</param>
|
||||
/// <returns>Spawn操作句柄。</returns>
|
||||
public SpawnHandle Spawn(Transform parent, Vector3 position, Quaternion rotation, bool forceClone, params System.Object[] userDatas)
|
||||
{
|
||||
InstantiateOperation operation;
|
||||
if (forceClone == false && _cacheOperations.Count > 0)
|
||||
operation = _cacheOperations.Dequeue();
|
||||
else
|
||||
operation = AssetHandle.InstantiateAsync();
|
||||
|
||||
SpawnCount++;
|
||||
SpawnHandle handle = new SpawnHandle(this, operation, parent, position, rotation, userDatas);
|
||||
YooAssets.StartOperation(handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
private void DestroyInstantiateOperation(InstantiateOperation operation)
|
||||
{
|
||||
// 取消异步操作
|
||||
operation.Cancel();
|
||||
|
||||
// 销毁游戏对象
|
||||
if (operation.Result != null)
|
||||
{
|
||||
Object.Destroy(operation.Result);
|
||||
}
|
||||
}
|
||||
private void SetRestoreGameObject(GameObject gameObj)
|
||||
{
|
||||
if (gameObj != null)
|
||||
{
|
||||
gameObj.SetActive(false);
|
||||
gameObj.transform.SetParent(_root.transform);
|
||||
gameObj.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3f0c9bab3d1243fda94ec9a08844ceee
|
||||
timeCreated: 1693831296
|
@@ -0,0 +1,253 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using YooAsset;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 游戏对象池系统。
|
||||
/// <remarks>用法 SpawnHandle handle = ResourcePool.SpawnAsync("Cube");</remarks>
|
||||
/// </summary>
|
||||
public static class ResourcePool
|
||||
{
|
||||
private static bool _isInitialize = false;
|
||||
private static readonly List<Spawner> Spawners = new List<Spawner>();
|
||||
private static GameObject _root;
|
||||
private static Spawner _defaultSpawner = null;
|
||||
|
||||
/// <summary>
|
||||
/// 默认Package对象生成器。
|
||||
/// </summary>
|
||||
private static Spawner DefaultSpawner => _defaultSpawner ??= CreateSpawner();
|
||||
|
||||
/// <summary>
|
||||
/// 初始化游戏对象池系统
|
||||
/// </summary>
|
||||
internal static void Initialize(GameObject root)
|
||||
{
|
||||
if (_isInitialize)
|
||||
throw new Exception($"{nameof(ResourcePool)} is initialized !");
|
||||
|
||||
if (_isInitialize == false)
|
||||
{
|
||||
_root = root;
|
||||
_isInitialize = true;
|
||||
Log.Info($"{nameof(ResourcePool)} Initialize !");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁游戏对象池系统
|
||||
/// </summary>
|
||||
internal static void Destroy()
|
||||
{
|
||||
if (_isInitialize)
|
||||
{
|
||||
foreach (var spawner in Spawners)
|
||||
{
|
||||
spawner.Destroy();
|
||||
}
|
||||
Spawners.Clear();
|
||||
|
||||
_isInitialize = false;
|
||||
|
||||
Log.Debug($"{nameof(ResourcePool)} destroy all !");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新游戏对象池系统
|
||||
/// </summary>
|
||||
internal static void Update()
|
||||
{
|
||||
if (_isInitialize)
|
||||
{
|
||||
foreach (var spawner in Spawners)
|
||||
{
|
||||
spawner.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建游戏对象生成器
|
||||
/// </summary>
|
||||
/// <param name="packageName">资源包名称</param>
|
||||
public static Spawner CreateSpawner(string packageName = "")
|
||||
{
|
||||
if (string.IsNullOrEmpty(packageName))
|
||||
{
|
||||
packageName = GameModule.Resource.packageName;
|
||||
}
|
||||
// 获取资源包
|
||||
var assetPackage = YooAssets.GetPackage(packageName);
|
||||
if (assetPackage == null)
|
||||
throw new Exception($"Not found asset package : {packageName}");
|
||||
|
||||
// 检测资源包初始化状态
|
||||
if (assetPackage.InitializeStatus == EOperationStatus.None)
|
||||
throw new Exception($"Asset package {packageName} not initialize !");
|
||||
if (assetPackage.InitializeStatus == EOperationStatus.Failed)
|
||||
throw new Exception($"Asset package {packageName} initialize failed !");
|
||||
|
||||
if (HasSpawner(packageName))
|
||||
return GetSpawner(packageName);
|
||||
|
||||
Spawner spawner = new Spawner(_root, assetPackage);
|
||||
Spawners.Add(spawner);
|
||||
return spawner;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取游戏对象生成器。
|
||||
/// </summary>
|
||||
/// <param name="packageName">资源包名称。</param>
|
||||
public static Spawner GetSpawner(string packageName = "")
|
||||
{
|
||||
if (string.IsNullOrEmpty(packageName))
|
||||
{
|
||||
packageName = GameModule.Resource.packageName;
|
||||
}
|
||||
foreach (var spawner in Spawners)
|
||||
{
|
||||
if (spawner.PackageName == packageName)
|
||||
return spawner;
|
||||
}
|
||||
|
||||
Log.Warning($"Not found spawner : {packageName}");
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测游戏对象生成器是否存在。
|
||||
/// </summary>
|
||||
/// <param name="packageName">资源包名称。</param>
|
||||
public static bool HasSpawner(string packageName = "")
|
||||
{
|
||||
if (string.IsNullOrEmpty(packageName))
|
||||
{
|
||||
packageName = GameModule.Resource.packageName;
|
||||
}
|
||||
foreach (var spawner in Spawners)
|
||||
{
|
||||
if (spawner.PackageName == packageName)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#region 操作接口
|
||||
|
||||
/// <summary>
|
||||
/// 销毁所有对象池及其资源。
|
||||
/// </summary>
|
||||
/// <param name="includeAll">销毁所有对象池,包括常驻对象池。</param>
|
||||
public static void DestroyAll(bool includeAll)
|
||||
{
|
||||
DefaultSpawner.DestroyAll(includeAll);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 异步创建指定资源的游戏对象池。
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="dontDestroy">资源常驻不销毁。</param>
|
||||
/// <param name="initCapacity">对象池的初始容量。</param>
|
||||
/// <param name="maxCapacity">对象池的最大容量。</param>
|
||||
/// <param name="destroyTime">静默销毁时间(注意:小于零代表不主动销毁)。</param>
|
||||
public static CreatePoolOperation CreateGameObjectPoolAsync(string location, bool dontDestroy = false, int initCapacity = 0, int maxCapacity = int.MaxValue, float destroyTime = -1f)
|
||||
{
|
||||
return DefaultSpawner.CreateGameObjectPoolAsync(location, dontDestroy, initCapacity, maxCapacity, destroyTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步创建指定资源的游戏对象池。
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="dontDestroy">资源常驻不销毁。</param>
|
||||
/// <param name="initCapacity">对象池的初始容量。</param>
|
||||
/// <param name="maxCapacity">对象池的最大容量。</param>
|
||||
/// <param name="destroyTime">静默销毁时间(注意:小于零代表不主动销毁)。</param>
|
||||
public static CreatePoolOperation CreateGameObjectPoolSync(string location, bool dontDestroy = false, int initCapacity = 0, int maxCapacity = int.MaxValue, float destroyTime = -1f)
|
||||
{
|
||||
return DefaultSpawner.CreateGameObjectPoolSync(location, dontDestroy, initCapacity, maxCapacity, destroyTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步实例化一个游戏对象。
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象。</param>
|
||||
/// <param name="userDatas">用户自定义数据。</param>
|
||||
public static SpawnHandle SpawnAsync(string location, bool forceClone = false, params System.Object[] userDatas)
|
||||
{
|
||||
return DefaultSpawner.SpawnAsync(location, null, Vector3.zero, Quaternion.identity, forceClone, userDatas);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步实例化一个游戏对象。
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="parent">父物体。</param>
|
||||
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象。</param>
|
||||
/// <param name="userDatas">用户自定义数据。</param>
|
||||
public static SpawnHandle SpawnAsync(string location, Transform parent, bool forceClone = false, params System.Object[] userDatas)
|
||||
{
|
||||
return DefaultSpawner.SpawnAsync(location, parent, Vector3.zero, Quaternion.identity, forceClone, userDatas);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步实例化一个游戏对象。
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="parent">父物体。</param>
|
||||
/// <param name="position">世界坐标。</param>
|
||||
/// <param name="rotation">世界角度。</param>
|
||||
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象。</param>
|
||||
/// <param name="userDatas">用户自定义数据。</param>
|
||||
public static SpawnHandle SpawnAsync(string location, Transform parent, Vector3 position, Quaternion rotation, bool forceClone = false, params System.Object[] userDatas)
|
||||
{
|
||||
return DefaultSpawner.SpawnAsync(location, parent, position, rotation, forceClone, userDatas);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步实例化一个游戏对象。
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象。</param>
|
||||
/// <param name="userDatas">用户自定义数据。</param>
|
||||
public static SpawnHandle SpawnSync(string location, bool forceClone = false, params System.Object[] userDatas)
|
||||
{
|
||||
return DefaultSpawner.SpawnSync(location, null, Vector3.zero, Quaternion.identity, forceClone, userDatas);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步实例化一个游戏对象。
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="parent">父物体</param>
|
||||
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象。</param>
|
||||
/// <param name="userDatas">用户自定义数据。</param>
|
||||
public static SpawnHandle SpawnSync(string location, Transform parent, bool forceClone = false, params System.Object[] userDatas)
|
||||
{
|
||||
return DefaultSpawner.SpawnAsync(location, parent, forceClone, userDatas);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步实例化一个游戏对象。
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="parent">父物体。</param>
|
||||
/// <param name="position">世界坐标。</param>
|
||||
/// <param name="rotation">世界角度。</param>
|
||||
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象。</param>
|
||||
/// <param name="userDatas">用户自定义数据。</param>
|
||||
public static SpawnHandle SpawnSync(string location, Transform parent, Vector3 position, Quaternion rotation, bool forceClone = false, params System.Object[] userDatas)
|
||||
{
|
||||
return DefaultSpawner.SpawnSync(location,parent,position,rotation,forceClone,userDatas);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be208ee3e46e4243b9a68d4c7212015e
|
||||
timeCreated: 1693831058
|
@@ -0,0 +1,152 @@
|
||||
using UnityEngine;
|
||||
using YooAsset;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public sealed class SpawnHandle : GameAsyncOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
Waiting,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly GameObjectPool _pool;
|
||||
private InstantiateOperation _operation;
|
||||
private readonly Transform _parent;
|
||||
private readonly Vector3 _position;
|
||||
private readonly Quaternion _rotation;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
/// <summary>
|
||||
/// 实例化的游戏对象。
|
||||
/// </summary>
|
||||
public GameObject GameObj
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_operation == null)
|
||||
{
|
||||
Log.Warning("The spawn handle is invalid !");
|
||||
return null;
|
||||
}
|
||||
|
||||
return _operation.Result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用户自定义数据集。
|
||||
/// </summary>
|
||||
public System.Object[] UserDatas { private set; get; }
|
||||
|
||||
private SpawnHandle()
|
||||
{
|
||||
}
|
||||
|
||||
internal SpawnHandle(GameObjectPool pool, InstantiateOperation operation, Transform parent, Vector3 position, Quaternion rotation,
|
||||
params System.Object[] userDatas)
|
||||
{
|
||||
_pool = pool;
|
||||
_operation = operation;
|
||||
_parent = parent;
|
||||
_position = position;
|
||||
_rotation = rotation;
|
||||
UserDatas = userDatas;
|
||||
}
|
||||
|
||||
protected override void OnStart()
|
||||
{
|
||||
_steps = ESteps.Waiting;
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.Waiting)
|
||||
{
|
||||
if (_operation.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_operation.Status != EOperationStatus.Succeed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _operation.Error;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_operation.Result == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Clone game object is null.";
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置参数
|
||||
_operation.Result.transform.SetParent(_parent);
|
||||
_operation.Result.transform.SetPositionAndRotation(_position, _rotation);
|
||||
_operation.Result.SetActive(true);
|
||||
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收对象。
|
||||
/// </summary>
|
||||
public void Restore()
|
||||
{
|
||||
if (_operation != null)
|
||||
{
|
||||
ClearCompletedCallback();
|
||||
CancelHandle();
|
||||
_pool.Restore(_operation);
|
||||
_operation = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 丢弃对象。
|
||||
/// </summary>
|
||||
public void Discard()
|
||||
{
|
||||
if (_operation != null)
|
||||
{
|
||||
ClearCompletedCallback();
|
||||
CancelHandle();
|
||||
_pool.Discard(_operation);
|
||||
_operation = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 等待异步实例化结束。
|
||||
/// </summary>
|
||||
public void WaitForAsyncComplete()
|
||||
{
|
||||
if (_operation != null)
|
||||
{
|
||||
if (_steps == ESteps.Done)
|
||||
return;
|
||||
_operation.WaitForAsyncComplete();
|
||||
OnUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
private void CancelHandle()
|
||||
{
|
||||
if (IsDone == false)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"User cancelled !";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eb2cdce8eb814f7c92c74199d065688a
|
||||
timeCreated: 1693831296
|
262
Assets/TEngine/Runtime/GameFramework/Resource/Pool/Spawner.cs
Normal file
262
Assets/TEngine/Runtime/GameFramework/Resource/Pool/Spawner.cs
Normal file
@@ -0,0 +1,262 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using YooAsset;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 对象生成器。
|
||||
/// </summary>
|
||||
public class Spawner
|
||||
{
|
||||
private readonly List<GameObjectPool> _gameObjectPools = new List<GameObjectPool>(100);
|
||||
private readonly List<GameObjectPool> _removeList = new List<GameObjectPool>(100);
|
||||
private readonly GameObject _spawnerRoot;
|
||||
private readonly ResourcePackage _package;
|
||||
|
||||
public string PackageName
|
||||
{
|
||||
get
|
||||
{
|
||||
return _package.PackageName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Spawner()
|
||||
{
|
||||
}
|
||||
internal Spawner(GameObject poolingRoot, ResourcePackage package)
|
||||
{
|
||||
_spawnerRoot = new GameObject($"{package.PackageName}");
|
||||
_spawnerRoot.transform.SetParent(poolingRoot.transform);
|
||||
_package = package;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新游戏对象池系统。
|
||||
/// </summary>
|
||||
internal void Update()
|
||||
{
|
||||
_removeList.Clear();
|
||||
foreach (var pool in _gameObjectPools)
|
||||
{
|
||||
if (pool.CanAutoDestroy())
|
||||
_removeList.Add(pool);
|
||||
}
|
||||
|
||||
foreach (var pool in _removeList)
|
||||
{
|
||||
_gameObjectPools.Remove(pool);
|
||||
pool.DestroyPool();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁游戏对象池系统。
|
||||
/// </summary>
|
||||
internal void Destroy()
|
||||
{
|
||||
DestroyAll(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁所有对象池及其资源。
|
||||
/// </summary>
|
||||
/// <param name="includeAll">销毁所有对象池,包括常驻对象池。</param>
|
||||
public void DestroyAll(bool includeAll)
|
||||
{
|
||||
if (includeAll)
|
||||
{
|
||||
foreach (var pool in _gameObjectPools)
|
||||
{
|
||||
pool.DestroyPool();
|
||||
}
|
||||
_gameObjectPools.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
List<GameObjectPool> removeList = new List<GameObjectPool>();
|
||||
foreach (var pool in _gameObjectPools)
|
||||
{
|
||||
if (pool.DontDestroy == false)
|
||||
removeList.Add(pool);
|
||||
}
|
||||
foreach (var pool in removeList)
|
||||
{
|
||||
_gameObjectPools.Remove(pool);
|
||||
pool.DestroyPool();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 异步创建指定资源的游戏对象池。
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="dontDestroy">资源常驻不销毁。</param>
|
||||
/// <param name="initCapacity">对象池的初始容量。</param>
|
||||
/// <param name="maxCapacity">对象池的最大容量。</param>
|
||||
/// <param name="destroyTime">静默销毁时间(注意:小于零代表不主动销毁)。</param>
|
||||
public CreatePoolOperation CreateGameObjectPoolAsync(string location, bool dontDestroy = false, int initCapacity = 0, int maxCapacity = int.MaxValue, float destroyTime = -1f)
|
||||
{
|
||||
return CreateGameObjectPoolInternal(location, dontDestroy, initCapacity, maxCapacity, destroyTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步创建指定资源的游戏对象池。
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="dontDestroy">资源常驻不销毁。</param>
|
||||
/// <param name="initCapacity">对象池的初始容量。</param>
|
||||
/// <param name="maxCapacity">对象池的最大容量。</param>
|
||||
/// <param name="destroyTime">静默销毁时间(注意:小于零代表不主动销毁)。</param>
|
||||
public CreatePoolOperation CreateGameObjectPoolSync(string location, bool dontDestroy = false, int initCapacity = 0, int maxCapacity = int.MaxValue, float destroyTime = -1f)
|
||||
{
|
||||
var operation = CreateGameObjectPoolInternal(location, dontDestroy, initCapacity, maxCapacity, destroyTime);
|
||||
operation.WaitForAsyncComplete();
|
||||
return operation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建指定资源的游戏对象池。
|
||||
/// </summary>
|
||||
private CreatePoolOperation CreateGameObjectPoolInternal(string location, bool dontDestroy = false, int initCapacity = 0, int maxCapacity = int.MaxValue, float destroyTime = -1f)
|
||||
{
|
||||
if (maxCapacity < initCapacity)
|
||||
throw new Exception("The max capacity value must be greater the init capacity value.");
|
||||
|
||||
GameObjectPool pool = TryGetGameObjectPool(location);
|
||||
if (pool != null)
|
||||
{
|
||||
Log.Warning($"GameObject pool is already existed : {location}");
|
||||
var operation = new CreatePoolOperation(pool.AssetHandle);
|
||||
YooAssets.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
else
|
||||
{
|
||||
pool = new GameObjectPool(_spawnerRoot, location, dontDestroy, initCapacity, maxCapacity, destroyTime);
|
||||
pool.CreatePool(_package);
|
||||
_gameObjectPools.Add(pool);
|
||||
|
||||
var operation = new CreatePoolOperation(pool.AssetHandle);
|
||||
YooAssets.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 异步实例化一个游戏对象。
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象。</param>
|
||||
/// <param name="userDatas">用户自定义数据。</param>
|
||||
public SpawnHandle SpawnAsync(string location, bool forceClone = false, params System.Object[] userDatas)
|
||||
{
|
||||
return SpawnInternal(location, null, Vector3.zero, Quaternion.identity, forceClone, userDatas);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步实例化一个游戏对象。
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="parent">父物体。</param>
|
||||
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象。</param>
|
||||
/// <param name="userDatas">用户自定义数据。</param>
|
||||
public SpawnHandle SpawnAsync(string location, Transform parent, bool forceClone = false, params System.Object[] userDatas)
|
||||
{
|
||||
return SpawnInternal(location, parent, Vector3.zero, Quaternion.identity, forceClone, userDatas);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步实例化一个游戏对象。
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="parent">父物体。</param>
|
||||
/// <param name="position">世界坐标。</param>
|
||||
/// <param name="rotation">世界角度。</param>
|
||||
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象。</param>
|
||||
/// <param name="userDatas">用户自定义数据。</param>
|
||||
public SpawnHandle SpawnAsync(string location, Transform parent, Vector3 position, Quaternion rotation, bool forceClone = false, params System.Object[] userDatas)
|
||||
{
|
||||
return SpawnInternal(location, parent, position, rotation, forceClone, userDatas);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步实例化一个游戏对象。
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象。</param>
|
||||
/// <param name="userDatas">用户自定义数据。</param>
|
||||
public SpawnHandle SpawnSync(string location, bool forceClone = false, params System.Object[] userDatas)
|
||||
{
|
||||
SpawnHandle handle = SpawnInternal(location, null, Vector3.zero, Quaternion.identity, forceClone, userDatas);
|
||||
handle.WaitForAsyncComplete();
|
||||
return handle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步实例化一个游戏对象。
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="parent">父物体</param>
|
||||
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象。</param>
|
||||
/// <param name="userDatas">用户自定义数据。</param>
|
||||
public SpawnHandle SpawnSync(string location, Transform parent, bool forceClone = false, params System.Object[] userDatas)
|
||||
{
|
||||
SpawnHandle handle = SpawnInternal(location, parent, Vector3.zero, Quaternion.identity, forceClone, userDatas);
|
||||
handle.WaitForAsyncComplete();
|
||||
return handle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步实例化一个游戏对象。
|
||||
/// </summary>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="parent">父物体。</param>
|
||||
/// <param name="position">世界坐标。</param>
|
||||
/// <param name="rotation">世界角度。</param>
|
||||
/// <param name="forceClone">强制克隆游戏对象,忽略缓存池里的对象。</param>
|
||||
/// <param name="userDatas">用户自定义数据。</param>
|
||||
public SpawnHandle SpawnSync(string location, Transform parent, Vector3 position, Quaternion rotation, bool forceClone = false, params System.Object[] userDatas)
|
||||
{
|
||||
SpawnHandle handle = SpawnInternal(location, parent, position, rotation, forceClone, userDatas);
|
||||
handle.WaitForAsyncComplete();
|
||||
return handle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 实例化一个游戏对象。
|
||||
/// </summary>
|
||||
private SpawnHandle SpawnInternal(string location, Transform parent, Vector3 position, Quaternion rotation, bool forceClone, params System.Object[] userDatas)
|
||||
{
|
||||
var pool = TryGetGameObjectPool(location);
|
||||
if (pool != null)
|
||||
{
|
||||
return pool.Spawn(parent, position, rotation, forceClone, userDatas);
|
||||
}
|
||||
|
||||
// 如果不存在创建游戏对象池
|
||||
pool = new GameObjectPool(_spawnerRoot, location, false, 0, int.MaxValue, -1f);
|
||||
pool.CreatePool(_package);
|
||||
_gameObjectPools.Add(pool);
|
||||
return pool.Spawn(parent, position, rotation, forceClone, userDatas);
|
||||
}
|
||||
|
||||
|
||||
private GameObjectPool TryGetGameObjectPool(string location)
|
||||
{
|
||||
foreach (var pool in _gameObjectPools)
|
||||
{
|
||||
if (pool.Location == location)
|
||||
return pool;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 570ac9abe8a04e77b49c42719a9fa93b
|
||||
timeCreated: 1693831272
|
@@ -9,9 +9,10 @@ namespace TEngine
|
||||
/// <summary>
|
||||
/// 资源管理器。
|
||||
/// </summary>
|
||||
internal partial class ResourceManager: GameFrameworkModule,IResourceManager
|
||||
internal partial class ResourceManager : GameFrameworkModule, IResourceManager
|
||||
{
|
||||
#region Propreties
|
||||
|
||||
/// <summary>
|
||||
/// 资源包名称。
|
||||
/// </summary>
|
||||
@@ -75,20 +76,26 @@ namespace TEngine
|
||||
/// </summary>
|
||||
/// <remarks>优先级较高的模块会优先轮询,并且关闭操作会后进行。</remarks>
|
||||
internal override int Priority => 4;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 生命周期
|
||||
|
||||
internal override void Update(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
ResourcePool.Update();
|
||||
}
|
||||
|
||||
internal override void Shutdown()
|
||||
{
|
||||
YooAssets.Destroy();
|
||||
ResourcePool.Destroy();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 设置接口
|
||||
|
||||
/// <summary>
|
||||
/// 设置资源只读区路径。
|
||||
/// </summary>
|
||||
@@ -116,6 +123,7 @@ namespace TEngine
|
||||
|
||||
m_ReadWritePath = readWritePath;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void Initialize()
|
||||
@@ -133,6 +141,7 @@ namespace TEngine
|
||||
defaultPackage = YooAssets.CreatePackage(packageName);
|
||||
YooAssets.SetDefaultPackage(defaultPackage);
|
||||
}
|
||||
ResourcePool.Initialize(GameModule.Resource.gameObject);
|
||||
}
|
||||
|
||||
public InitializationOperation InitPackage()
|
||||
@@ -296,6 +305,7 @@ namespace TEngine
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 同步加载资源。
|
||||
/// </summary>
|
||||
@@ -309,6 +319,7 @@ namespace TEngine
|
||||
Log.Error("Asset name is invalid.");
|
||||
return default;
|
||||
}
|
||||
|
||||
AssetOperationHandle handle = YooAssets.LoadAssetSync<T>(assetName);
|
||||
|
||||
if (typeof(T) == typeof(GameObject))
|
||||
@@ -339,6 +350,7 @@ namespace TEngine
|
||||
Log.Error("Asset name is invalid.");
|
||||
return default;
|
||||
}
|
||||
|
||||
AssetOperationHandle handle = YooAssets.LoadAssetSync<T>(assetName);
|
||||
|
||||
if (typeof(T) == typeof(GameObject))
|
||||
@@ -362,7 +374,7 @@ namespace TEngine
|
||||
/// <param name="assetName">要加载资源的名称。</param>
|
||||
/// <typeparam name="T">要加载资源的类型。</typeparam>
|
||||
/// <returns>资源实例。</returns>
|
||||
public T LoadAsset<T>(string assetName,out AssetOperationHandle handle) where T : Object
|
||||
public T LoadAsset<T>(string assetName, out AssetOperationHandle handle) where T : Object
|
||||
{
|
||||
handle = YooAssets.LoadAssetSync<T>(assetName);
|
||||
|
||||
@@ -391,7 +403,7 @@ namespace TEngine
|
||||
/// <param name="parent">父节点位置。</param>
|
||||
/// <typeparam name="T">要加载资源的类型。</typeparam>
|
||||
/// <returns>资源实例。</returns>
|
||||
public T LoadAsset<T>(string assetName, Transform parent,out AssetOperationHandle handle) where T : Object
|
||||
public T LoadAsset<T>(string assetName, Transform parent, out AssetOperationHandle handle) where T : Object
|
||||
{
|
||||
handle = YooAssets.LoadAssetSync<T>(assetName);
|
||||
|
||||
@@ -471,9 +483,10 @@ namespace TEngine
|
||||
/// <param name="activateOnLoad">加载完毕时是否主动激活</param>
|
||||
/// <param name="priority">优先级</param>
|
||||
/// <returns>异步加载场景句柄。</returns>
|
||||
public SceneOperationHandle LoadSceneAsync(string location, LoadSceneMode sceneMode = LoadSceneMode.Single, bool activateOnLoad = true, int priority = 100)
|
||||
public SceneOperationHandle LoadSceneAsync(string location, LoadSceneMode sceneMode = LoadSceneMode.Single, bool activateOnLoad = true,
|
||||
int priority = 100)
|
||||
{
|
||||
return YooAssets.LoadSceneAsync(location,sceneMode,activateOnLoad,priority);
|
||||
return YooAssets.LoadSceneAsync(location, sceneMode, activateOnLoad, priority);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -484,9 +497,10 @@ namespace TEngine
|
||||
/// <param name="activateOnLoad">加载完毕时是否主动激活</param>
|
||||
/// <param name="priority">优先级</param>
|
||||
/// <returns>异步加载场景句柄。</returns>
|
||||
public SceneOperationHandle LoadSceneAsync(AssetInfo assetInfo, LoadSceneMode sceneMode = LoadSceneMode.Single, bool activateOnLoad = true, int priority = 100)
|
||||
public SceneOperationHandle LoadSceneAsync(AssetInfo assetInfo, LoadSceneMode sceneMode = LoadSceneMode.Single, bool activateOnLoad = true,
|
||||
int priority = 100)
|
||||
{
|
||||
return YooAssets.LoadSceneAsync(assetInfo,sceneMode,activateOnLoad,priority);
|
||||
return YooAssets.LoadSceneAsync(assetInfo, sceneMode, activateOnLoad, priority);
|
||||
}
|
||||
|
||||
|
||||
@@ -554,7 +568,7 @@ namespace TEngine
|
||||
/// <returns>异步游戏物体实例。</returns>
|
||||
public async UniTask<GameObject> LoadGameObjectAsync(string location, Transform parent, CancellationToken cancellationToken)
|
||||
{
|
||||
GameObject gameObject = await LoadGameObjectAsync(location,cancellationToken);
|
||||
GameObject gameObject = await LoadGameObjectAsync(location, cancellationToken);
|
||||
if (parent != null)
|
||||
{
|
||||
gameObject.transform.SetParent(parent);
|
||||
@@ -563,6 +577,7 @@ namespace TEngine
|
||||
{
|
||||
Log.Error("Set Parent Failed");
|
||||
}
|
||||
|
||||
return gameObject;
|
||||
}
|
||||
|
||||
@@ -572,14 +587,13 @@ namespace TEngine
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="cancellationToken">取消操作Token。</param>
|
||||
/// <returns>原生文件资源实例操作句柄。</returns>
|
||||
/// <remarks>需要自行释放资源句柄(RawFileOperationHandle)。</remarks>
|
||||
public async UniTask<RawFileOperationHandle> LoadRawAssetAsync(string location, CancellationToken cancellationToken)
|
||||
{
|
||||
RawFileOperationHandle handle = YooAssets.LoadRawFileAsync(location);
|
||||
|
||||
bool cancelOrFailed = await handle.ToUniTask().AttachExternalCancellation(cancellationToken).SuppressCancellationThrow();
|
||||
|
||||
handle.Dispose();
|
||||
|
||||
return cancelOrFailed ? null : handle;
|
||||
}
|
||||
|
||||
@@ -591,7 +605,7 @@ namespace TEngine
|
||||
/// <param name="cancellationToken">取消操作Token。</param>
|
||||
/// <typeparam name="T">资源实例类型。</typeparam>
|
||||
/// <returns>原生文件资源实例。</returns>
|
||||
public async UniTask<T> LoadSubAssetAsync<T>(string location,string assetName, CancellationToken cancellationToken) where T : Object
|
||||
public async UniTask<T> LoadSubAssetAsync<T>(string location, string assetName, CancellationToken cancellationToken) where T : Object
|
||||
{
|
||||
var assetInfo = GetAssetInfo(location);
|
||||
if (assetInfo == null)
|
||||
@@ -616,7 +630,7 @@ namespace TEngine
|
||||
/// <param name="cancellationToken">取消操作Token。</param>
|
||||
/// <typeparam name="T">资源实例类型。</typeparam>
|
||||
/// <returns>原生文件资源实例。</returns>
|
||||
public async UniTask<T[]> LoadAllSubAssetAsync<T>(string location,CancellationToken cancellationToken) where T : Object
|
||||
public async UniTask<T[]> LoadAllSubAssetAsync<T>(string location, CancellationToken cancellationToken) where T : Object
|
||||
{
|
||||
var assetInfo = GetAssetInfo(location);
|
||||
if (assetInfo == null)
|
||||
@@ -643,10 +657,11 @@ namespace TEngine
|
||||
/// <param name="activateOnLoad">加载完毕时是否主动激活.</param>
|
||||
/// <param name="priority">优先级.</param>
|
||||
/// <returns>场景资源实例。</returns>
|
||||
public async UniTask<Scene> LoadSceneAsyncByUniTask(string location,CancellationToken cancellationToken,LoadSceneMode sceneMode = LoadSceneMode.Single,
|
||||
public async UniTask<Scene> LoadSceneAsyncByUniTask(string location, CancellationToken cancellationToken,
|
||||
LoadSceneMode sceneMode = LoadSceneMode.Single,
|
||||
bool activateOnLoad = true, int priority = 100)
|
||||
{
|
||||
SceneOperationHandle handle = YooAssets.LoadSceneAsync(location,sceneMode,activateOnLoad,priority);
|
||||
SceneOperationHandle handle = YooAssets.LoadSceneAsync(location, sceneMode, activateOnLoad, priority);
|
||||
|
||||
bool cancelOrFailed = await handle.ToUniTask().AttachExternalCancellation(cancellationToken).SuppressCancellationThrow();
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
/// </summary>
|
||||
public sealed class DefaultSettingSerializer : GameFrameworkSerializer<DefaultSetting>
|
||||
{
|
||||
private static readonly byte[] Header = new byte[] { (byte)'G', (byte)'F', (byte)'S' };
|
||||
private static readonly byte[] Header = new byte[] { (byte)'T', (byte)'E', (byte)'S' };
|
||||
|
||||
/// <summary>
|
||||
/// 初始化默认游戏配置序列化器的新实例。
|
||||
|
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b9128b665b538746a11489aee369030
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -13,6 +13,19 @@ public class Actor : ObjectBase
|
||||
/// </summary>
|
||||
/// <param name="isShutdown">是否是关闭对象池时触发。</param>
|
||||
protected override void Release(bool isShutdown){}
|
||||
|
||||
/// <summary>
|
||||
/// 创建Actor对象。
|
||||
/// </summary>
|
||||
/// <param name="actorName">对象名称。</param>
|
||||
/// <param name="target">对象持有实例。</param>
|
||||
/// <returns></returns>
|
||||
public static Actor Create(string name, object target)
|
||||
{
|
||||
var actor = MemoryPool.Acquire<Actor>();
|
||||
actor.Initialize(name, target);
|
||||
return actor;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -29,8 +42,10 @@ void Start()
|
||||
/// <summary>
|
||||
/// 创建Actor对象。
|
||||
/// </summary>
|
||||
/// <returns>Actor对象实例。</returns>
|
||||
public Actor CreateActor()
|
||||
/// <param name="actorName">对象名称。</param>
|
||||
/// <param name="target">对象持有实例。</param>
|
||||
/// <returns>Actor对象实例</returns>
|
||||
public Actor CreateActor(string actorName, GameObject target)
|
||||
{
|
||||
Actor ret = null;
|
||||
if (_actorPool.CanSpawn())
|
||||
@@ -39,7 +54,7 @@ public Actor CreateActor()
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = MemoryPool.Acquire<Actor>();
|
||||
ret = Actor.Create(actorName, target);
|
||||
_actorPool.Register(ret,true);
|
||||
}
|
||||
|
||||
|
@@ -60,6 +60,10 @@
|
||||
"Value": "../../Client/Unity/Assets/Scripts/Hotfix/Generate/CustomExport/",
|
||||
"Comment": "客户端自定义导出代码文件夹位置"
|
||||
},
|
||||
"SceneConfigPath": {
|
||||
"Value": "../../../Config/Excel/Server/SceneConfig.xlsx",
|
||||
"Comment": "SceneConfig.xlsx的位置"
|
||||
},
|
||||
"CustomExportAssembly": {
|
||||
"Value": "Logic",
|
||||
"Comment": "自定义导出代码存放的程序集"
|
||||
|
@@ -40,6 +40,7 @@ namespace Bright.Serialization
|
||||
|
||||
public sealed class ByteBuf : ICloneable, IEquatable<ByteBuf>
|
||||
{
|
||||
#pragma warning disable CS8618
|
||||
public ByteBuf()
|
||||
{
|
||||
Bytes = Array.Empty<byte>();
|
||||
@@ -76,6 +77,7 @@ namespace Bright.Serialization
|
||||
{
|
||||
return new ByteBuf(bytes, 0, bytes.Length);
|
||||
}
|
||||
#pragma warning restore CS8618
|
||||
|
||||
public void Replace(byte[] bytes)
|
||||
{
|
||||
@@ -1015,20 +1017,24 @@ namespace Bright.Serialization
|
||||
return ((long)((ulong)x >> 1) ^ ((x & 1) << 63));
|
||||
}
|
||||
|
||||
public void WriteString(string x)
|
||||
public void WriteString(string? x)
|
||||
{
|
||||
var n = x != null ? Encoding.UTF8.GetByteCount(x) : 0;
|
||||
WriteSize(n);
|
||||
if (n > 0)
|
||||
{
|
||||
EnsureWrite(n);
|
||||
Encoding.UTF8.GetBytes(x, 0, x.Length, Bytes, WriterIndex);
|
||||
if (x != null)
|
||||
{
|
||||
Encoding.UTF8.GetBytes(x, 0, x.Length, this.Bytes, this.WriterIndex);
|
||||
}
|
||||
|
||||
WriterIndex += n;
|
||||
}
|
||||
}
|
||||
|
||||
// byte[], [start, end)
|
||||
public static Func<byte[], int, int, string> StringCacheFinder { get; set; }
|
||||
public static Func<byte[], int, int, string>? StringCacheFinder { get; set; }
|
||||
|
||||
public string ReadString()
|
||||
{
|
||||
@@ -1056,14 +1062,14 @@ namespace Bright.Serialization
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] x)
|
||||
public void WriteBytes(byte[]? x)
|
||||
{
|
||||
var n = x != null ? x.Length : 0;
|
||||
WriteSize(n);
|
||||
if (n > 0)
|
||||
{
|
||||
EnsureWrite(n);
|
||||
x.CopyTo(Bytes, WriterIndex);
|
||||
x?.CopyTo(Bytes, WriterIndex);
|
||||
WriterIndex += n;
|
||||
}
|
||||
}
|
||||
@@ -1485,12 +1491,12 @@ namespace Bright.Serialization
|
||||
return string.Join(".", datas);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return (obj is ByteBuf other) && Equals(other);
|
||||
}
|
||||
|
||||
public bool Equals(ByteBuf other)
|
||||
public bool Equals(ByteBuf? other)
|
||||
{
|
||||
if (other == null)
|
||||
{
|
||||
|
@@ -1,48 +1,104 @@
|
||||
#if TENGINE_NET
|
||||
using System.Text;
|
||||
using TEngine.Core;
|
||||
using TEngine.Helper;
|
||||
|
||||
namespace TEngine.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 将场景类型配置表转换为枚举和字典的自定义导出类。
|
||||
/// </summary>
|
||||
public sealed class SceneTypeConfigToEnum : ACustomExport
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行自定义导出操作。
|
||||
/// </summary>
|
||||
public override void Run()
|
||||
{
|
||||
var serverSceneType = new HashSet<string>();
|
||||
var instanceList = SceneConfigData.Instance.List;
|
||||
|
||||
foreach (var sceneConfig in instanceList)
|
||||
// 获取场景配置表的完整路径
|
||||
using var excelPackage = ExcelHelper.LoadExcel(Define.SceneConfigPath);
|
||||
var sceneType = new Dictionary<string, string>();
|
||||
var sceneSubType = new Dictionary<string, string>();
|
||||
// 获取场景类型配置工作表
|
||||
var sceneTypeConfig = excelPackage.Workbook.Worksheets["SceneTypeConfig"];
|
||||
// 遍历场景类型配置表的行
|
||||
for (var row = 3; row <= sceneTypeConfig.Dimension.Rows; row++)
|
||||
{
|
||||
serverSceneType.Add(sceneConfig.SceneType);
|
||||
var sceneTypeId = sceneTypeConfig.GetCellValue(row, 1);
|
||||
var sceneTypeStr = sceneTypeConfig.GetCellValue(row, 2);
|
||||
|
||||
if (string.IsNullOrEmpty(sceneTypeId) || string.IsNullOrEmpty(sceneTypeStr))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sceneType.Add(sceneTypeId, sceneTypeStr);
|
||||
}
|
||||
|
||||
if (serverSceneType.Count > 0)
|
||||
// 获取场景子类型配置工作表
|
||||
var sceneSubTypeConfig = excelPackage.Workbook.Worksheets["SceneSubTypeConfig"];
|
||||
// 遍历场景子类型配置表的行
|
||||
for (var row = 3; row <= sceneSubTypeConfig.Dimension.Rows; row++)
|
||||
{
|
||||
Write(CustomExportType.Server, serverSceneType);
|
||||
var sceneSubTypeId = sceneSubTypeConfig.GetCellValue(row, 1);
|
||||
var sceneSubTypeStr = sceneSubTypeConfig.GetCellValue(row, 2);
|
||||
|
||||
if (string.IsNullOrEmpty(sceneSubTypeId) || string.IsNullOrEmpty(sceneSubTypeStr))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sceneSubType.Add(sceneSubTypeId, sceneSubTypeStr);
|
||||
}
|
||||
// 如果存在场景类型或场景子类型,执行导出操作
|
||||
if (sceneType.Count > 0 || sceneSubType.Count > 0)
|
||||
{
|
||||
Write(CustomExportType.Server, sceneType, sceneSubType);
|
||||
}
|
||||
}
|
||||
|
||||
private void Write(CustomExportType customExportType, HashSet<string> sceneTypes)
|
||||
private void Write(CustomExportType customExportType, Dictionary<string, string> sceneTypes, Dictionary<string, string> sceneSubType)
|
||||
{
|
||||
var index = 0;
|
||||
var strBuilder = new StringBuilder();
|
||||
var dicBuilder = new StringBuilder();
|
||||
|
||||
// 添加命名空间和注释头部
|
||||
strBuilder.AppendLine("namespace TEngine\n{");
|
||||
strBuilder.AppendLine("\t// 生成器自动生成,请不要手动编辑。");
|
||||
strBuilder.AppendLine("\tpublic class SceneType\n\t{");
|
||||
dicBuilder.AppendLine("\n\t\tpublic static readonly Dictionary<string, int> SceneDic = new Dictionary<string, int>()\n\t\t{");
|
||||
// 生成场景类型的静态类
|
||||
strBuilder.AppendLine("\tpublic static class SceneType\n\t{");
|
||||
dicBuilder.AppendLine("\n\t\tpublic static readonly Dictionary<string, int> SceneTypeDic = new Dictionary<string, int>()\n\t\t{");
|
||||
|
||||
foreach (var str in sceneTypes)
|
||||
// 遍历场景类型字典,生成场景类型的常量和字典项
|
||||
foreach (var (sceneTypeId, sceneTypeStr) in sceneTypes)
|
||||
{
|
||||
index++;
|
||||
dicBuilder.AppendLine($"\t\t\t{{ \"{str}\", {index} }},");
|
||||
strBuilder.AppendLine($"\t\tpublic const int {str} = {index};");
|
||||
dicBuilder.AppendLine($"\t\t\t{{ \"{sceneTypeStr}\", {sceneTypeId} }},");
|
||||
strBuilder.AppendLine($"\t\tpublic const int {sceneTypeStr} = {sceneTypeId};");
|
||||
}
|
||||
|
||||
// 添加场景类型字典尾部,合并到主字符串构建器中
|
||||
dicBuilder.AppendLine("\t\t};");
|
||||
strBuilder.Append(dicBuilder);
|
||||
strBuilder.AppendLine("\t}\n");
|
||||
|
||||
// 生成场景子类型的静态类
|
||||
strBuilder.AppendLine("\t// 生成器自动生成,请不要手动编辑。");
|
||||
strBuilder.AppendLine("\tpublic static class SceneSubType\n\t{");
|
||||
// 清空字典构建器,用于生成场景子类型的字典项
|
||||
dicBuilder.Clear();
|
||||
dicBuilder.AppendLine("\n\t\tpublic static readonly Dictionary<string, int> SceneSubTypeDic = new Dictionary<string, int>()\n\t\t{");
|
||||
// 遍历场景子类型字典,生成场景子类型的常量和字典项
|
||||
foreach (var (sceneSubTypeId, sceneSubTypeStr) in sceneSubType)
|
||||
{
|
||||
dicBuilder.AppendLine($"\t\t\t{{ \"{sceneSubTypeStr}\", {sceneSubTypeId} }},");
|
||||
strBuilder.AppendLine($"\t\tpublic const int {sceneSubTypeStr} = {sceneSubTypeId};");
|
||||
}
|
||||
|
||||
// 添加场景子类型字典尾部,合并到主字符串构建器中
|
||||
dicBuilder.AppendLine("\t\t};");
|
||||
strBuilder.Append(dicBuilder);
|
||||
strBuilder.AppendLine("\t}\n}");
|
||||
|
||||
// 调用外部方法将生成的代码写入文件
|
||||
Write("SceneType.cs", strBuilder.ToString(), customExportType);
|
||||
}
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@ namespace TEngine
|
||||
public const int Addressable = 2;
|
||||
public const int Map = 3;
|
||||
public const int Chat = 4;
|
||||
public const int Center = 5;
|
||||
|
||||
public static readonly Dictionary<string, int> SceneTypeDic = new Dictionary<string, int>()
|
||||
{
|
||||
@@ -14,6 +15,7 @@ namespace TEngine
|
||||
{ "Addressable", 2 },
|
||||
{ "Map", 3 },
|
||||
{ "Chat", 4 },
|
||||
{ "Center", 5 },
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -1,10 +0,0 @@
|
||||
set GEN_CLIENT=dotnet ..\Tools\Luban.ClientServer\Luban.ClientServer.dll
|
||||
|
||||
%GEN_CLIENT% -j cfg --^
|
||||
-d Defines\__root__.xml ^
|
||||
--input_data_dir Datas ^
|
||||
--output_data_dir output_json ^
|
||||
--output_code_dir Gen ^
|
||||
--gen_types code_cs_unity_json,data_json ^
|
||||
-s all
|
||||
pause
|
@@ -1,10 +0,0 @@
|
||||
#!/bin/zsh
|
||||
GEN_CLIENT=../Tools/Luban.ClientServer/Luban.ClientServer.dll
|
||||
|
||||
dotnet ${GEN_CLIENT} -j cfg --\
|
||||
-d Defines/__root__.xml \
|
||||
--input_data_dir Datas \
|
||||
--output_data_dir output_json \
|
||||
--output_code_dir Gen \
|
||||
--gen_types code_cs_unity_json,data_json \
|
||||
-s all
|
Reference in New Issue
Block a user