mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
TEngine Commit 1.0.0
TEngine Commit 1.0.0
This commit is contained in:
8
Assets/TEngine/Runtime/3rd.meta
Normal file
8
Assets/TEngine/Runtime/3rd.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 99bd65c4be7ea5b46a417cdbed6b9064
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/TEngine/Runtime/3rd/JsonDotNet.meta
Normal file
8
Assets/TEngine/Runtime/3rd/JsonDotNet.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 377e07ca9e18e8b408a9f2b22030fe32
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
9
Assets/TEngine/Runtime/3rd/JsonDotNet/Assemblies.meta
Normal file
9
Assets/TEngine/Runtime/3rd/JsonDotNet/Assemblies.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 577d9725f58264943855b8ac185531fe
|
||||
folderAsset: yes
|
||||
timeCreated: 1466788344
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14f21d7a1e53a8c4e87b25526a7eb63c
|
||||
folderAsset: yes
|
||||
timeCreated: 1466788345
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aadad8ac54f29e44583510294ac5c312
|
||||
timeCreated: 1466788355
|
||||
licenseType: Store
|
||||
TextScriptImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
@@ -0,0 +1,76 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a3c684705042f345975d924f6983e36
|
||||
timeCreated: 1466788352
|
||||
licenseType: Store
|
||||
PluginImporter:
|
||||
serializedVersion: 1
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
isPreloaded: 0
|
||||
platformData:
|
||||
Android:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
Any:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
Editor:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
Linux:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86
|
||||
Linux64:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86_64
|
||||
OSXIntel:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
OSXIntel64:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
SamsungTV:
|
||||
enabled: 1
|
||||
settings:
|
||||
STV_MODEL: STANDARD_13
|
||||
Tizen:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
WebGL:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
Win:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
Win64:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
WindowsStoreApps:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DontProcess: False
|
||||
PlaceholderPath: Assets/JsonDotNet/Assemblies/Standalone/Newtonsoft.Json.dll
|
||||
SDK: AnySDK
|
||||
ScriptingBackend: Il2Cpp
|
||||
iOS:
|
||||
enabled: 1
|
||||
settings:
|
||||
CompileFlags:
|
||||
FrameworkDependencies:
|
||||
tvOS:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01ef782d02bb1994dbe418b69432552b
|
||||
folderAsset: yes
|
||||
timeCreated: 1466788344
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d6807fedb8dcaf04682d2c84f0ab753f
|
||||
timeCreated: 1466788355
|
||||
licenseType: Store
|
||||
TextScriptImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
@@ -0,0 +1,75 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 17aef65a15b471f468b5fbeb4ff0c6a1
|
||||
timeCreated: 1466788349
|
||||
licenseType: Store
|
||||
PluginImporter:
|
||||
serializedVersion: 1
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
isPreloaded: 0
|
||||
platformData:
|
||||
Android:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
Any:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
Editor:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
Linux:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: x86
|
||||
Linux64:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: x86_64
|
||||
LinuxUniversal:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
OSXIntel:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
OSXIntel64:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
OSXUniversal:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
SamsungTV:
|
||||
enabled: 0
|
||||
settings:
|
||||
STV_MODEL: STANDARD_13
|
||||
Win:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
Win64:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
WindowsStoreApps:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DontProcess: False
|
||||
PlaceholderPath:
|
||||
SDK: AnySDK
|
||||
ScriptingBackend: Il2Cpp
|
||||
iOS:
|
||||
enabled: 0
|
||||
settings:
|
||||
CompileFlags:
|
||||
FrameworkDependencies:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1418141139a6ac443b18cb05c0643a29
|
||||
folderAsset: yes
|
||||
timeCreated: 1466788345
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36f7323c55864364d8bb88c736e4bca6
|
||||
timeCreated: 1466788355
|
||||
licenseType: Store
|
||||
TextScriptImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
@@ -0,0 +1,67 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b6ba260dada0ea4a871a42011f8b87d
|
||||
timeCreated: 1466788355
|
||||
licenseType: Store
|
||||
PluginImporter:
|
||||
serializedVersion: 1
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
isPreloaded: 0
|
||||
platformData:
|
||||
Android:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
Any:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
Editor:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
Linux:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86
|
||||
Linux64:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86_64
|
||||
OSXIntel:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
OSXIntel64:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
SamsungTV:
|
||||
enabled: 0
|
||||
settings:
|
||||
STV_MODEL: STANDARD_13
|
||||
Win:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
Win64:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
WindowsStoreApps:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DontProcess: False
|
||||
PlaceholderPath: Assets/JsonDotNet/Assemblies/Standalone/Newtonsoft.Json.dll
|
||||
SDK: AnySDK
|
||||
ScriptingBackend: DotNet
|
||||
iOS:
|
||||
enabled: 0
|
||||
settings:
|
||||
CompileFlags:
|
||||
FrameworkDependencies:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
7
Assets/TEngine/Runtime/3rd/JsonDotNet/link.xml
Normal file
7
Assets/TEngine/Runtime/3rd/JsonDotNet/link.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<linker>
|
||||
<assembly fullname="System">
|
||||
<type fullname="System.ComponentModel.TypeConverter" preserve="all" />
|
||||
<!-- <namespace fullname="System.ComponentModel" preserve="all" /> -->
|
||||
</assembly>
|
||||
</linker>
|
6
Assets/TEngine/Runtime/3rd/JsonDotNet/link.xml.meta
Normal file
6
Assets/TEngine/Runtime/3rd/JsonDotNet/link.xml.meta
Normal file
@@ -0,0 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 06314f49bdda26043963578d60a0a7ee
|
||||
TextScriptImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/TEngine/Runtime/3rd/protobuf-net.meta
Normal file
8
Assets/TEngine/Runtime/3rd/protobuf-net.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 83007d75ac9798343a7c69bae15e6ce3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
BIN
Assets/TEngine/Runtime/3rd/protobuf-net/protobuf-net.dll
Normal file
BIN
Assets/TEngine/Runtime/3rd/protobuf-net/protobuf-net.dll
Normal file
Binary file not shown.
@@ -0,0 +1,33 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa22137905c778947a383e10c3a9e800
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 1
|
||||
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:
|
8
Assets/TEngine/Runtime/ClientSaveData.meta
Normal file
8
Assets/TEngine/Runtime/ClientSaveData.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2f6ee4c168f3e364ab85faf457f75038
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
130
Assets/TEngine/Runtime/ClientSaveData/ClientSaveData.cs
Normal file
130
Assets/TEngine/Runtime/ClientSaveData/ClientSaveData.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
using System.Collections.Generic;
|
||||
using LitJson;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public abstract class BaseClientData
|
||||
{
|
||||
private string m_configName;
|
||||
|
||||
public void Init(string configName)
|
||||
{
|
||||
m_configName = configName;
|
||||
Load();
|
||||
}
|
||||
|
||||
public void Load()
|
||||
{
|
||||
string fullName = GetSaveUniqPrefix() + m_configName;
|
||||
var jsonString = PlayerPrefs.GetString(fullName);
|
||||
if (!string.IsNullOrEmpty(jsonString))
|
||||
{
|
||||
JsonData json = JsonHelper.Instance.Deserialize(jsonString);
|
||||
if (json != null)
|
||||
{
|
||||
Deserialize(json);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
string fullName = GetSaveUniqPrefix() + m_configName;
|
||||
JsonData jsonData = new JsonData();
|
||||
Serialize(jsonData);
|
||||
|
||||
var jsonTex = JsonHelper.Instance.Serialize(jsonData);
|
||||
if (!string.IsNullOrEmpty(jsonTex))
|
||||
{
|
||||
PlayerPrefs.SetString(fullName, jsonTex);
|
||||
PlayerPrefs.Save();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void Serialize(JsonData json);
|
||||
|
||||
protected abstract void Deserialize(JsonData json);
|
||||
|
||||
private string GetSaveUniqPrefix()
|
||||
{
|
||||
string hashPath = UnityUtil.GetHashCodeByString(Application.dataPath).ToString();
|
||||
string uniqInstance = SystemInfo.deviceUniqueIdentifier;
|
||||
string uniqKey = hashPath + uniqInstance;
|
||||
return uniqKey;
|
||||
}
|
||||
}
|
||||
|
||||
public class SystemSaveData: BaseClientData
|
||||
{
|
||||
public int[] settingParams;
|
||||
public uint test;
|
||||
public float m_cameraDistance;
|
||||
|
||||
public SystemSaveData()
|
||||
{
|
||||
settingParams = new int[(int)SystemSaveType.Max];
|
||||
settingParams[(int) SystemSaveType.Lod] = 0;
|
||||
}
|
||||
|
||||
public enum SystemSaveType
|
||||
{
|
||||
Lod, // 同屏人数
|
||||
MusicOn, // 打开音乐
|
||||
SoundOn, // 打开音效
|
||||
Max,
|
||||
}
|
||||
|
||||
protected override void Serialize(JsonData json)
|
||||
{
|
||||
if (json == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void Deserialize(JsonData json)
|
||||
{
|
||||
if (json == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ClientSaveData : TSingleton<ClientSaveData>
|
||||
{
|
||||
private Dictionary<string, BaseClientData> m_dictSaveData = new Dictionary<string, BaseClientData>();
|
||||
|
||||
public T GetSaveData<T>() where T : BaseClientData, new()
|
||||
{
|
||||
string typeName = typeof(T).Name;
|
||||
BaseClientData ret;
|
||||
if (!m_dictSaveData.TryGetValue(typeName, out ret))
|
||||
{
|
||||
ret = new T();
|
||||
ret.Init(typeName);
|
||||
m_dictSaveData.Add(typeName, ret);
|
||||
}
|
||||
return (T)ret;
|
||||
}
|
||||
|
||||
public void SaveAllData()
|
||||
{
|
||||
var enumerator = m_dictSaveData.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
enumerator.Current.Value.Save();
|
||||
}
|
||||
}
|
||||
|
||||
public SystemSaveData CurrentSystemSaveData
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetSaveData<SystemSaveData>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ClientSaveData/ClientSaveData.cs.meta
Normal file
11
Assets/TEngine/Runtime/ClientSaveData/ClientSaveData.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19999af1b542c4040bea4b45f95d1807
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/TEngine/Runtime/Config.meta
Normal file
8
Assets/TEngine/Runtime/Config.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ba7cabbe2806af4689ed667c89bb7ab
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
117
Assets/TEngine/Runtime/Config/ResConfigUtil.cs
Normal file
117
Assets/TEngine/Runtime/Config/ResConfigUtil.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public class ResConfigUtil
|
||||
{
|
||||
private static StringBuilder m_strBuilder = new StringBuilder();
|
||||
private static readonly string m_split = "_";
|
||||
|
||||
#region 读取接口
|
||||
public static List<T> ReadConfigListRes<T>(string fileName)
|
||||
{
|
||||
string resPath = string.Format("Config/{0}.json",fileName);
|
||||
TextAsset jsonStr = TResources.Load<TextAsset>(resPath);
|
||||
if (jsonStr == null)
|
||||
{
|
||||
TLogger.LogError("读取Json配置数据失败:{0}", fileName);
|
||||
return null;
|
||||
}
|
||||
|
||||
List<T> list = new List<T>();
|
||||
var jsonData = JsonHelper.Instance.Deserialize<List<T>>(jsonStr.text);
|
||||
list = jsonData;
|
||||
return list;
|
||||
}
|
||||
|
||||
public static Dictionary<string, T> ReadConfigRes<T>(string fileName)
|
||||
{
|
||||
string resPath = string.Format("Config/{0}.json", fileName);
|
||||
TextAsset jsonStr = TResources.Load<TextAsset>(resPath);
|
||||
if (jsonStr == null)
|
||||
{
|
||||
TLogger.LogError("读取Json配置数据失败:{0}", fileName);
|
||||
return null;
|
||||
}
|
||||
|
||||
Dictionary<string, T> dic = new Dictionary<string, T>();
|
||||
var jsonData = JsonHelper.Instance.Deserialize<Dictionary<string, T>>(jsonStr.text);
|
||||
dic = jsonData;
|
||||
return dic;
|
||||
}
|
||||
|
||||
public static Dictionary<int, T> ReadConfigResIntKey<T>(string fileName)
|
||||
{
|
||||
string resPath = string.Format("Config/{0}.json", fileName);
|
||||
TextAsset jsonStr = TResources.Load<TextAsset>(resPath);
|
||||
if (jsonStr == null)
|
||||
{
|
||||
TLogger.LogError("读取Json配置数据失败:{0}", fileName);
|
||||
return null;
|
||||
}
|
||||
|
||||
Dictionary<int, T> dic = new Dictionary<int, T>();
|
||||
var jsonData = JsonHelper.Instance.Deserialize<Dictionary<int, T>>(jsonStr.text);
|
||||
dic = jsonData;
|
||||
return dic;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static UInt64 Make64Key(uint key1, uint key2)
|
||||
{
|
||||
return (((UInt64)key1) << 32) | key2;
|
||||
}
|
||||
|
||||
public static string MakeStringKey(uint key1, uint key2, uint key3)
|
||||
{
|
||||
m_strBuilder.Length = 0;
|
||||
m_strBuilder.Append(key1);
|
||||
m_strBuilder.Append(m_split);
|
||||
m_strBuilder.Append(key2);
|
||||
m_strBuilder.Append(m_split);
|
||||
m_strBuilder.Append(key3);
|
||||
return m_strBuilder.ToString();
|
||||
}
|
||||
|
||||
public static string MakeStringKey(string key1, uint key2)
|
||||
{
|
||||
m_strBuilder.Length = 0;
|
||||
m_strBuilder.Append(key1);
|
||||
m_strBuilder.Append(m_split);
|
||||
m_strBuilder.Append(key2);
|
||||
return m_strBuilder.ToString();
|
||||
}
|
||||
|
||||
public static string MakeStringKey(string key1, string key2)
|
||||
{
|
||||
m_strBuilder.Length = 0;
|
||||
m_strBuilder.Append(key1);
|
||||
m_strBuilder.Append(m_split);
|
||||
m_strBuilder.Append(key2);
|
||||
return m_strBuilder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
*
|
||||
===》 example 《===
|
||||
public class BufferMgr : Singleton<BufferMgr>
|
||||
{
|
||||
private Dictionary<string, BuffConfig> m_dictBaseConfig = new Dictionary<string, BuffConfig>();
|
||||
|
||||
public BufferMgr()
|
||||
{
|
||||
m_dictBaseConfig = ResConfigUtil.ReadConfigRes<BuffConfig>("BuffConfig");
|
||||
}
|
||||
|
||||
public Dictionary<string, BuffConfig> GetBuffConfig()
|
||||
{
|
||||
return m_dictBaseConfig;
|
||||
}
|
||||
}
|
||||
*
|
||||
*/
|
11
Assets/TEngine/Runtime/Config/ResConfigUtil.cs.meta
Normal file
11
Assets/TEngine/Runtime/Config/ResConfigUtil.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 47732fcfbdbefb94e9922877e93e81ae
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/TEngine/Runtime/Core.meta
Normal file
8
Assets/TEngine/Runtime/Core.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7a14c1ddd696e74abc1460f63bf580c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
74
Assets/TEngine/Runtime/Core/BaseLogicSys.cs
Normal file
74
Assets/TEngine/Runtime/Core/BaseLogicSys.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 基础LogicSys,生命周期由TEngine实现,推荐给系统实现,
|
||||
/// 减少多余的Mono,保持系统层面只有一个Update
|
||||
/// 用TEngine的主Mono来驱动LogicSys的生命周期
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class BaseLogicSys<T> : ILogicSys where T : new()
|
||||
{
|
||||
private static T m_Instance;
|
||||
|
||||
public static bool HasInstance
|
||||
{
|
||||
get { return m_Instance != null; }
|
||||
}
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == m_Instance)
|
||||
{
|
||||
m_Instance = new T();
|
||||
}
|
||||
|
||||
return m_Instance;
|
||||
}
|
||||
}
|
||||
|
||||
#region virtual fucntion
|
||||
public virtual bool OnInit()
|
||||
{
|
||||
if (null == m_Instance)
|
||||
{
|
||||
m_Instance = new T();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual void OnStart()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnUpdate()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnLateUpdate()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnPause()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnResume()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnDrawGizmos()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnMapChanged()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
11
Assets/TEngine/Runtime/Core/BaseLogicSys.cs.meta
Normal file
11
Assets/TEngine/Runtime/Core/BaseLogicSys.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 13e1df50dc89375458f8e0e646cf3e0b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
20
Assets/TEngine/Runtime/Core/ILogicSys.cs
Normal file
20
Assets/TEngine/Runtime/Core/ILogicSys.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace TEngine
|
||||
{
|
||||
public interface ILogicSys
|
||||
{
|
||||
bool OnInit();
|
||||
|
||||
void OnDestroy();
|
||||
|
||||
void OnStart();
|
||||
|
||||
void OnUpdate();
|
||||
|
||||
void OnLateUpdate();
|
||||
|
||||
void OnPause();
|
||||
|
||||
void OnResume();
|
||||
}
|
||||
|
||||
}
|
11
Assets/TEngine/Runtime/Core/ILogicSys.cs.meta
Normal file
11
Assets/TEngine/Runtime/Core/ILogicSys.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 076f0bb54d9835e45907ce6ea3147e72
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
90
Assets/TEngine/Runtime/Core/ListPool.cs
Normal file
90
Assets/TEngine/Runtime/Core/ListPool.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public static class ListPool<T>
|
||||
{
|
||||
private static readonly ObjectPool<List<T>> m_ListPool = new ObjectPool<List<T>>(null, Clear);
|
||||
|
||||
static void Clear(List<T> list)
|
||||
{
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
public static List<T> Get()
|
||||
{
|
||||
return m_ListPool.Get();
|
||||
}
|
||||
|
||||
public static void Release(List<T> toRelease)
|
||||
{
|
||||
m_ListPool.Release(toRelease);
|
||||
}
|
||||
}
|
||||
|
||||
public class ObjectPool<T> where T : new()
|
||||
{
|
||||
private readonly Stack<T> m_Stack = new Stack<T>();
|
||||
private readonly UnityAction<T> m_ActionGet;
|
||||
private readonly UnityAction<T> m_ActionRelease;
|
||||
|
||||
public int CountAll { get; private set; }
|
||||
public int CountActive
|
||||
{
|
||||
get
|
||||
{
|
||||
return CountAll - CountInActive;
|
||||
}
|
||||
}
|
||||
|
||||
public int CountInActive
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Stack.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public ObjectPool()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ObjectPool(UnityAction<T> actionGet, UnityAction<T> actionRelease)
|
||||
{
|
||||
m_ActionGet = actionGet;
|
||||
m_ActionRelease = actionRelease;
|
||||
}
|
||||
|
||||
public T Get()
|
||||
{
|
||||
T element;
|
||||
if (m_Stack.Count <= 0)
|
||||
{
|
||||
element = new T();
|
||||
CountAll++;
|
||||
}
|
||||
else
|
||||
{
|
||||
element = m_Stack.Pop();
|
||||
}
|
||||
|
||||
if (m_ActionGet != null)
|
||||
{
|
||||
m_ActionGet.Invoke(element);
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
public void Release(T element)
|
||||
{
|
||||
if (m_Stack.Count > 0 && ReferenceEquals(m_Stack.Peek(), element))
|
||||
{
|
||||
TLogger.LogError("Internal error. Trying to destroy object that is already released to pool.");
|
||||
}
|
||||
m_ActionRelease?.Invoke(element);
|
||||
m_Stack.Push(element);
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/Core/ListPool.cs.meta
Normal file
11
Assets/TEngine/Runtime/Core/ListPool.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce3d838c8607a1442acaee8b2ff1b7af
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
125
Assets/TEngine/Runtime/Core/MemPoolMgr.cs
Normal file
125
Assets/TEngine/Runtime/Core/MemPoolMgr.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Debug = UnityEngine.Debug;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public interface IMemPoolObject
|
||||
{
|
||||
void Init();
|
||||
void Destroy();
|
||||
}
|
||||
|
||||
public interface MemPoolBase
|
||||
{
|
||||
string GetName();
|
||||
int GetPoolItemCount();
|
||||
void ClearPool();
|
||||
}
|
||||
|
||||
public class MemPool
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class MemPoolMgr : TSingleton<MemPoolMgr>
|
||||
{
|
||||
List<MemPoolBase> m_listPool = new List<MemPoolBase>();
|
||||
|
||||
[Conditional("TEngine_DEBUG")]
|
||||
public void ShowCount()
|
||||
{
|
||||
int totalCnt = 0;
|
||||
for (int i = 0; i < m_listPool.Count; i++)
|
||||
{
|
||||
var pool = m_listPool[i];
|
||||
totalCnt += pool.GetPoolItemCount();
|
||||
TLogger.LogInfo("[pool][{0}] [{1}]", pool.GetName(), pool.GetPoolItemCount());
|
||||
}
|
||||
TLogger.LogInfo("-------------------------memory pool count: {0}", totalCnt);
|
||||
}
|
||||
|
||||
public void RegMemPool(MemPoolBase pool)
|
||||
{
|
||||
m_listPool.Add(pool);
|
||||
}
|
||||
|
||||
public void ClearAllPool()
|
||||
{
|
||||
for (int i = 0; i < m_listPool.Count; i++)
|
||||
{
|
||||
var pool = m_listPool[i];
|
||||
pool.ClearPool();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class GameMemPool<T> : TSingleton<GameMemPool<T>>, MemPoolBase where T : IMemPoolObject, new()
|
||||
{
|
||||
private List<T> m_objPool = new List<T>();
|
||||
|
||||
public static T Alloc()
|
||||
{
|
||||
return GameMemPool<T>.Instance.DoAlloc();
|
||||
}
|
||||
|
||||
public static void Free(T obj)
|
||||
{
|
||||
GameMemPool<T>.Instance.DoFree(obj);
|
||||
}
|
||||
|
||||
public GameMemPool()
|
||||
{
|
||||
MemPoolMgr.Instance.RegMemPool(this);
|
||||
}
|
||||
|
||||
private T DoAlloc()
|
||||
{
|
||||
T newObj;
|
||||
if (m_objPool.Count > 0)
|
||||
{
|
||||
var lastIndex = m_objPool.Count - 1;
|
||||
newObj = m_objPool[lastIndex];
|
||||
m_objPool.RemoveAt(lastIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
newObj = new T();
|
||||
}
|
||||
|
||||
newObj.Init();
|
||||
return newObj;
|
||||
}
|
||||
|
||||
private void DoFree(T obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
obj.Destroy();
|
||||
m_objPool.Add(obj);
|
||||
}
|
||||
|
||||
public void ClearPool()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
TLogger.LogInfo("clear memory[{0}] count[{1}]", GetName(), m_objPool.Count);
|
||||
#endif
|
||||
m_objPool.Clear();
|
||||
}
|
||||
|
||||
public string GetName()
|
||||
{
|
||||
return typeof(T).FullName;
|
||||
}
|
||||
|
||||
public int GetPoolItemCount()
|
||||
{
|
||||
return m_objPool.Count;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
11
Assets/TEngine/Runtime/Core/MemPoolMgr.cs.meta
Normal file
11
Assets/TEngine/Runtime/Core/MemPoolMgr.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 538182f774d67f0449e479ce28993300
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
28
Assets/TEngine/Runtime/Core/Singleton.cs
Normal file
28
Assets/TEngine/Runtime/Core/Singleton.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 通用单例,无需释放和销毁
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class Singleton<T> where T : new()
|
||||
{
|
||||
private static T _instance;
|
||||
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new T();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public static T Active()
|
||||
{
|
||||
return Instance;
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/Core/Singleton.cs.meta
Normal file
11
Assets/TEngine/Runtime/Core/Singleton.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80e398d58b294df4596e470547c69b01
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
149
Assets/TEngine/Runtime/Core/TEngine.cs
Normal file
149
Assets/TEngine/Runtime/Core/TEngine.cs
Normal file
@@ -0,0 +1,149 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 游戏入口,派生TEngine,实现进入游戏虚函数(override StartGame)
|
||||
/// </summary>
|
||||
public class TEngine : UnitySingleton<TEngine>
|
||||
{
|
||||
public override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
TLogger.LogInfo($"DevicePerformanceLevel 设备性能评级:{DevicePerformanceUtil.GetDevicePerformanceLevel()}");
|
||||
|
||||
InitLibImp();
|
||||
|
||||
RegisterAllSystem();
|
||||
|
||||
AfterAwake();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册实现库
|
||||
/// </summary>
|
||||
protected virtual void InitLibImp()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册系统(例如BaseLogic/TEngineObject/MonoManger)
|
||||
/// </summary>
|
||||
protected virtual void RegisterAllSystem()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected void SetTargetFrameRate(int targetFrameRate)
|
||||
{
|
||||
Application.targetFrameRate = targetFrameRate;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------系统注册--------------------------------------------------------//
|
||||
private List<ILogicSys> m_LogicMgrList = new List<ILogicSys>();
|
||||
|
||||
/// <summary>
|
||||
/// 系统注册
|
||||
/// </summary>
|
||||
/// <param name="logicSys"></param>
|
||||
/// <returns></returns>
|
||||
protected bool AddLogicSys(ILogicSys logicSys)
|
||||
{
|
||||
if (m_LogicMgrList.Contains(logicSys))
|
||||
{
|
||||
TLogger.LogInfo("Repeat add logic system: " + logicSys.GetType().Name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!logicSys.OnInit())
|
||||
{
|
||||
TLogger.LogInfo(" Init failed " + logicSys.GetType().Name);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_LogicMgrList.Add(logicSys);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#region 生命周期
|
||||
public void Start()
|
||||
{
|
||||
var listLogic = m_LogicMgrList;
|
||||
var logicCnt = listLogic.Count;
|
||||
for (int i = 0; i < logicCnt; i++)
|
||||
{
|
||||
var logic = listLogic[i];
|
||||
logic.OnStart();
|
||||
}
|
||||
TLogger.LogInfo("TEngine:StartGame");
|
||||
StartGame();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
var listLogic = m_LogicMgrList;
|
||||
var logicCnt = listLogic.Count;
|
||||
for (int i = 0; i < logicCnt; i++)
|
||||
{
|
||||
var logic = listLogic[i];
|
||||
logic.OnUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
public void LateUpdate()
|
||||
{
|
||||
var listLogic = m_LogicMgrList;
|
||||
var logicCnt = listLogic.Count;
|
||||
for (int i = 0; i < logicCnt; i++)
|
||||
{
|
||||
var logic = listLogic[i];
|
||||
logic.OnLateUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPause()
|
||||
{
|
||||
for (int i = 0; i < m_LogicMgrList.Count; i++)
|
||||
{
|
||||
var logicSys = m_LogicMgrList[i];
|
||||
logicSys.OnPause();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnResume()
|
||||
{
|
||||
for (int i = 0; i < m_LogicMgrList.Count; i++)
|
||||
{
|
||||
var logicSys = m_LogicMgrList[i];
|
||||
logicSys.OnResume();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
for (int i = 0; i < m_LogicMgrList.Count; i++)
|
||||
{
|
||||
var logicSys = m_LogicMgrList[i];
|
||||
logicSys.OnDestroy();
|
||||
}
|
||||
base.OnDestroy();
|
||||
SingletonMgr.Release();
|
||||
}
|
||||
|
||||
protected virtual void AfterAwake()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected virtual void StartGame()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/Core/TEngine.cs.meta
Normal file
11
Assets/TEngine/Runtime/Core/TEngine.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eab97947b9db71a47b27c473727f40bb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
880
Assets/TEngine/Runtime/Core/TEngineRedux.cs
Normal file
880
Assets/TEngine/Runtime/Core/TEngineRedux.cs
Normal file
@@ -0,0 +1,880 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
#region Architecture
|
||||
|
||||
public interface IArchitecture
|
||||
{
|
||||
void RegisterSystem<T>(T system) where T : ISystem;
|
||||
|
||||
void RegisterModel<T>(T model) where T : IModel;
|
||||
|
||||
void RegisterUtility<T>(T utility) where T : IUtility;
|
||||
|
||||
T GetSystem<T>() where T : class, ISystem;
|
||||
|
||||
T GetModel<T>() where T : class, IModel;
|
||||
|
||||
T GetUtility<T>() where T : class, IUtility;
|
||||
|
||||
void SendCommand<T>() where T : ICommand, new();
|
||||
|
||||
void SendCommand<T>(T command) where T : ICommand;
|
||||
|
||||
TResult SendQuery<TResult>(IQuery<TResult> query);
|
||||
|
||||
void SendEvent<T>() where T : new();
|
||||
|
||||
void SendEvent<T>(T e);
|
||||
|
||||
IUnRegister RegisterEvent<T>(Action<T> onEvent);
|
||||
|
||||
void UnRegisterEvent<T>(Action<T> onEvent);
|
||||
}
|
||||
|
||||
public abstract class Architecture<T> : IArchitecture where T : Architecture<T>, new()
|
||||
{
|
||||
private bool _Inited = false;
|
||||
|
||||
private List<ISystem> _Systems = new List<ISystem>();
|
||||
|
||||
private List<IModel> _Models = new List<IModel>();
|
||||
|
||||
public static Action<T> OnRegisterPatch = architecture => { };
|
||||
|
||||
private static T _Architecture;
|
||||
|
||||
public static IArchitecture Interface
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_Architecture == null)
|
||||
{
|
||||
MakeSureArchitecture();
|
||||
}
|
||||
|
||||
return _Architecture;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void MakeSureArchitecture()
|
||||
{
|
||||
if (_Architecture == null)
|
||||
{
|
||||
_Architecture = new T();
|
||||
_Architecture.Init();
|
||||
|
||||
OnRegisterPatch?.Invoke(_Architecture);
|
||||
|
||||
foreach (var architectureModel in _Architecture._Models)
|
||||
{
|
||||
architectureModel.Init();
|
||||
}
|
||||
|
||||
_Architecture._Models.Clear();
|
||||
|
||||
foreach (var architectureSystem in _Architecture._Systems)
|
||||
{
|
||||
architectureSystem.Init();
|
||||
}
|
||||
|
||||
_Architecture._Systems.Clear();
|
||||
|
||||
_Architecture._Inited = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void Init();
|
||||
|
||||
private TEngineContainer mContainer = new TEngineContainer();
|
||||
|
||||
public void RegisterSystem<TSystem>(TSystem system) where TSystem : ISystem
|
||||
{
|
||||
system.SetArchitecture(this);
|
||||
mContainer.Register<TSystem>(system);
|
||||
|
||||
if (!_Inited)
|
||||
{
|
||||
_Systems.Add(system);
|
||||
}
|
||||
else
|
||||
{
|
||||
system.Init();
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterModel<TModel>(TModel model) where TModel : IModel
|
||||
{
|
||||
model.SetArchitecture(this);
|
||||
mContainer.Register<TModel>(model);
|
||||
|
||||
if (!_Inited)
|
||||
{
|
||||
_Models.Add(model);
|
||||
}
|
||||
else
|
||||
{
|
||||
model.Init();
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterUtility<TUtility>(TUtility utility) where TUtility : IUtility
|
||||
{
|
||||
mContainer.Register<TUtility>(utility);
|
||||
}
|
||||
|
||||
public TSystem GetSystem<TSystem>() where TSystem : class, ISystem
|
||||
{
|
||||
return mContainer.Get<TSystem>();
|
||||
}
|
||||
|
||||
public TModel GetModel<TModel>() where TModel : class, IModel
|
||||
{
|
||||
return mContainer.Get<TModel>();
|
||||
}
|
||||
|
||||
public TUtility GetUtility<TUtility>() where TUtility : class, IUtility
|
||||
{
|
||||
return mContainer.Get<TUtility>();
|
||||
}
|
||||
|
||||
public void SendCommand<TCommand>() where TCommand : ICommand, new()
|
||||
{
|
||||
var command = new TCommand();
|
||||
command.SetArchitecture(this);
|
||||
command.Execute();
|
||||
}
|
||||
|
||||
public void SendCommand<TCommand>(TCommand command) where TCommand : ICommand
|
||||
{
|
||||
command.SetArchitecture(this);
|
||||
command.Execute();
|
||||
}
|
||||
|
||||
public TResult SendQuery<TResult>(IQuery<TResult> query)
|
||||
{
|
||||
query.SetArchitecture(this);
|
||||
return query.Do();
|
||||
}
|
||||
|
||||
private TypeEventSystem mTypeEventSystem = new TypeEventSystem();
|
||||
|
||||
public void SendEvent<TEvent>() where TEvent : new()
|
||||
{
|
||||
mTypeEventSystem.Send<TEvent>();
|
||||
}
|
||||
|
||||
public void SendEvent<TEvent>(TEvent e)
|
||||
{
|
||||
mTypeEventSystem.Send<TEvent>(e);
|
||||
}
|
||||
|
||||
public IUnRegister RegisterEvent<TEvent>(Action<TEvent> onEvent)
|
||||
{
|
||||
return mTypeEventSystem.Register<TEvent>(onEvent);
|
||||
}
|
||||
|
||||
public void UnRegisterEvent<TEvent>(Action<TEvent> onEvent)
|
||||
{
|
||||
mTypeEventSystem.UnRegister<TEvent>(onEvent);
|
||||
}
|
||||
}
|
||||
|
||||
public interface IOnEvent<T>
|
||||
{
|
||||
void OnEvent(T e);
|
||||
}
|
||||
|
||||
public static class OnGlobalEventExtension
|
||||
{
|
||||
public static IUnRegister RegisterEvent<T>(this IOnEvent<T> self) where T : struct
|
||||
{
|
||||
return TypeEventSystem.Global.Register<T>(self.OnEvent);
|
||||
}
|
||||
|
||||
public static void UnRegisterEvent<T>(this IOnEvent<T> self) where T : struct
|
||||
{
|
||||
TypeEventSystem.Global.UnRegister<T>(self.OnEvent);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Controller
|
||||
|
||||
public interface IController : IBelongToArchitecture, ICanSendCommand, ICanGetSystem, ICanGetModel,
|
||||
ICanRegisterEvent, ICanSendQuery
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region System
|
||||
|
||||
public interface ISystem : IBelongToArchitecture, ICanSetArchitecture, ICanGetModel, ICanGetUtility,
|
||||
ICanRegisterEvent, ICanSendEvent, ICanGetSystem
|
||||
{
|
||||
void Init();
|
||||
}
|
||||
|
||||
public abstract class AbstractSystem : ISystem
|
||||
{
|
||||
private IArchitecture _Architecture;
|
||||
|
||||
IArchitecture IBelongToArchitecture.GetArchitecture()
|
||||
{
|
||||
return _Architecture;
|
||||
}
|
||||
|
||||
void ICanSetArchitecture.SetArchitecture(IArchitecture architecture)
|
||||
{
|
||||
_Architecture = architecture;
|
||||
}
|
||||
|
||||
void ISystem.Init()
|
||||
{
|
||||
OnInit();
|
||||
}
|
||||
|
||||
protected abstract void OnInit();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Model
|
||||
|
||||
public interface IModel : IBelongToArchitecture, ICanSetArchitecture, ICanGetUtility, ICanSendEvent
|
||||
{
|
||||
void Init();
|
||||
}
|
||||
|
||||
public abstract class AbstractModel : IModel
|
||||
{
|
||||
private IArchitecture _Architecturel;
|
||||
|
||||
IArchitecture IBelongToArchitecture.GetArchitecture()
|
||||
{
|
||||
return _Architecturel;
|
||||
}
|
||||
|
||||
void ICanSetArchitecture.SetArchitecture(IArchitecture architecture)
|
||||
{
|
||||
_Architecturel = architecture;
|
||||
}
|
||||
|
||||
void IModel.Init()
|
||||
{
|
||||
OnInit();
|
||||
}
|
||||
|
||||
protected abstract void OnInit();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Utility
|
||||
|
||||
public interface IUtility
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Command
|
||||
|
||||
public interface ICommand : IBelongToArchitecture, ICanSetArchitecture, ICanGetSystem, ICanGetModel, ICanGetUtility,
|
||||
ICanSendEvent, ICanSendCommand, ICanSendQuery
|
||||
{
|
||||
void Execute();
|
||||
}
|
||||
|
||||
public abstract class AbstractCommand : ICommand
|
||||
{
|
||||
private IArchitecture _Architecture;
|
||||
|
||||
IArchitecture IBelongToArchitecture.GetArchitecture()
|
||||
{
|
||||
return _Architecture;
|
||||
}
|
||||
|
||||
void ICanSetArchitecture.SetArchitecture(IArchitecture architecture)
|
||||
{
|
||||
_Architecture = architecture;
|
||||
}
|
||||
|
||||
void ICommand.Execute()
|
||||
{
|
||||
OnExecute();
|
||||
}
|
||||
|
||||
protected abstract void OnExecute();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Query
|
||||
|
||||
public interface IQuery<TResult> : IBelongToArchitecture, ICanSetArchitecture, ICanGetModel, ICanGetSystem,
|
||||
ICanSendQuery
|
||||
{
|
||||
TResult Do();
|
||||
}
|
||||
|
||||
public abstract class AbstractQuery<T> : IQuery<T>
|
||||
{
|
||||
public T Do()
|
||||
{
|
||||
return OnDo();
|
||||
}
|
||||
|
||||
protected abstract T OnDo();
|
||||
|
||||
|
||||
private IArchitecture _Architecture;
|
||||
|
||||
public IArchitecture GetArchitecture()
|
||||
{
|
||||
return _Architecture;
|
||||
}
|
||||
|
||||
public void SetArchitecture(IArchitecture architecture)
|
||||
{
|
||||
_Architecture = architecture;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rule
|
||||
|
||||
public interface IBelongToArchitecture
|
||||
{
|
||||
IArchitecture GetArchitecture();
|
||||
}
|
||||
|
||||
public interface ICanSetArchitecture
|
||||
{
|
||||
void SetArchitecture(IArchitecture architecture);
|
||||
}
|
||||
|
||||
public interface ICanGetModel : IBelongToArchitecture
|
||||
{
|
||||
}
|
||||
|
||||
public static class CanGetModelExtension
|
||||
{
|
||||
public static T GetModel<T>(this ICanGetModel self) where T : class, IModel
|
||||
{
|
||||
return self.GetArchitecture().GetModel<T>();
|
||||
}
|
||||
}
|
||||
|
||||
public interface ICanGetSystem : IBelongToArchitecture
|
||||
{
|
||||
}
|
||||
|
||||
public static class CanGetSystemExtension
|
||||
{
|
||||
public static T GetSystem<T>(this ICanGetSystem self) where T : class, ISystem
|
||||
{
|
||||
return self.GetArchitecture().GetSystem<T>();
|
||||
}
|
||||
}
|
||||
|
||||
public interface ICanGetUtility : IBelongToArchitecture
|
||||
{
|
||||
}
|
||||
|
||||
public static class CanGetUtilityExtension
|
||||
{
|
||||
public static T GetUtility<T>(this ICanGetUtility self) where T : class, IUtility
|
||||
{
|
||||
return self.GetArchitecture().GetUtility<T>();
|
||||
}
|
||||
}
|
||||
|
||||
public interface ICanRegisterEvent : IBelongToArchitecture
|
||||
{
|
||||
}
|
||||
|
||||
public static class CanRegisterEventExtension
|
||||
{
|
||||
public static IUnRegister RegisterEvent<T>(this ICanRegisterEvent self, Action<T> onEvent)
|
||||
{
|
||||
return self.GetArchitecture().RegisterEvent<T>(onEvent);
|
||||
}
|
||||
|
||||
public static void UnRegisterEvent<T>(this ICanRegisterEvent self, Action<T> onEvent)
|
||||
{
|
||||
self.GetArchitecture().UnRegisterEvent<T>(onEvent);
|
||||
}
|
||||
}
|
||||
|
||||
public interface ICanSendCommand : IBelongToArchitecture
|
||||
{
|
||||
}
|
||||
|
||||
public static class CanSendCommandExtension
|
||||
{
|
||||
public static void SendCommand<T>(this ICanSendCommand self) where T : ICommand, new()
|
||||
{
|
||||
self.GetArchitecture().SendCommand<T>();
|
||||
}
|
||||
|
||||
public static void SendCommand<T>(this ICanSendCommand self, T command) where T : ICommand
|
||||
{
|
||||
self.GetArchitecture().SendCommand<T>(command);
|
||||
}
|
||||
}
|
||||
|
||||
public interface ICanSendEvent : IBelongToArchitecture
|
||||
{
|
||||
}
|
||||
|
||||
public static class CanSendEventExtension
|
||||
{
|
||||
public static void SendEvent<T>(this ICanSendEvent self) where T : new()
|
||||
{
|
||||
self.GetArchitecture().SendEvent<T>();
|
||||
}
|
||||
|
||||
public static void SendEvent<T>(this ICanSendEvent self, T e)
|
||||
{
|
||||
self.GetArchitecture().SendEvent<T>(e);
|
||||
}
|
||||
}
|
||||
|
||||
public interface ICanSendQuery : IBelongToArchitecture
|
||||
{
|
||||
}
|
||||
|
||||
public static class CanSendQueryExtension
|
||||
{
|
||||
public static TResult SendQuery<TResult>(this ICanSendQuery self, IQuery<TResult> query)
|
||||
{
|
||||
return self.GetArchitecture().SendQuery(query);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region TypeEventSystem
|
||||
|
||||
public interface IUnRegister
|
||||
{
|
||||
void UnRegister();
|
||||
}
|
||||
|
||||
public interface IUnRegisterList
|
||||
{
|
||||
List<IUnRegister> UnregisterList { get; }
|
||||
}
|
||||
|
||||
public static class IUnRegisterListExtension
|
||||
{
|
||||
public static void AddToUnregisterList(this IUnRegister self, IUnRegisterList unRegisterList)
|
||||
{
|
||||
unRegisterList.UnregisterList.Add(self);
|
||||
}
|
||||
|
||||
public static void UnRegisterAll(this IUnRegisterList self)
|
||||
{
|
||||
foreach (var unRegister in self.UnregisterList)
|
||||
{
|
||||
unRegister.UnRegister();
|
||||
}
|
||||
|
||||
self.UnregisterList.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自定义可注销的类
|
||||
/// </summary>
|
||||
public struct CustomUnRegister : IUnRegister
|
||||
{
|
||||
/// <summary>
|
||||
/// 委托对象
|
||||
/// </summary>
|
||||
private Action mOnUnRegister { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 带参构造函数
|
||||
/// </summary>
|
||||
/// <param name="onDispose"></param>
|
||||
public CustomUnRegister(Action onUnRegsiter)
|
||||
{
|
||||
mOnUnRegister = onUnRegsiter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 资源释放
|
||||
/// </summary>
|
||||
public void UnRegister()
|
||||
{
|
||||
mOnUnRegister.Invoke();
|
||||
mOnUnRegister = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class UnRegisterOnDestroyTrigger : MonoBehaviour
|
||||
{
|
||||
private readonly HashSet<IUnRegister> mUnRegisters = new HashSet<IUnRegister>();
|
||||
|
||||
public void AddUnRegister(IUnRegister unRegister)
|
||||
{
|
||||
mUnRegisters.Add(unRegister);
|
||||
}
|
||||
|
||||
public void RemoveUnRegister(IUnRegister unRegister)
|
||||
{
|
||||
mUnRegisters.Remove(unRegister);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
foreach (var unRegister in mUnRegisters)
|
||||
{
|
||||
unRegister.UnRegister();
|
||||
}
|
||||
|
||||
mUnRegisters.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnRegisterExtension
|
||||
{
|
||||
public static IUnRegister UnRegisterWhenGameObjectDestroyed(this IUnRegister unRegister, GameObject gameObject)
|
||||
{
|
||||
var trigger = gameObject.GetComponent<UnRegisterOnDestroyTrigger>();
|
||||
|
||||
if (!trigger)
|
||||
{
|
||||
trigger = gameObject.AddComponent<UnRegisterOnDestroyTrigger>();
|
||||
}
|
||||
|
||||
trigger.AddUnRegister(unRegister);
|
||||
|
||||
return unRegister;
|
||||
}
|
||||
}
|
||||
|
||||
public class TypeEventSystem
|
||||
{
|
||||
private readonly EasyEvents mEvents = new EasyEvents();
|
||||
|
||||
|
||||
public static readonly TypeEventSystem Global = new TypeEventSystem();
|
||||
|
||||
public void Send<T>() where T : new()
|
||||
{
|
||||
mEvents.GetEvent<EasyEvent<T>>()?.Trigger(new T());
|
||||
}
|
||||
|
||||
public void Send<T>(T e)
|
||||
{
|
||||
mEvents.GetEvent<EasyEvent<T>>()?.Trigger(e);
|
||||
}
|
||||
|
||||
public IUnRegister Register<T>(Action<T> onEvent)
|
||||
{
|
||||
var e = mEvents.GetOrAddEvent<EasyEvent<T>>();
|
||||
return e.Register(onEvent);
|
||||
}
|
||||
|
||||
public void UnRegister<T>(Action<T> onEvent)
|
||||
{
|
||||
var e = mEvents.GetEvent<EasyEvent<T>>();
|
||||
if (e != null)
|
||||
{
|
||||
e.UnRegister(onEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region TEngine
|
||||
|
||||
public class TEngineContainer
|
||||
{
|
||||
private Dictionary<Type, object> _Instances = new Dictionary<Type, object>();
|
||||
|
||||
public void Register<T>(T instance)
|
||||
{
|
||||
var key = typeof(T);
|
||||
|
||||
if (_Instances.ContainsKey(key))
|
||||
{
|
||||
_Instances[key] = instance;
|
||||
}
|
||||
else
|
||||
{
|
||||
_Instances.Add(key, instance);
|
||||
}
|
||||
}
|
||||
|
||||
public T Get<T>() where T : class
|
||||
{
|
||||
var key = typeof(T);
|
||||
|
||||
if (_Instances.TryGetValue(key, out var retInstance))
|
||||
{
|
||||
return retInstance as T;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region BindableProperty
|
||||
|
||||
public interface IBindableProperty<T> : IReadonlyBindableProperty<T>
|
||||
{
|
||||
new T Value { get; set; }
|
||||
void SetValueWithoutEvent(T newValue);
|
||||
}
|
||||
|
||||
public interface IReadonlyBindableProperty<T>
|
||||
{
|
||||
T Value { get; }
|
||||
|
||||
IUnRegister RegisterWithInitValue(Action<T> action);
|
||||
void UnRegister(Action<T> onValueChanged);
|
||||
IUnRegister Register(Action<T> onValueChanged);
|
||||
}
|
||||
|
||||
public class BindableProperty<T> : IBindableProperty<T>
|
||||
{
|
||||
public BindableProperty(T defaultValue = default)
|
||||
{
|
||||
mValue = defaultValue;
|
||||
}
|
||||
|
||||
protected T mValue;
|
||||
|
||||
public T Value
|
||||
{
|
||||
get => GetValue();
|
||||
set
|
||||
{
|
||||
if (value == null && mValue == null) return;
|
||||
if (value != null && value.Equals(mValue)) return;
|
||||
|
||||
SetValue(value);
|
||||
mOnValueChanged?.Invoke(value);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void SetValue(T newValue)
|
||||
{
|
||||
mValue = newValue;
|
||||
}
|
||||
|
||||
protected virtual T GetValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
public void SetValueWithoutEvent(T newValue)
|
||||
{
|
||||
mValue = newValue;
|
||||
}
|
||||
|
||||
private Action<T> mOnValueChanged = (v) => { };
|
||||
|
||||
public IUnRegister Register(Action<T> onValueChanged)
|
||||
{
|
||||
mOnValueChanged += onValueChanged;
|
||||
return new BindablePropertyUnRegister<T>()
|
||||
{
|
||||
BindableProperty = this,
|
||||
OnValueChanged = onValueChanged
|
||||
};
|
||||
}
|
||||
|
||||
public IUnRegister RegisterWithInitValue(Action<T> onValueChanged)
|
||||
{
|
||||
onValueChanged(mValue);
|
||||
return Register(onValueChanged);
|
||||
}
|
||||
|
||||
public static implicit operator T(BindableProperty<T> property)
|
||||
{
|
||||
return property.Value;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
|
||||
public void UnRegister(Action<T> onValueChanged)
|
||||
{
|
||||
mOnValueChanged -= onValueChanged;
|
||||
}
|
||||
}
|
||||
|
||||
public class BindablePropertyUnRegister<T> : IUnRegister
|
||||
{
|
||||
public BindableProperty<T> BindableProperty { get; set; }
|
||||
|
||||
public Action<T> OnValueChanged { get; set; }
|
||||
|
||||
public void UnRegister()
|
||||
{
|
||||
BindableProperty.UnRegister(OnValueChanged);
|
||||
|
||||
BindableProperty = null;
|
||||
OnValueChanged = null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region EasyEvent
|
||||
|
||||
public interface IEasyEvent
|
||||
{
|
||||
}
|
||||
|
||||
public class EasyEvent : IEasyEvent
|
||||
{
|
||||
private Action mOnEvent = () => { };
|
||||
|
||||
public IUnRegister Register(Action onEvent)
|
||||
{
|
||||
mOnEvent += onEvent;
|
||||
return new CustomUnRegister(() => { UnRegister(onEvent); });
|
||||
}
|
||||
|
||||
public void UnRegister(Action onEvent)
|
||||
{
|
||||
mOnEvent -= onEvent;
|
||||
}
|
||||
|
||||
public void Trigger()
|
||||
{
|
||||
mOnEvent?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
public class EasyEvent<T> : IEasyEvent
|
||||
{
|
||||
private Action<T> mOnEvent = e => { };
|
||||
|
||||
public IUnRegister Register(Action<T> onEvent)
|
||||
{
|
||||
mOnEvent += onEvent;
|
||||
return new CustomUnRegister(() => { UnRegister(onEvent); });
|
||||
}
|
||||
|
||||
public void UnRegister(Action<T> onEvent)
|
||||
{
|
||||
mOnEvent -= onEvent;
|
||||
}
|
||||
|
||||
public void Trigger(T t)
|
||||
{
|
||||
mOnEvent?.Invoke(t);
|
||||
}
|
||||
}
|
||||
|
||||
public class EasyEvent<T, K> : IEasyEvent
|
||||
{
|
||||
private Action<T, K> mOnEvent = (t, k) => { };
|
||||
|
||||
public IUnRegister Register(Action<T, K> onEvent)
|
||||
{
|
||||
mOnEvent += onEvent;
|
||||
return new CustomUnRegister(() => { UnRegister(onEvent); });
|
||||
}
|
||||
|
||||
public void UnRegister(Action<T, K> onEvent)
|
||||
{
|
||||
mOnEvent -= onEvent;
|
||||
}
|
||||
|
||||
public void Trigger(T t, K k)
|
||||
{
|
||||
mOnEvent?.Invoke(t, k);
|
||||
}
|
||||
}
|
||||
|
||||
public class EasyEvent<T, K, S> : IEasyEvent
|
||||
{
|
||||
private Action<T, K, S> mOnEvent = (t, k, s) => { };
|
||||
|
||||
public IUnRegister Register(Action<T, K, S> onEvent)
|
||||
{
|
||||
mOnEvent += onEvent;
|
||||
return new CustomUnRegister(() => { UnRegister(onEvent); });
|
||||
}
|
||||
|
||||
public void UnRegister(Action<T, K, S> onEvent)
|
||||
{
|
||||
mOnEvent -= onEvent;
|
||||
}
|
||||
|
||||
public void Trigger(T t, K k, S s)
|
||||
{
|
||||
mOnEvent?.Invoke(t, k, s);
|
||||
}
|
||||
}
|
||||
|
||||
public class EasyEvents
|
||||
{
|
||||
private static EasyEvents mGlobalEvents = new EasyEvents();
|
||||
|
||||
public static T Get<T>() where T : IEasyEvent
|
||||
{
|
||||
return mGlobalEvents.GetEvent<T>();
|
||||
}
|
||||
|
||||
|
||||
public static void Register<T>() where T : IEasyEvent, new()
|
||||
{
|
||||
mGlobalEvents.AddEvent<T>();
|
||||
}
|
||||
|
||||
private Dictionary<Type, IEasyEvent> mTypeEvents = new Dictionary<Type, IEasyEvent>();
|
||||
|
||||
public void AddEvent<T>() where T : IEasyEvent, new()
|
||||
{
|
||||
mTypeEvents.Add(typeof(T), new T());
|
||||
}
|
||||
|
||||
public T GetEvent<T>() where T : IEasyEvent
|
||||
{
|
||||
IEasyEvent e;
|
||||
|
||||
if (mTypeEvents.TryGetValue(typeof(T), out e))
|
||||
{
|
||||
return (T)e;
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public T GetOrAddEvent<T>() where T : IEasyEvent, new()
|
||||
{
|
||||
var eType = typeof(T);
|
||||
if (mTypeEvents.TryGetValue(eType, out var e))
|
||||
{
|
||||
return (T)e;
|
||||
}
|
||||
|
||||
var t = new T();
|
||||
mTypeEvents.Add(eType, t);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
11
Assets/TEngine/Runtime/Core/TEngineRedux.cs.meta
Normal file
11
Assets/TEngine/Runtime/Core/TEngineRedux.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d6ac57b69a5ba014c86bb71d54e8c24d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
341
Assets/TEngine/Runtime/Core/TLogger.cs
Normal file
341
Assets/TEngine/Runtime/Core/TLogger.cs
Normal file
@@ -0,0 +1,341 @@
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using Debug = UnityEngine.Debug;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public static class ColorUtils
|
||||
{
|
||||
#region ColorStr
|
||||
|
||||
public const string White = "FFFFFF";
|
||||
public const string Black = "000000";
|
||||
public const string Red = "FF0000";
|
||||
public const string Green = "00FF18";
|
||||
public const string Oringe = "FF9400";
|
||||
public const string Exception = "FF00BD";
|
||||
#endregion
|
||||
|
||||
public static string ToColor(this string str, string color)
|
||||
{
|
||||
if (string.IsNullOrEmpty(str))
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
return string.Format("<color=#{0}>{1}</color>", color, str);
|
||||
}
|
||||
}
|
||||
|
||||
public class TLogger : TSingleton<TLogger>
|
||||
{
|
||||
protected override void Init()
|
||||
{
|
||||
_outputType = OutputType.EDITOR;
|
||||
_logToFile = new LogToFile();
|
||||
_logToFile.Init();
|
||||
UnityEngine.Application.logMessageReceivedThreaded += OnLogMessageReceivedThreaded;
|
||||
}
|
||||
|
||||
private LogToFile _logToFile;
|
||||
private void OnLogMessageReceivedThreaded(string condition, string stackTrace, LogType type)
|
||||
{
|
||||
if (!condition.StartsWith("TLogger]"))
|
||||
{
|
||||
_stringBuilder.Clear();
|
||||
|
||||
_stringBuilder.AppendFormat("[System][{0}][{1}] {2}", type.ToString(), System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), condition);
|
||||
|
||||
if (type == LogType.Warning || type == LogType.Error || type == LogType.Exception)
|
||||
{
|
||||
_stringBuilder.AppendLine(stackTrace);
|
||||
}
|
||||
|
||||
string strToWrite = _stringBuilder.ToString();
|
||||
|
||||
_logToFile.Write(strToWrite);
|
||||
}
|
||||
}
|
||||
|
||||
~TLogger()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void Release()
|
||||
{
|
||||
Application.logMessageReceivedThreaded -= OnLogMessageReceivedThreaded;
|
||||
_logToFile.DeInit();
|
||||
_logToFile = null;
|
||||
base.Release();
|
||||
}
|
||||
|
||||
|
||||
private void ChangeOutputChannel(OutputType type)
|
||||
{
|
||||
if (type != _outputType)
|
||||
{
|
||||
_outputType = type;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetFilterLevel(LogLevel filterLevel)
|
||||
{
|
||||
Instance._filterLevel = filterLevel;
|
||||
}
|
||||
|
||||
[Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_ASSERT")]
|
||||
public static void LogAssert(bool condition, string logStr)
|
||||
{
|
||||
if (!condition)
|
||||
Instance.Log(LogLevel.ASSERT, logStr);
|
||||
}
|
||||
|
||||
[Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_ASSERT")]
|
||||
public static void LogAssert(bool condition, string format, params System.Object[] args)
|
||||
{
|
||||
if (!condition)
|
||||
{
|
||||
string logStr = string.Format(format, args);
|
||||
Instance.Log(LogLevel.ASSERT, logStr);
|
||||
}
|
||||
}
|
||||
|
||||
[Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_INFO")]
|
||||
public static void LogInfo(string logStr)
|
||||
{
|
||||
Instance.Log(LogLevel.INFO, logStr);
|
||||
}
|
||||
|
||||
[Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_INFO")]
|
||||
public static void LogInfo(string format, params System.Object[] args)
|
||||
{
|
||||
string logStr = string.Format(format, args);
|
||||
Instance.Log(LogLevel.INFO, logStr);
|
||||
}
|
||||
|
||||
[Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_SUCCESS")]
|
||||
public static void LogInfoSuccessd(string logStr)
|
||||
{
|
||||
Instance.Log(LogLevel.Successd, logStr);
|
||||
}
|
||||
|
||||
[Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_SUCCESS")]
|
||||
public static void LogInfoSuccessd(string format, params System.Object[] args)
|
||||
{
|
||||
string logStr = string.Format(format, args);
|
||||
Instance.Log(LogLevel.Successd, logStr);
|
||||
}
|
||||
|
||||
[Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_WARNING")]
|
||||
public static void LogWarning(string logStr)
|
||||
{
|
||||
Instance.Log(LogLevel.WARNING, logStr);
|
||||
}
|
||||
|
||||
[Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_WARNING")]
|
||||
public static void LogWarning(string format, params System.Object[] args)
|
||||
{
|
||||
string logStr = string.Format(format, args);
|
||||
Instance.Log(LogLevel.WARNING, logStr);
|
||||
}
|
||||
|
||||
[Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_ERROR")]
|
||||
public static void LogError(string logStr)
|
||||
{
|
||||
Instance.Log(LogLevel.ERROR, logStr);
|
||||
}
|
||||
|
||||
[Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_ERROR")]
|
||||
public static void LogError(string format, params System.Object[] args)
|
||||
{
|
||||
string logStr = string.Format(format, args);
|
||||
Instance.Log(LogLevel.ERROR, logStr);
|
||||
}
|
||||
|
||||
[Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_EXCEPTION")]
|
||||
public static void LogException(string logStr)
|
||||
{
|
||||
Instance.Log(LogLevel.EXCEPTION, logStr);
|
||||
}
|
||||
|
||||
[Conditional("UNITY_EDITOR"), Conditional("_DEVELOPMENT_BUILD_"), Conditional("ENABLE_LOG_EXCEPTION")]
|
||||
public static void LogException(string format, params System.Object[] args)
|
||||
{
|
||||
string msg = string.Format(format, args);
|
||||
Instance.Log(LogLevel.EXCEPTION, msg);
|
||||
}
|
||||
|
||||
private StringBuilder GetFormatedString(LogLevel logLevel, string logString, bool bColor)
|
||||
{
|
||||
_stringBuilder.Clear();
|
||||
switch (logLevel)
|
||||
{
|
||||
case LogLevel.Successd:
|
||||
if (UseCustomColor)
|
||||
{
|
||||
_stringBuilder.AppendFormat("[TLogger][SUCCESSED][{0}] - <color=#{2}>{1}</color>",
|
||||
System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString, ColorUtils.Green);
|
||||
}
|
||||
else
|
||||
{
|
||||
_stringBuilder.AppendFormat(
|
||||
bColor ? "[TLogger][INFO][{0}] - <color=gray>{1}</color>" : "[TLogger][SUCCESSED][{0}] - {1}",
|
||||
System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString);
|
||||
}
|
||||
break;
|
||||
case LogLevel.INFO:
|
||||
if (UseCustomColor)
|
||||
{
|
||||
_stringBuilder.AppendFormat("[TLogger][INFO][{0}] - <color=#{2}>{1}</color>" ,
|
||||
System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString,ColorUtils.Black);
|
||||
}
|
||||
else
|
||||
{
|
||||
_stringBuilder.AppendFormat(
|
||||
bColor ? "[TLogger][INFO][{0}] - <color=gray>{1}</color>" : "[TLogger][INFO][{0}] - {1}",
|
||||
System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString);
|
||||
}
|
||||
break;
|
||||
case LogLevel.ASSERT:
|
||||
if (UseCustomColor)
|
||||
{
|
||||
_stringBuilder.AppendFormat("[TLogger][ASSERT][{0}] - <color=#{2}>{1}</color>",
|
||||
System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString,ColorUtils.Exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
_stringBuilder.AppendFormat(
|
||||
bColor ? "[TLogger][ASSERT][{0}] - <color=green>{1}</color>" : "[TLogger][ASSERT][{0}] - {1}",
|
||||
System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString);
|
||||
}
|
||||
break;
|
||||
case LogLevel.WARNING:
|
||||
if (UseCustomColor)
|
||||
{
|
||||
_stringBuilder.AppendFormat("[TLogger][WARNING][{0}] - <color=#{2}>{1}</color>",
|
||||
System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString, ColorUtils.Oringe);
|
||||
}
|
||||
else
|
||||
{
|
||||
_stringBuilder.AppendFormat(
|
||||
bColor
|
||||
? "[TLogger][WARNING][{0}] - <color=yellow>{1}</color>"
|
||||
: "[TLogger][WARNING][{0}] - {1}", System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"),
|
||||
logString);
|
||||
}
|
||||
break;
|
||||
case LogLevel.ERROR:
|
||||
if (UseCustomColor)
|
||||
{
|
||||
_stringBuilder.AppendFormat("[ERROR][WARNING][{0}] - <color=#{2}>{1}</color>",
|
||||
System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString, ColorUtils.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
_stringBuilder.AppendFormat(
|
||||
bColor ? "[TLogger][ERROR][{0}] - <color=red>{1}</color>" : "[TLogger][ERROR][{0}] - {1}",
|
||||
System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString);
|
||||
}
|
||||
break;
|
||||
case LogLevel.EXCEPTION:
|
||||
if (UseCustomColor)
|
||||
{
|
||||
_stringBuilder.AppendFormat("[ERROR][EXCEPTION][{0}] - <color=#{2}>{1}</color>",
|
||||
System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString, ColorUtils.Exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
_stringBuilder.AppendFormat(
|
||||
bColor
|
||||
? "[TLogger][EXCEPTION][{0}] - <color=red>{1}</color>"
|
||||
: "[TLogger][EXCEPTION][{0}] - {1}",
|
||||
System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), logString);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return _stringBuilder;
|
||||
}
|
||||
|
||||
private void Log(LogLevel type, string logString)
|
||||
{
|
||||
if (_outputType == OutputType.NONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (type < _filterLevel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder infoBuilder = GetFormatedString(type, logString, UseSystemColor);
|
||||
string logStr = infoBuilder.ToString();
|
||||
|
||||
//获取C#堆栈,Warning以上级别日志才获取堆栈
|
||||
if (type == LogLevel.ERROR || type == LogLevel.WARNING || type == LogLevel.EXCEPTION)
|
||||
{
|
||||
StackFrame[] sf = new StackTrace().GetFrames();
|
||||
for (int i = 0; i < sf.Length; i++)
|
||||
{
|
||||
StackFrame frame = sf[i];
|
||||
string declaringTypeName = frame.GetMethod().DeclaringType.FullName;
|
||||
string methodName = sf[i].GetMethod().Name;
|
||||
|
||||
infoBuilder.AppendFormat("[{0}::{1}\n", declaringTypeName, methodName);
|
||||
}
|
||||
}
|
||||
|
||||
if (type == LogLevel.INFO || type == LogLevel.Successd)
|
||||
{
|
||||
Debug.Log(logStr);
|
||||
}
|
||||
else if (type == LogLevel.WARNING)
|
||||
{
|
||||
Debug.LogWarning(logStr);
|
||||
}
|
||||
else if (type == LogLevel.ASSERT)
|
||||
{
|
||||
Debug.LogAssertion(logStr);
|
||||
}
|
||||
else if (type == LogLevel.ERROR)
|
||||
{
|
||||
Debug.LogError(logStr);
|
||||
}
|
||||
else if (type == LogLevel.EXCEPTION)
|
||||
{
|
||||
Debug.LogError(logStr);
|
||||
}
|
||||
}
|
||||
|
||||
#region Properties
|
||||
public bool UseCustomColor = false;
|
||||
public bool UseSystemColor = true;
|
||||
|
||||
public enum LogLevel
|
||||
{
|
||||
INFO,
|
||||
Successd,
|
||||
ASSERT,
|
||||
WARNING,
|
||||
ERROR,
|
||||
EXCEPTION,
|
||||
}
|
||||
|
||||
[System.Flags]
|
||||
public enum OutputType
|
||||
{
|
||||
NONE = 0,
|
||||
EDITOR = 0x1,
|
||||
GUI = 0x2,
|
||||
FILE = 0x4
|
||||
}
|
||||
|
||||
private LogLevel _filterLevel = LogLevel.INFO;
|
||||
private OutputType _outputType = OutputType.EDITOR;
|
||||
private StringBuilder _stringBuilder = new StringBuilder();
|
||||
#endregion
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/Core/TLogger.cs.meta
Normal file
11
Assets/TEngine/Runtime/Core/TLogger.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3db72e0120ff79a4cb83a29cbbc3df04
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
198
Assets/TEngine/Runtime/Core/TSingleton.cs
Normal file
198
Assets/TEngine/Runtime/Core/TSingleton.cs
Normal file
@@ -0,0 +1,198 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 单例接口
|
||||
/// </summary>
|
||||
public interface ISingleton
|
||||
{
|
||||
void Active();
|
||||
|
||||
void Release();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 单例管理器(统一化持久和释放)
|
||||
/// </summary>
|
||||
public static class SingletonMgr
|
||||
{
|
||||
private static List<ISingleton> _iSingletonList;
|
||||
private static Dictionary<string, GameObject> _gameObjects;
|
||||
private static GameObject _root;
|
||||
public static GameObject Root
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_root == null)
|
||||
{
|
||||
_root = GameObject.Find("TEngine");
|
||||
}
|
||||
|
||||
return _root;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Retain(ISingleton go)
|
||||
{
|
||||
if (_iSingletonList == null)
|
||||
{
|
||||
_iSingletonList = new List<ISingleton>();
|
||||
}
|
||||
_iSingletonList.Add(go);
|
||||
}
|
||||
|
||||
public static void Retain(GameObject go)
|
||||
{
|
||||
if (_gameObjects == null)
|
||||
{
|
||||
_gameObjects = new Dictionary<string, GameObject>();
|
||||
}
|
||||
|
||||
if (!_gameObjects.ContainsKey(go.name))
|
||||
{
|
||||
_gameObjects.Add(go.name, go);
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
UnityEngine.Object.DontDestroyOnLoad(go);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Release(GameObject go)
|
||||
{
|
||||
if (_gameObjects != null && _gameObjects.ContainsKey(go.name))
|
||||
{
|
||||
_gameObjects.Remove(go.name);
|
||||
UnityEngine.Object.Destroy(go);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Release(ISingleton go)
|
||||
{
|
||||
if (_iSingletonList != null && _iSingletonList.Contains(go))
|
||||
{
|
||||
_iSingletonList.Remove(go);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Release()
|
||||
{
|
||||
if (_gameObjects != null)
|
||||
{
|
||||
foreach (var item in _gameObjects)
|
||||
{
|
||||
UnityEngine.Object.Destroy(item.Value);
|
||||
}
|
||||
|
||||
_gameObjects.Clear();
|
||||
}
|
||||
|
||||
if (_iSingletonList != null)
|
||||
{
|
||||
for (int i = 0; i < _iSingletonList.Count; ++i)
|
||||
{
|
||||
_iSingletonList[i].Release();
|
||||
}
|
||||
|
||||
_iSingletonList.Clear();
|
||||
}
|
||||
|
||||
Resources.UnloadUnusedAssets();
|
||||
}
|
||||
|
||||
public static GameObject GetGameObject(string name)
|
||||
{
|
||||
GameObject go = null;
|
||||
if (_gameObjects != null)
|
||||
{
|
||||
_gameObjects.TryGetValue(name, out go);
|
||||
}
|
||||
|
||||
return go;
|
||||
}
|
||||
|
||||
internal static bool CointansKey(string name)
|
||||
{
|
||||
if (_gameObjects != null)
|
||||
{
|
||||
return _gameObjects.ContainsKey(name);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
internal static ISingleton GetSingleton(string name)
|
||||
{
|
||||
for (int i = 0; i < _iSingletonList.Count; ++i)
|
||||
{
|
||||
if (_iSingletonList[i].ToString() == name)
|
||||
{
|
||||
return _iSingletonList[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 全局单例对象(非线程安全)
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public abstract class TSingleton<T> : ISingleton where T : TSingleton<T>, new()
|
||||
{
|
||||
protected static T _instance = default(T);
|
||||
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == _instance)
|
||||
{
|
||||
_instance = new T();
|
||||
_instance.Init();
|
||||
#if UNITY_EDITOR
|
||||
TLogger.LogInfo($"TSingleton Instance:{typeof(T).Name}");
|
||||
#endif
|
||||
SingletonMgr.Retain(_instance);
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsValid
|
||||
{
|
||||
get
|
||||
{
|
||||
return _instance != null;
|
||||
}
|
||||
}
|
||||
|
||||
protected TSingleton()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected virtual void Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void Active()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void Release()
|
||||
{
|
||||
if (_instance != null)
|
||||
{
|
||||
SingletonMgr.Release(_instance);
|
||||
_instance = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/Core/TSingleton.cs.meta
Normal file
11
Assets/TEngine/Runtime/Core/TSingleton.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9f616a84727082041946279b89d4a1fb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
110
Assets/TEngine/Runtime/Core/UnitySingleton.cs
Normal file
110
Assets/TEngine/Runtime/Core/UnitySingleton.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 具备Unity完整生命周期的单例
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class UnitySingleton<T> : MonoBehaviour where T : MonoBehaviour
|
||||
{
|
||||
|
||||
private static T _instance;
|
||||
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
System.Type thisType = typeof(T);
|
||||
string instName = thisType.Name;
|
||||
GameObject go = SingletonMgr.GetGameObject(instName);
|
||||
if (go == null)
|
||||
{
|
||||
go = GameObject.Find($"/{instName}");
|
||||
if (go == null)
|
||||
{
|
||||
go = new GameObject(instName);
|
||||
go.transform.position = Vector3.zero;
|
||||
}
|
||||
SingletonMgr.Retain(go);
|
||||
}
|
||||
|
||||
if (go != null)
|
||||
{
|
||||
_instance = go.GetComponent<T>();
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = go.AddComponent<T>();
|
||||
}
|
||||
}
|
||||
|
||||
if (_instance == null)
|
||||
{
|
||||
TLogger.LogError($"Can't create UnitySingleton<{typeof(T)}>");
|
||||
}
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public static T Active()
|
||||
{
|
||||
return Instance;
|
||||
}
|
||||
|
||||
public static bool IsValid
|
||||
{
|
||||
get
|
||||
{
|
||||
return _instance != null;
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckInstance()
|
||||
{
|
||||
if (this == Instance)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
GameObject.Destroy(gameObject);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual void OnLoad()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void Awake()
|
||||
{
|
||||
if (CheckInstance())
|
||||
{
|
||||
OnLoad();
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
TLogger.LogInfo($"UnitySingleton Instance:{typeof(T).Name}");
|
||||
GameObject tEngine = SingletonMgr.Root;
|
||||
if (tEngine != null)
|
||||
{
|
||||
this.gameObject.transform.SetParent(tEngine.transform);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
protected virtual void OnDestroy()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
public static void Release()
|
||||
{
|
||||
if (_instance != null)
|
||||
{
|
||||
SingletonMgr.Release(_instance.gameObject);
|
||||
_instance = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/Core/UnitySingleton.cs.meta
Normal file
11
Assets/TEngine/Runtime/Core/UnitySingleton.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ff6e26c492126a4c84b39b2ce7a8423
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/TEngine/Runtime/ECS.meta
Normal file
8
Assets/TEngine/Runtime/ECS.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d941eb2d2cbae294bb5d2788bb724e80
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
113
Assets/TEngine/Runtime/ECS/ArrayPool.cs
Normal file
113
Assets/TEngine/Runtime/ECS/ArrayPool.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public interface IIndex
|
||||
{
|
||||
int Index { get; set; }
|
||||
}
|
||||
|
||||
internal class HashSetDebugView<T> where T : IIndex
|
||||
{
|
||||
private readonly ArrayPool<T> m_Set;
|
||||
|
||||
public HashSetDebugView(ArrayPool<T> set)
|
||||
{
|
||||
m_Set = set ?? throw new ArgumentNullException(nameof(set));
|
||||
}
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
|
||||
public T[] Items
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Set.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerTypeProxy(typeof(HashSetDebugView<>))]
|
||||
[DebuggerDisplay("Count = {Count}")]
|
||||
public class ArrayPool<T> where T:IIndex
|
||||
{
|
||||
internal T[] m_Items = new T[256];
|
||||
internal bool[] Buckets = new bool[256];
|
||||
private int m_Index;
|
||||
private int count;
|
||||
|
||||
public T this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Items[index];
|
||||
}
|
||||
set
|
||||
{
|
||||
m_Items[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
public T[] ToArray()
|
||||
{
|
||||
List<T> elements = new List<T>();
|
||||
for (int i = 0; i < m_Items.Length; i++)
|
||||
{
|
||||
if (Buckets[i])
|
||||
{
|
||||
elements.Add(m_Items[i]);
|
||||
}
|
||||
}
|
||||
return elements.ToArray();
|
||||
}
|
||||
|
||||
public void Remove(T item)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
m_Items[item.Index] = default;
|
||||
Buckets[item.Index] = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(T item)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (item.Index != -1)
|
||||
{
|
||||
if (!Buckets[item.Index])
|
||||
{
|
||||
m_Items[item.Index] = item;
|
||||
Buckets[item.Index] = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_Items[m_Index] = item;
|
||||
Buckets[m_Index] = true;
|
||||
item.Index = m_Index;
|
||||
m_Index++;
|
||||
if (m_Index >= m_Items.Length)
|
||||
{
|
||||
T[] newItems = new T[m_Items.Length * 2];
|
||||
bool[] newBuckets = new bool[m_Items.Length * 2];
|
||||
Array.Copy(m_Items,0,newItems,0,m_Items.Length);
|
||||
Array.Copy(Buckets, 0, newBuckets, 0, Buckets.Length);
|
||||
m_Items = newItems;
|
||||
Buckets = newBuckets;
|
||||
}
|
||||
count = m_Index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/ArrayPool.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/ArrayPool.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1abd052a77e45b44ebcde5803fb36afd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/TEngine/Runtime/ECS/Demo.meta
Normal file
8
Assets/TEngine/Runtime/ECS/Demo.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 385b1863dab169f4fa291611477e106c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
25
Assets/TEngine/Runtime/ECS/Demo/ECSDemoApp.cs
Normal file
25
Assets/TEngine/Runtime/ECS/Demo/ECSDemoApp.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using TEngine;
|
||||
using UnityEngine;
|
||||
|
||||
public class ECSDemoApp : MonoBehaviour
|
||||
{
|
||||
public ECSGameSystem EcsGameSystem = new ECSGameSystem();
|
||||
public GameObject @object;
|
||||
|
||||
void Start()
|
||||
{
|
||||
var entity = EcsGameSystem.Create<Entity>();
|
||||
ECSActor actor = entity.AddComponent<ECSActor>();
|
||||
actor.Name = typeof(ECSActor).ToString();
|
||||
actor.gameObject = Instantiate(@object);
|
||||
actor.transform = actor.gameObject.GetComponent<Transform>();
|
||||
entity.AddComponent<ECSComponent>();
|
||||
|
||||
Debug.Log(entity.ToString());
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
EcsGameSystem.OnUpdate();
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/Demo/ECSDemoApp.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/Demo/ECSDemoApp.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb5cf3287e9bf3949820b50049e4bd8c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
9
Assets/TEngine/Runtime/ECS/Demo/ECSGameSystem.cs
Normal file
9
Assets/TEngine/Runtime/ECS/Demo/ECSGameSystem.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using TEngine;
|
||||
|
||||
public class ECSGameSystem : ECSSystem
|
||||
{
|
||||
public void OnUpdate()
|
||||
{
|
||||
Update();
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/Demo/ECSGameSystem.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/Demo/ECSGameSystem.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d9d458a85873d744ab382e86008b89a0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
13
Assets/TEngine/Runtime/ECS/ECSActor.cs
Normal file
13
Assets/TEngine/Runtime/ECS/ECSActor.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// ECS Actor
|
||||
/// </summary>
|
||||
public class ECSActor : ECSComponent
|
||||
{
|
||||
public string Name;
|
||||
public UnityEngine.GameObject gameObject;
|
||||
public UnityEngine.Transform transform;
|
||||
public uint ActorID;
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/ECSActor.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/ECSActor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34a977c48d3bdb144b7c923a702164b0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
14
Assets/TEngine/Runtime/ECS/ECSComponent.cs
Normal file
14
Assets/TEngine/Runtime/ECS/ECSComponent.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// ECS构架可以将此组件从Entity上移除这个组件并丢入对象池,给其他此刻需要此组件的Entity使用,
|
||||
/// 因此可以节省大量的内存反复创建和释放, 这也是ECS的特性可以大量重复使用组件
|
||||
/// </summary>
|
||||
public class ECSComponent:ECSObject
|
||||
{
|
||||
#pragma warning disable IDE1006
|
||||
public Entity Entity { get; set; }
|
||||
#pragma warning restore IDE1006
|
||||
}
|
||||
}
|
||||
|
11
Assets/TEngine/Runtime/ECS/ECSComponent.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/ECSComponent.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e93d874e10ffedf488c413fd5bbc012f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
72
Assets/TEngine/Runtime/ECS/ECSDebugBehaviour.cs
Normal file
72
Assets/TEngine/Runtime/ECS/ECSDebugBehaviour.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public enum ECSDebugType
|
||||
{
|
||||
Entity,
|
||||
System,
|
||||
Component
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class ECSCmptDebugKeyInfo
|
||||
{
|
||||
public string m_name;
|
||||
public string val;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class ECSCmptDebugInfo
|
||||
{
|
||||
public string m_name;
|
||||
public ECSDebugType Type = ECSDebugType.Component;
|
||||
public List<ECSCmptDebugKeyInfo> m_info = new List<ECSCmptDebugKeyInfo>();
|
||||
}
|
||||
|
||||
public class ECSDebugBehaviour : UnityEngine.MonoBehaviour
|
||||
{
|
||||
public List<ECSCmptDebugInfo> m_ECSInfo = new List<ECSCmptDebugInfo>();
|
||||
public ECSCmptDebugInfo AddDebugCmpt(string cmptName)
|
||||
{
|
||||
var cmptInfo = m_ECSInfo.Find((item) => { return item.m_name == cmptName; });
|
||||
if (cmptInfo == null)
|
||||
{
|
||||
cmptInfo = new ECSCmptDebugInfo();
|
||||
cmptInfo.m_name = cmptName;
|
||||
m_ECSInfo.Add(cmptInfo); ;
|
||||
}
|
||||
|
||||
return cmptInfo;
|
||||
}
|
||||
|
||||
public void RmvDebugCmpt(string cmptName)
|
||||
{
|
||||
m_ECSInfo.RemoveAll((item) => { return item.m_name == cmptName; });
|
||||
}
|
||||
|
||||
public void SetDebugInfo(string cmptName, string key, string val)
|
||||
{
|
||||
var cmptInfo = AddDebugCmpt(cmptName);
|
||||
var entry = cmptInfo.m_info.Find((t) => { return t.m_name == key; });
|
||||
if (entry == null)
|
||||
{
|
||||
entry = new ECSCmptDebugKeyInfo();
|
||||
entry.m_name = key;
|
||||
cmptInfo.m_info.Add(entry);
|
||||
}
|
||||
|
||||
entry.val = val;
|
||||
}
|
||||
|
||||
public void RemoveAllDebugInfo(string cmpName)
|
||||
{
|
||||
var cmpInfo = m_ECSInfo.Find((item) => { return item.m_name == cmpName; });
|
||||
if (cmpInfo != null)
|
||||
{
|
||||
cmpInfo.m_info.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/ECSDebugBehaviour.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/ECSDebugBehaviour.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2dc3e456c545c0c419624e068b9249dc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
236
Assets/TEngine/Runtime/ECS/ECSEventCmpt.cs
Normal file
236
Assets/TEngine/Runtime/ECS/ECSEventCmpt.cs
Normal file
@@ -0,0 +1,236 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public class ECSEventCmpt : ECSComponent
|
||||
{
|
||||
private Dictionary<int, IEcsEcsEventInfo> m_eventDic = new Dictionary<int, IEcsEcsEventInfo>();
|
||||
|
||||
#region AddEventListener
|
||||
public void AddEventListener<T>(int eventid, Action<T> action)
|
||||
{
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventDic[eventid] as EcsEventInfo<T>).actions += action;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_eventDic.Add(eventid, new EcsEventInfo<T>(action));
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEventListener<T, U>(int eventid, Action<T, U> action)
|
||||
{
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventDic[eventid] as EcsEventInfo<T, U>).actions += action;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_eventDic.Add(eventid, new EcsEventInfo<T, U>(action));
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEventListener<T, U, W>(int eventid, Action<T, U, W> action)
|
||||
{
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventDic[eventid] as EcsEventInfo<T, U, W>).actions += action;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_eventDic.Add(eventid, new EcsEventInfo<T, U, W>(action));
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEventListener(int eventid, Action action)
|
||||
{
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventDic[eventid] as EcsEventInfo).actions += action;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_eventDic.Add(eventid, new EcsEventInfo(action));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RemoveEventListener
|
||||
public void RemoveEventListener<T>(int eventid, Action<T> action)
|
||||
{
|
||||
if (action == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventDic[eventid] as EcsEventInfo<T>).actions -= action;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveEventListener<T, U>(int eventid, Action<T, U> action)
|
||||
{
|
||||
if (action == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventDic[eventid] as EcsEventInfo<T, U>).actions -= action;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveEventListener<T, U, W>(int eventid, Action<T, U, W> action)
|
||||
{
|
||||
if (action == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventDic[eventid] as EcsEventInfo<T, U, W>).actions -= action;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveEventListener(int eventid, Action action)
|
||||
{
|
||||
if (action == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventDic[eventid] as EcsEventInfo).actions -= action;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Send
|
||||
public void Send<T>(int eventid, T info)
|
||||
{
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
var EcsEventInfo = (m_eventDic[eventid] as EcsEventInfo<T>);
|
||||
if (EcsEventInfo != null)
|
||||
{
|
||||
EcsEventInfo.actions.Invoke(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Send<T, U>(int eventid, T info, U info2)
|
||||
{
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
var EcsEventInfo = (m_eventDic[eventid] as EcsEventInfo<T, U>);
|
||||
if (EcsEventInfo != null)
|
||||
{
|
||||
EcsEventInfo.actions.Invoke(info, info2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Send<T, U, W>(int eventid, T info, U info2, W info3)
|
||||
{
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
var EcsEventInfo = (m_eventDic[eventid] as EcsEventInfo<T, U, W>);
|
||||
if (EcsEventInfo != null)
|
||||
{
|
||||
EcsEventInfo.actions.Invoke(info, info2, info3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 事件触发 无参
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public void Send(int eventid)
|
||||
{
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
var EcsEventInfo = (m_eventDic[eventid] as EcsEventInfo);
|
||||
if (EcsEventInfo != null)
|
||||
{
|
||||
EcsEventInfo.actions.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Clear
|
||||
public void Clear()
|
||||
{
|
||||
m_eventDic.Clear();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 生命周期
|
||||
public override void OnDestroy()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
public override void Awake()
|
||||
{
|
||||
Entity.Event = this;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region EcsEventInfo
|
||||
internal interface IEcsEcsEventInfo
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class EcsEventInfo : IEcsEcsEventInfo
|
||||
{
|
||||
public Action actions;
|
||||
|
||||
public EcsEventInfo(Action action)
|
||||
{
|
||||
actions += action;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class EcsEventInfo<T> : IEcsEcsEventInfo
|
||||
{
|
||||
public Action<T> actions;
|
||||
|
||||
public EcsEventInfo(Action<T> action)
|
||||
{
|
||||
actions += action;
|
||||
}
|
||||
}
|
||||
|
||||
public class EcsEventInfo<T, U> : IEcsEcsEventInfo
|
||||
{
|
||||
public Action<T, U> actions;
|
||||
|
||||
public EcsEventInfo(Action<T, U> action)
|
||||
{
|
||||
actions += action;
|
||||
}
|
||||
}
|
||||
|
||||
public class EcsEventInfo<T, U, W> : IEcsEcsEventInfo
|
||||
{
|
||||
public Action<T, U, W> actions;
|
||||
|
||||
public EcsEventInfo(Action<T, U, W> action)
|
||||
{
|
||||
actions += action;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/ECSEventCmpt.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/ECSEventCmpt.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af343da6b3090a24b92fc12aaa638411
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
112
Assets/TEngine/Runtime/ECS/ECSObject.cs
Normal file
112
Assets/TEngine/Runtime/ECS/ECSObject.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// ECS架构基类Object
|
||||
/// </summary>
|
||||
public class ECSObject
|
||||
{
|
||||
internal int HashCode;
|
||||
|
||||
internal ECSSystem System;
|
||||
|
||||
public ECSObject()
|
||||
{
|
||||
HashCode = GetType().GetHashCode();
|
||||
}
|
||||
|
||||
public virtual void Awake() { }
|
||||
|
||||
public virtual void OnDestroy() { }
|
||||
|
||||
/// <summary>
|
||||
/// Remove The ECSEntity or Component And Throw the ECSObject to ArrayPool When AddComponent Or Create Can Use Again
|
||||
/// </summary>
|
||||
/// <param name="ecsObject"></param>
|
||||
/// <param name="reuse">此对象是否可以复用,复用会将对象丢入System对象池中 等待再次使用,如果是Entity对象,并且不复用的话,则把Entity所使用的组件也不复用</param>
|
||||
public static void Destroy(ECSObject ecsObject, bool reuse = true)
|
||||
{
|
||||
if (ecsObject is ECSComponent ecsComponent)
|
||||
{
|
||||
ecsComponent.Entity.Components.Remove(ecsComponent);
|
||||
if (ecsComponent is IUpdate update)
|
||||
{
|
||||
ecsComponent.Entity.Updates.Remove(update);
|
||||
}
|
||||
if (reuse)
|
||||
{
|
||||
ecsComponent.Entity.System.Push(ecsComponent);
|
||||
}
|
||||
ecsObject.OnDestroy();
|
||||
return;
|
||||
}
|
||||
else if (ecsObject is Entity entity)
|
||||
{
|
||||
entity.System.RemoveEntity(entity);
|
||||
entity.OnDestroy();
|
||||
while (entity.Components.Count > 0)
|
||||
{
|
||||
ECSComponent ecsComponentTemp = entity.Components[0];
|
||||
entity.Components.RemoveAt(0);
|
||||
ecsComponentTemp.OnDestroy();
|
||||
if (reuse)
|
||||
{
|
||||
entity.System.Push(ecsComponentTemp);
|
||||
}
|
||||
}
|
||||
entity.Updates.Clear();
|
||||
entity.CanUpdate = false;
|
||||
if (reuse)
|
||||
{
|
||||
entity.System.Push(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public T FindObjectOfType<T>() where T : ECSObject
|
||||
{
|
||||
Type type = typeof(T);
|
||||
var elements = System.Entities.ToArray();
|
||||
for (int i = 0; i < elements.Length; i++)
|
||||
{
|
||||
if (elements[i].GetType() == type)
|
||||
{
|
||||
return elements[i] as T;
|
||||
}
|
||||
for (int n = 0; n < elements[i].Components.Count; n++)
|
||||
{
|
||||
if (elements[i].Components[n].GetType() == type)
|
||||
{
|
||||
return elements[i].Components[n] as T;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public T[] FindObjectsOfType<T>() where T : ECSObject
|
||||
{
|
||||
Type type = typeof(T);
|
||||
var items = System.Entities.ToArray();
|
||||
List<T> elements = new List<T>();
|
||||
for (int i = 0; i < items.Length; i++)
|
||||
{
|
||||
if (items[i].GetType() == type)
|
||||
{
|
||||
elements.Add(items[i] as T);
|
||||
}
|
||||
for (int n = 0; n < items[i].Components.Count; n++)
|
||||
{
|
||||
if (items[i].Components[n].GetType() == type)
|
||||
{
|
||||
elements.Add(items[i].Components[n] as T);
|
||||
}
|
||||
}
|
||||
}
|
||||
return elements.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
11
Assets/TEngine/Runtime/ECS/ECSObject.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/ECSObject.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 003794832e9179348a633bdafe92ff3c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
233
Assets/TEngine/Runtime/ECS/ECSSystem.cs
Normal file
233
Assets/TEngine/Runtime/ECS/ECSSystem.cs
Normal file
@@ -0,0 +1,233 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// ECS系统 管理Entity、ECSComponent复用对象池
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class ECSSystem : IDisposable
|
||||
{
|
||||
private static ECSSystem instance = new ECSSystem();
|
||||
public static ECSSystem Instance => instance;
|
||||
private readonly Dictionary<int,Stack<ECSObject>> m_ObjectPool = new Dictionary<int, Stack<ECSObject>>();
|
||||
internal readonly ArrayPool<Entity> Entities = new ArrayPool<Entity>();
|
||||
private bool m_IsDispose = false;
|
||||
|
||||
public void AddEntity(Entity entity)
|
||||
{
|
||||
entity.System = this;
|
||||
entity.Awake();
|
||||
Entities.Add(entity);
|
||||
}
|
||||
|
||||
public void RemoveEntity(Entity entity)
|
||||
{
|
||||
Entities.Remove(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get Object From ECSSystem
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public T Get<T>() where T : ECSObject, new()
|
||||
{
|
||||
int type = typeof(T).GetHashCode();
|
||||
if (m_ObjectPool.TryGetValue(type,out Stack<ECSObject> stack))
|
||||
{
|
||||
if (stack.Count > 0)
|
||||
{
|
||||
return (T) stack.Pop();
|
||||
}
|
||||
goto Instantiate;
|
||||
}
|
||||
stack = new Stack<ECSObject>();
|
||||
m_ObjectPool.Add(type,stack);
|
||||
Instantiate: T ecsObject = new T();
|
||||
return ecsObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Push Object To ECSSystem
|
||||
/// </summary>
|
||||
public void Push(ECSObject ecsObject)
|
||||
{
|
||||
int type = ecsObject.HashCode;
|
||||
|
||||
if (m_ObjectPool.TryGetValue(type,out Stack<ECSObject> stack))
|
||||
{
|
||||
stack.Push(ecsObject);
|
||||
return;
|
||||
}
|
||||
stack = new Stack<ECSObject>();
|
||||
m_ObjectPool.Add(type,stack);
|
||||
stack.Push(ecsObject);
|
||||
}
|
||||
|
||||
public T Create<T>() where T : Entity, new()
|
||||
{
|
||||
T entity = Get<T>();
|
||||
AddEntity(entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
public T Create<T>(T entity) where T : Entity, new()
|
||||
{
|
||||
AddEntity(entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新ECS系统
|
||||
/// </summary>
|
||||
/// <param name="worker">线程池是否并行</param>
|
||||
public void Update(bool worker = false)
|
||||
{
|
||||
Run(worker);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新ECS物理系统
|
||||
/// </summary>
|
||||
/// <param name="worker">线程池是否并行</param>
|
||||
public void FixedUpdate(bool worker = false)
|
||||
{
|
||||
RunFixed(worker);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 运行ECS系统
|
||||
/// </summary>
|
||||
/// <param name="worker">线程池是否并行</param>
|
||||
public void Run(bool worker = false)
|
||||
{
|
||||
int count = Entities.Count;
|
||||
if (!worker)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (!Entities.Buckets[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Entities[i].CanUpdate)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Entities[i].Execute();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Parallel.For(0, count, i =>
|
||||
{
|
||||
if (!Entities.Buckets[i])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Entities[i].CanUpdate)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Entities[i].Execute();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void RunFixed(bool worker = false)
|
||||
{
|
||||
int count = Entities.Count;
|
||||
if (!worker)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (!Entities.Buckets[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Entities[i].CanFixedUpdate)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Entities[i].FixedUpdate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Parallel.For(0, count, i =>
|
||||
{
|
||||
if (!Entities.Buckets[i])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Entities[i].CanFixedUpdate)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Entities[i].FixedUpdate();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (m_IsDispose)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_IsDispose = true;
|
||||
}
|
||||
|
||||
public T FindObjectOfType<T>() where T : ECSObject
|
||||
{
|
||||
Type type = typeof(T);
|
||||
var elements = Entities.ToArray();
|
||||
for (int i = 0; i < elements.Length; i++)
|
||||
{
|
||||
if (elements[i].GetType() == type)
|
||||
{
|
||||
return elements[i] as T;
|
||||
}
|
||||
|
||||
for (int j = 0; j < elements[i].Components.Count; j++)
|
||||
{
|
||||
if (elements[i].Components[j].GetType() == type)
|
||||
{
|
||||
return elements[i].Components[j] as T;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public T[] FindObjectsOfType<T>() where T : ECSObject
|
||||
{
|
||||
Type type = typeof(T);
|
||||
var entities = Entities.ToArray();
|
||||
List<T> elements = new List<T>();
|
||||
for (int i = 0; i < entities.Length; i++)
|
||||
{
|
||||
if (entities[i].GetType() == type)
|
||||
{
|
||||
elements.Add(entities[i] as T);
|
||||
}
|
||||
for (int n = 0; n < entities[i].Components.Count; n++)
|
||||
{
|
||||
if (entities[i].Components[n].GetType() == type)
|
||||
{
|
||||
elements.Add(entities[i].Components[n] as T);
|
||||
}
|
||||
}
|
||||
}
|
||||
return elements.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
11
Assets/TEngine/Runtime/ECS/ECSSystem.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/ECSSystem.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2bd4af51a518164c8da0dff296b2bb1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
273
Assets/TEngine/Runtime/ECS/Entity.cs
Normal file
273
Assets/TEngine/Runtime/ECS/Entity.cs
Normal file
@@ -0,0 +1,273 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public class Entity : ECSObject, IIndex
|
||||
{
|
||||
[SerializeField]
|
||||
internal List<ECSComponent> Components = new List<ECSComponent>();
|
||||
internal List<IUpdate> Updates = new List<IUpdate>();
|
||||
internal List<IFixedUpdate> FixedUpdates = new List<IFixedUpdate>();
|
||||
internal bool InActive;
|
||||
internal bool CanUpdate;
|
||||
internal bool CanFixedUpdate;
|
||||
public int Index { get; set; } = -1;
|
||||
public ECSEventCmpt Event { get; set; }
|
||||
public Entity()
|
||||
{
|
||||
InActive = true;
|
||||
System = ECSSystem.Instance;
|
||||
}
|
||||
|
||||
~Entity()
|
||||
{
|
||||
InActive = false;
|
||||
}
|
||||
|
||||
internal void Execute()
|
||||
{
|
||||
for (int i = 0; i < Updates.Count; i++)
|
||||
{
|
||||
Updates[i].Update();
|
||||
}
|
||||
}
|
||||
|
||||
internal void FixedUpdate()
|
||||
{
|
||||
for (int i = 0; i < FixedUpdates.Count; i++)
|
||||
{
|
||||
FixedUpdates[i].FixedUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
public void RmvComponent<T>() where T : ECSComponent, new()
|
||||
{
|
||||
for (int i = 0; i < Components.Count; i++)
|
||||
{
|
||||
if (Components[i] is T component)
|
||||
{
|
||||
if (component is IUpdate update)
|
||||
{
|
||||
Updates.Remove(update);
|
||||
}
|
||||
else if (component is IFixedUpdate fixedUpdate)
|
||||
{
|
||||
FixedUpdates.Remove(fixedUpdate);
|
||||
}
|
||||
|
||||
System.Push(component);
|
||||
|
||||
CanUpdate = Updates.Count > 0;
|
||||
|
||||
CanFixedUpdate = FixedUpdates.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
CheckDebugInfo();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void RmvComponent(Type componentType)
|
||||
{
|
||||
for (int i = 0; i < Components.Count; i++)
|
||||
{
|
||||
if (Components[i].GetType() == componentType)
|
||||
{
|
||||
|
||||
if (componentType is IUpdate update)
|
||||
{
|
||||
Updates.Remove(update);
|
||||
|
||||
CanUpdate = Updates.Count > 0;
|
||||
}
|
||||
else if (componentType is IFixedUpdate fixedUpdate)
|
||||
{
|
||||
FixedUpdates.Remove(fixedUpdate);
|
||||
|
||||
CanFixedUpdate = FixedUpdates.Count > 0;
|
||||
}
|
||||
//if (componentType is ECSComponent component)
|
||||
//{
|
||||
// System.Push(component);
|
||||
//}
|
||||
}
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
CheckDebugInfo();
|
||||
#endif
|
||||
}
|
||||
|
||||
public T AddComponent<T>() where T : ECSComponent, new()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
CheckDebugInfo();
|
||||
#endif
|
||||
T component = System.Get<T>();
|
||||
component.Entity = this;
|
||||
component.System = System;
|
||||
Components.Add(component);
|
||||
component.Awake();
|
||||
if (component is IUpdate update)
|
||||
{
|
||||
Updates.Add(update);
|
||||
}
|
||||
else if (component is IFixedUpdate fixedUpdate)
|
||||
{
|
||||
FixedUpdates.Add(fixedUpdate);
|
||||
}
|
||||
CanUpdate = Updates.Count > 0;
|
||||
CanFixedUpdate = FixedUpdates.Count > 0;
|
||||
return component;
|
||||
}
|
||||
|
||||
public ECSComponent AddComponent(ECSComponent component)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
CheckDebugInfo();
|
||||
#endif
|
||||
component.Entity = this;
|
||||
component.System = System;
|
||||
Components.Add(component);
|
||||
component.Awake();
|
||||
if (component is IUpdate update)
|
||||
{
|
||||
Updates.Add(update);
|
||||
}
|
||||
else if (component is IFixedUpdate fixedUpdate)
|
||||
{
|
||||
FixedUpdates.Add(fixedUpdate);
|
||||
}
|
||||
CanUpdate = Updates.Count > 0;
|
||||
CanFixedUpdate = FixedUpdates.Count > 0;
|
||||
return component;
|
||||
}
|
||||
|
||||
public T GetComponent<T>() where T : ECSComponent
|
||||
{
|
||||
for (int i = 0; i < Components.Count; i++)
|
||||
{
|
||||
if (Components[i] is T type)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ECSComponent GetComponent(Type componentType)
|
||||
{
|
||||
for (int i = 0; i < Components.Count; i++)
|
||||
{
|
||||
if (Components[i].GetType() == componentType)
|
||||
{
|
||||
return Components[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public T[] GetComponents<T>() where T : ECSComponent
|
||||
{
|
||||
List<T> elements = new List<T>();
|
||||
for (int i = 0; i < Components.Count; i++)
|
||||
{
|
||||
if (Components[i] is T type)
|
||||
{
|
||||
elements.Add(type);
|
||||
}
|
||||
}
|
||||
return elements.ToArray();
|
||||
}
|
||||
|
||||
public List<T> GetComponentsList<T>() where T : ECSComponent
|
||||
{
|
||||
List<T> elements = new List<T>();
|
||||
for (int i = 0; i < Components.Count; i++)
|
||||
{
|
||||
if (Components[i] is T type)
|
||||
{
|
||||
elements.Add(type);
|
||||
}
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
public ECSComponent[] GetComponents(Type comType)
|
||||
{
|
||||
List<ECSComponent> elements = new List<ECSComponent>();
|
||||
for (int i = 0; i < Components.Count; i++)
|
||||
{
|
||||
{
|
||||
if (Components[i].GetType() == comType)
|
||||
{
|
||||
elements.Add(Components[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return elements.ToArray();
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string str = "[";
|
||||
for (int i = 0; i < Components.Count; i++)
|
||||
{
|
||||
str += Components[i].GetType().Name + ",";
|
||||
}
|
||||
str = str.TrimEnd(',');
|
||||
str += "]";
|
||||
return $"{GetType().Name} Components: {str}";
|
||||
}
|
||||
|
||||
|
||||
public void CheckDebugInfo(GameObject gameObject)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (gameObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var debugBehaviour = UnityUtil.AddMonoBehaviour<ECSDebugBehaviour>(gameObject);
|
||||
debugBehaviour.m_ECSInfo.Clear();
|
||||
for (int i = 0; i < this.Components.Count; i++)
|
||||
{
|
||||
var component = this.Components[i];
|
||||
var cmptName = component.GetType().Name;
|
||||
debugBehaviour.SetDebugInfo(cmptName, "", "");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
public void CheckDebugInfo()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
//var actorEntity = this as Entity;
|
||||
|
||||
//if (actorEntity == null)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
|
||||
//if (actorEntity.gameObject == null)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
|
||||
//var debugBehaviour = UnityUtil.AddMonoBehaviour<ECSDebugBehaviour>(actorEntity.gameObject);
|
||||
//debugBehaviour.m_ECSInfo.Clear();
|
||||
//for (int i = 0; i < this.Components.Count; i++)
|
||||
//{
|
||||
// var component = this.Components[i];
|
||||
// var cmptName = component.GetType().Name;
|
||||
// debugBehaviour.SetDebugInfo(cmptName, "", "");
|
||||
//}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/Entity.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/Entity.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9f5bc14d7a4aee34695c39d02ae1c71f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
32
Assets/TEngine/Runtime/ECS/HotfixComponent.cs
Normal file
32
Assets/TEngine/Runtime/ECS/HotfixComponent.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public class HotfixComponent : ECSComponent,IUpdate
|
||||
{
|
||||
public object[] Values;
|
||||
public Action OnAwake, OnUpdate, OnDestroyExt;
|
||||
|
||||
public override void Awake()
|
||||
{
|
||||
OnAwake?.Invoke();
|
||||
}
|
||||
|
||||
void IUpdate.Update()
|
||||
{
|
||||
OnUpdate?.Invoke();
|
||||
}
|
||||
|
||||
public override void OnDestroy()
|
||||
{
|
||||
OnDestroyExt?.Invoke();
|
||||
OnAwake = null;
|
||||
OnUpdate = null;
|
||||
OnDestroyExt = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
11
Assets/TEngine/Runtime/ECS/HotfixComponent.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/HotfixComponent.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0ac8b7fabe2bae499a568608191eb57
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
10
Assets/TEngine/Runtime/ECS/IFixedUpdate.cs
Normal file
10
Assets/TEngine/Runtime/ECS/IFixedUpdate.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// ECS组件更新接口(减少组件for循环开销)
|
||||
/// </summary>
|
||||
public interface IFixedUpdate
|
||||
{
|
||||
void FixedUpdate();
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/IFixedUpdate.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/IFixedUpdate.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7fb8a7b6d364a024e8a49a0a731de201
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
10
Assets/TEngine/Runtime/ECS/IUpdate.cs
Normal file
10
Assets/TEngine/Runtime/ECS/IUpdate.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// ECS组件更新接口(减少组件for循环开销)
|
||||
/// </summary>
|
||||
public interface IUpdate
|
||||
{
|
||||
void Update();
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/IUpdate.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/IUpdate.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7918afae3870234391c6e6f521e9ca7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
13
Assets/TEngine/Runtime/ECS/UpdateComponent.cs
Normal file
13
Assets/TEngine/Runtime/ECS/UpdateComponent.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 热更层由此组件进行更新(ILRuntime不支持多继承, 接口继承)
|
||||
/// </summary>
|
||||
public class UpdateComponent :ECSComponent, IUpdate
|
||||
{
|
||||
public virtual void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/ECS/UpdateComponent.cs.meta
Normal file
11
Assets/TEngine/Runtime/ECS/UpdateComponent.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02463b27b6971f0408bb517c32c66553
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/TEngine/Runtime/Event.meta
Normal file
8
Assets/TEngine/Runtime/Event.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bbe3f3f803983744f83757c6180a1c22
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
392
Assets/TEngine/Runtime/Event/GameEventMgr.cs
Normal file
392
Assets/TEngine/Runtime/Event/GameEventMgr.cs
Normal file
@@ -0,0 +1,392 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TEngine;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
#region EventInfo
|
||||
internal interface IEventInfo
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class EventInfo : IEventInfo
|
||||
{
|
||||
public Action actions;
|
||||
|
||||
public EventInfo(Action action)
|
||||
{
|
||||
actions += action;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class EventInfo<T> : IEventInfo
|
||||
{
|
||||
public Action<T> actions;
|
||||
|
||||
public EventInfo(Action<T> action)
|
||||
{
|
||||
actions += action;
|
||||
}
|
||||
}
|
||||
|
||||
public class EventInfo<T, U> : IEventInfo
|
||||
{
|
||||
public Action<T, U> actions;
|
||||
|
||||
public EventInfo(Action<T, U> action)
|
||||
{
|
||||
actions += action;
|
||||
}
|
||||
}
|
||||
|
||||
public class EventInfo<T, U, W> : IEventInfo
|
||||
{
|
||||
public Action<T, U, W> actions;
|
||||
|
||||
public EventInfo(Action<T, U, W> action)
|
||||
{
|
||||
actions += action;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// 总观察者 - 总事件中心系统
|
||||
/// </summary>
|
||||
public class GameEventMgr : TSingleton<GameEventMgr>
|
||||
{
|
||||
/// <summary>
|
||||
/// Dictionary<int, IEventInfo> Key->Int.32 Value->EventInfo,调用频率高建议使用int事件,减少字典内String的哈希碰撞
|
||||
/// </summary>
|
||||
private Dictionary<int, IEventInfo> m_eventDic = new Dictionary<int, IEventInfo>();
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary<string, IEventInfo> Key->string Value->EventInfo,调用频率不高的时候可以使用
|
||||
/// </summary>
|
||||
private Dictionary<string, IEventInfo> m_eventStrDic = new Dictionary<string, IEventInfo>();
|
||||
|
||||
#region AddEventListener
|
||||
public void AddEventListener<T>(int eventid, Action<T> action)
|
||||
{
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventDic[eventid] as EventInfo<T>).actions += action;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_eventDic.Add(eventid, new EventInfo<T>(action));
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEventListener<T, U>(int eventid, Action<T, U> action)
|
||||
{
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventDic[eventid] as EventInfo<T, U>).actions += action;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_eventDic.Add(eventid, new EventInfo<T, U>(action));
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEventListener<T, U, W>(int eventid, Action<T, U, W> action)
|
||||
{
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventDic[eventid] as EventInfo<T, U, W>).actions += action;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_eventDic.Add(eventid, new EventInfo<T, U, W>(action));
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEventListener(int eventid, Action action)
|
||||
{
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventDic[eventid] as EventInfo).actions += action;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_eventDic.Add(eventid, new EventInfo(action));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RemoveEventListener
|
||||
public void RemoveEventListener<T>(int eventid, Action<T> action)
|
||||
{
|
||||
if (action == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventDic[eventid] as EventInfo<T>).actions -= action;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveEventListener<T, U>(int eventid, Action<T, U> action)
|
||||
{
|
||||
if (action == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventDic[eventid] as EventInfo<T, U>).actions -= action;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveEventListener<T, U, W>(int eventid, Action<T, U, W> action)
|
||||
{
|
||||
if (action == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventDic[eventid] as EventInfo<T, U, W>).actions -= action;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveEventListener(int eventid, Action action)
|
||||
{
|
||||
if (action == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventDic[eventid] as EventInfo).actions -= action;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Send
|
||||
public void Send<T>(int eventid, T info)
|
||||
{
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
var eventInfo = (m_eventDic[eventid] as EventInfo<T>);
|
||||
if (eventInfo != null)
|
||||
{
|
||||
eventInfo.actions.Invoke(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Send<T, U>(int eventid, T info, U info2)
|
||||
{
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
var eventInfo = (m_eventDic[eventid] as EventInfo<T, U>);
|
||||
if (eventInfo != null)
|
||||
{
|
||||
eventInfo.actions.Invoke(info, info2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Send<T, U, W>(int eventid, T info, U info2, W info3)
|
||||
{
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
var eventInfo = (m_eventDic[eventid] as EventInfo<T, U, W>);
|
||||
if (eventInfo != null)
|
||||
{
|
||||
eventInfo.actions.Invoke(info, info2, info3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 事件触发 无参
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public void Send(int eventid)
|
||||
{
|
||||
if (m_eventDic.ContainsKey(eventid))
|
||||
{
|
||||
var eventInfo = (m_eventDic[eventid] as EventInfo);
|
||||
if (eventInfo != null)
|
||||
{
|
||||
eventInfo.actions.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region StringEvent
|
||||
#region AddEventListener
|
||||
public void AddEventListener<T>(string eventid, Action<T> action)
|
||||
{
|
||||
if (m_eventStrDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventStrDic[eventid] as EventInfo<T>).actions += action;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_eventStrDic.Add(eventid, new EventInfo<T>(action));
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEventListener<T, U>(string eventid, Action<T, U> action)
|
||||
{
|
||||
if (m_eventStrDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventStrDic[eventid] as EventInfo<T, U>).actions += action;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_eventStrDic.Add(eventid, new EventInfo<T, U>(action));
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEventListener<T, U, W>(string eventid, Action<T, U, W> action)
|
||||
{
|
||||
if (m_eventStrDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventStrDic[eventid] as EventInfo<T, U, W>).actions += action;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_eventStrDic.Add(eventid, new EventInfo<T, U, W>(action));
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEventListener(string eventid, Action action)
|
||||
{
|
||||
if (m_eventStrDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventStrDic[eventid] as EventInfo).actions += action;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_eventStrDic.Add(eventid, new EventInfo(action));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RemoveEventListener
|
||||
public void RemoveEventListener<T>(string eventid, Action<T> action)
|
||||
{
|
||||
if (action == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_eventStrDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventStrDic[eventid] as EventInfo<T>).actions -= action;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveEventListener<T, U>(string eventid, Action<T, U> action)
|
||||
{
|
||||
if (action == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_eventStrDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventStrDic[eventid] as EventInfo<T, U>).actions -= action;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveEventListener<T, U, W>(string eventid, Action<T, U, W> action)
|
||||
{
|
||||
if (action == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_eventStrDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventStrDic[eventid] as EventInfo<T, U, W>).actions -= action;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveEventListener(string eventid, Action action)
|
||||
{
|
||||
if (action == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_eventStrDic.ContainsKey(eventid))
|
||||
{
|
||||
(m_eventStrDic[eventid] as EventInfo).actions -= action;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Send
|
||||
public void Send<T>(string eventid, T info)
|
||||
{
|
||||
if (m_eventStrDic.ContainsKey(eventid))
|
||||
{
|
||||
var eventInfo = (m_eventStrDic[eventid] as EventInfo<T>);
|
||||
if (eventInfo != null)
|
||||
{
|
||||
eventInfo.actions.Invoke(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Send<T, U>(string eventid, T info, U info2)
|
||||
{
|
||||
if (m_eventStrDic.ContainsKey(eventid))
|
||||
{
|
||||
var eventInfo = (m_eventStrDic[eventid] as EventInfo<T, U>);
|
||||
if (eventInfo != null)
|
||||
{
|
||||
eventInfo.actions.Invoke(info, info2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Send<T, U, W>(string eventid, T info, U info2, W info3)
|
||||
{
|
||||
if (m_eventStrDic.ContainsKey(eventid))
|
||||
{
|
||||
var eventInfo = (m_eventStrDic[eventid] as EventInfo<T, U, W>);
|
||||
if (eventInfo != null)
|
||||
{
|
||||
eventInfo.actions.Invoke(info, info2, info3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Send(string eventid)
|
||||
{
|
||||
if (m_eventStrDic.ContainsKey(eventid))
|
||||
{
|
||||
var eventInfo = (m_eventStrDic[eventid] as EventInfo);
|
||||
if (eventInfo != null)
|
||||
{
|
||||
eventInfo.actions.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Clear
|
||||
public void Clear()
|
||||
{
|
||||
m_eventDic.Clear();
|
||||
m_eventStrDic.Clear();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
11
Assets/TEngine/Runtime/Event/GameEventMgr.cs.meta
Normal file
11
Assets/TEngine/Runtime/Event/GameEventMgr.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c42c5b68ecfcd7849bc964b670a1217e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
37
Assets/TEngine/Runtime/Event/StringId.cs
Normal file
37
Assets/TEngine/Runtime/Event/StringId.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public class StringId
|
||||
{
|
||||
private static Dictionary<string, int> m_eventTypeHashMap = new Dictionary<string, int>();
|
||||
private static Dictionary<int, string> m_eventHashToStringMap = new Dictionary<int, string>();
|
||||
private static int m_currentId = 0;
|
||||
|
||||
public static int StringToHash(string val)
|
||||
{
|
||||
int hashId;
|
||||
if (m_eventTypeHashMap.TryGetValue(val, out hashId))
|
||||
{
|
||||
return hashId;
|
||||
}
|
||||
|
||||
hashId = ++m_currentId;
|
||||
m_eventTypeHashMap[val] = hashId;
|
||||
m_eventHashToStringMap[hashId] = val;
|
||||
|
||||
return hashId;
|
||||
}
|
||||
|
||||
public static string HashToString(int hash)
|
||||
{
|
||||
string value;
|
||||
if (m_eventHashToStringMap.TryGetValue(hash, out value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
11
Assets/TEngine/Runtime/Event/StringId.cs.meta
Normal file
11
Assets/TEngine/Runtime/Event/StringId.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa2415431c50eaf468e5c8cc468ac47f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/TEngine/Runtime/FileSystem.meta
Normal file
8
Assets/TEngine/Runtime/FileSystem.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d49eaeb5e19e9945add3faaf9921f10
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
130
Assets/TEngine/Runtime/FileSystem/FileSystem.cs
Normal file
130
Assets/TEngine/Runtime/FileSystem/FileSystem.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public static class FileSystem
|
||||
{
|
||||
public const string ArtResourcePath = "Assets/ArtResources";
|
||||
public const string GameResourcePath = AssetConfig.AssetRootPath;
|
||||
internal static Dictionary<string, string> _fileFixList = new Dictionary<string, string>();
|
||||
private static string _persistentDataPath = null;
|
||||
private static string _resRootPath = null;
|
||||
private static string _resRootStreamAssetPath = null;
|
||||
public const string BuildPath = "Build";
|
||||
public const string AssetBundleBuildPath = BuildPath + "/AssetBundles";
|
||||
private const string AssetBundleTargetPath = "{0}/AssetBundles";
|
||||
/// <summary>
|
||||
/// 资源更新读取根目录
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string ResourceRoot
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_resRootPath))
|
||||
{
|
||||
_resRootPath = Path.Combine(PersistentDataPath, "TEngine");
|
||||
}
|
||||
|
||||
if (!Directory.Exists(_resRootPath))
|
||||
{
|
||||
Directory.CreateDirectory(_resRootPath);
|
||||
}
|
||||
|
||||
return _resRootPath.FixPath();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 持久化数据存储路径
|
||||
/// </summary>
|
||||
public static string PersistentDataPath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_persistentDataPath))
|
||||
{
|
||||
#if UNITY_EDITOR_WIN
|
||||
_persistentDataPath = Application.dataPath + "/../TEnginePersistentDataPath";
|
||||
if (!Directory.Exists(_persistentDataPath))
|
||||
{
|
||||
Directory.CreateDirectory(_persistentDataPath);
|
||||
}
|
||||
#else
|
||||
_persistentDataPath = Application.persistentDataPath;
|
||||
#endif
|
||||
}
|
||||
return _persistentDataPath.FixPath();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 资源更新读取StreamAsset根目录
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string ResourceRootInStreamAsset
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_resRootStreamAssetPath))
|
||||
{
|
||||
_resRootStreamAssetPath = Path.Combine(Application.streamingAssetsPath, "TEngine");
|
||||
}
|
||||
return _resRootStreamAssetPath.FixPath();
|
||||
}
|
||||
}
|
||||
public static string GetAssetBundlePathInVersion(string bundlename)
|
||||
{
|
||||
//默认用外部目录
|
||||
string path = FilePath($"{ResourceRoot}/AssetBundles/{bundlename}");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
path = $"{ResourceRootInStreamAsset}/AssetBundles/{bundlename}";
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public static string StreamAssetBundlePath
|
||||
{
|
||||
get { return string.Format(AssetBundleTargetPath, ResourceRootInStreamAsset); }
|
||||
}
|
||||
|
||||
internal static string FilePath(string path)
|
||||
{
|
||||
path = path.FixPath();
|
||||
#if UNITY_EDITOR_WIN
|
||||
path = path.Replace("Assets/../", "");
|
||||
#endif
|
||||
if (_fileFixList.ContainsKey(path))
|
||||
{
|
||||
return _fileFixList[path];
|
||||
}
|
||||
else
|
||||
{
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
public static string FixPath(this string str)
|
||||
{
|
||||
str = str.Replace("\\", "/");
|
||||
return str;
|
||||
}
|
||||
|
||||
public static Stream OpenRead(string filePath)
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
byte[] bytes = ReadAllBytesFromOutOrInnerFolder(filePath);
|
||||
if (bytes != null)
|
||||
return new MemoryStream(bytes);
|
||||
else
|
||||
return null;
|
||||
#else
|
||||
return File.OpenRead(filePath);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/FileSystem/FileSystem.cs.meta
Normal file
11
Assets/TEngine/Runtime/FileSystem/FileSystem.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d47370f2bbc4b354d9d8b6cd95c9f3bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
96
Assets/TEngine/Runtime/FileSystem/FileWriter.cs
Normal file
96
Assets/TEngine/Runtime/FileSystem/FileWriter.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public class FileWriter
|
||||
{
|
||||
private FileStream _fStream;
|
||||
private StreamWriter _writer;
|
||||
|
||||
|
||||
public bool OpenFile(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
_fStream = File.Open(path, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
|
||||
_writer = new StreamWriter(_fStream);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
TLogger.LogException(e.ToString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Shutdown()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_writer != null)
|
||||
{
|
||||
_writer.Close();
|
||||
}
|
||||
_writer = null;
|
||||
|
||||
if (_fStream != null)
|
||||
{
|
||||
_fStream.Close();
|
||||
}
|
||||
_fStream = null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
TLogger.LogException(e.ToString());
|
||||
_writer = null;
|
||||
_fStream = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(string msg)
|
||||
{
|
||||
if (_writer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(msg))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_writer.WriteLine(msg);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
Flush();
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
if (_writer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (_writer.BaseStream != null)
|
||||
{
|
||||
_writer.Flush();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Shutdown();
|
||||
TLogger.LogException( e.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/FileSystem/FileWriter.cs.meta
Normal file
11
Assets/TEngine/Runtime/FileSystem/FileWriter.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e93fa62068e31849833f7077a8179d5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
106
Assets/TEngine/Runtime/FileSystem/LogToFile.cs
Normal file
106
Assets/TEngine/Runtime/FileSystem/LogToFile.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
public class LogToFile
|
||||
{
|
||||
private FileWriter _fileWriter = new FileWriter();
|
||||
private static readonly string mLogRootPath = Path.Combine(FileSystem.PersistentDataPath, "Log").FixPath();
|
||||
private static int MaxLogDays = 3;
|
||||
private static string _currentLogName = string.Empty;
|
||||
|
||||
private string GetLogPath(DateTime dt)
|
||||
{
|
||||
string dataDir = dt.ToString("yyyy_MM_dd");
|
||||
string logPath = Path.Combine(mLogRootPath, dataDir);
|
||||
return logPath.FixPath();
|
||||
}
|
||||
|
||||
public void DeInit()
|
||||
{
|
||||
if (_fileWriter == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_fileWriter.Flush();
|
||||
_fileWriter.Shutdown();
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
DateTime currentTime = DateTime.Now;
|
||||
RemoveOldLogs(currentTime);
|
||||
string logDir = GetLogPath(currentTime);
|
||||
string logFileName = string.Format("Log_{0}.log", currentTime.ToString("yyyy_MM_dd-HH_mm_ss"));
|
||||
_currentLogName = logFileName;
|
||||
string fullPath = Path.Combine(logDir, logFileName).FixPath();
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(logDir))
|
||||
{
|
||||
Directory.CreateDirectory(logDir);
|
||||
}
|
||||
|
||||
if (File.Exists(fullPath))
|
||||
{
|
||||
File.Delete(fullPath);
|
||||
}
|
||||
|
||||
_fileWriter.OpenFile(fullPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
TLogger.LogException( e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(string msg)
|
||||
{
|
||||
if (_fileWriter == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_fileWriter.Write(msg);
|
||||
}
|
||||
|
||||
private void RemoveOldLogs(DateTime now)
|
||||
{
|
||||
HashSet<string> foldersToKeep = new HashSet<string>();
|
||||
for (int i = 0; i < MaxLogDays; i++)
|
||||
{
|
||||
DateTime current = now.AddDays(-i);
|
||||
string folder = GetLogPath(current);
|
||||
foldersToKeep.Add(folder);
|
||||
}
|
||||
if (Directory.Exists(mLogRootPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] allLogDir = Directory.GetDirectories(mLogRootPath);
|
||||
foreach (string dir in allLogDir)
|
||||
{
|
||||
string fixedDir = dir.FixPath();
|
||||
if (!foldersToKeep.Contains(fixedDir))
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(fixedDir, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
TLogger.LogException(e.ToString());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
TLogger.LogException(e.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/TEngine/Runtime/FileSystem/LogToFile.cs.meta
Normal file
11
Assets/TEngine/Runtime/FileSystem/LogToFile.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e1223cf4c8c7f0746968878b1e16f356
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/TEngine/Runtime/HotUpdate.meta
Normal file
8
Assets/TEngine/Runtime/HotUpdate.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bcb4b9a81c7ec9e4485ffdd16ea3b198
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/TEngine/Runtime/HotUpdate/Editor.meta
Normal file
8
Assets/TEngine/Runtime/HotUpdate/Editor.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0957d93b8c01bb74a8b6c8a6b15dede9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
234
Assets/TEngine/Runtime/HotUpdate/Editor/HTEditorCache.cs
Normal file
234
Assets/TEngine/Runtime/HotUpdate/Editor/HTEditorCache.cs
Normal file
@@ -0,0 +1,234 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Huatuo.Editor
|
||||
{
|
||||
enum EFILE_NAME
|
||||
{
|
||||
NONE,
|
||||
HUATUO,
|
||||
IL2CPP,
|
||||
HUATUO_MAIN,
|
||||
}
|
||||
|
||||
internal class HTEditorCache
|
||||
{
|
||||
private string libil2cppTagPrefix;
|
||||
private string huatuoTagPrefix;
|
||||
private int m_nDownloadTotal;
|
||||
private int m_counter;
|
||||
private int m_nSuccessCount;
|
||||
private int m_nFailedCount;
|
||||
|
||||
private static HTEditorCache instance = null;
|
||||
|
||||
public static HTEditorCache Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new HTEditorCache();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
private static string CacheDirName = ".huatuo_cache";
|
||||
public string CacheBasePath;
|
||||
|
||||
HTEditorCache()
|
||||
{
|
||||
libil2cppTagPrefix = HTEditorConfig.libil2cppTagPrefixGithub;
|
||||
huatuoTagPrefix = HTEditorConfig.huatuoTagPrefixGithub;
|
||||
}
|
||||
|
||||
public void SetDownloadCount(int count)
|
||||
{
|
||||
m_nDownloadTotal = count;
|
||||
m_counter = 0;
|
||||
m_nSuccessCount = 0;
|
||||
m_nFailedCount = 0;
|
||||
}
|
||||
|
||||
public bool DownloadDone()
|
||||
{
|
||||
return m_nDownloadTotal == m_nFailedCount + m_nSuccessCount;
|
||||
}
|
||||
|
||||
public bool DownloadSuccess()
|
||||
{
|
||||
return m_nDownloadTotal == m_nSuccessCount;
|
||||
}
|
||||
|
||||
public void SetCacheDirectory(string path)
|
||||
{
|
||||
var tmp = "";
|
||||
if (path == null || path.Length == 0)
|
||||
{
|
||||
tmp = Path.Combine(Path.GetFullPath("Library"), CacheDirName);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = path;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(tmp);
|
||||
CacheBasePath = tmp;
|
||||
HTEditorInstaller.Instance.SaveCacheDir();
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
Debug.LogError("缓存设置失败,请不要使用C盘路径做缓存");
|
||||
}
|
||||
}
|
||||
|
||||
public string GetDownUrlWithTagHuatuo(string tag)
|
||||
{
|
||||
return $"{huatuoTagPrefix}/{tag}.zip";
|
||||
}
|
||||
|
||||
public string GetDownUrlWithTagIl2cpp(string tag)
|
||||
{
|
||||
return $"{libil2cppTagPrefix}/{tag}.zip";
|
||||
}
|
||||
|
||||
public string GetZipName(EFILE_NAME nameType, string tag)
|
||||
{
|
||||
var zipFileName = "";
|
||||
switch (nameType)
|
||||
{
|
||||
case EFILE_NAME.HUATUO:
|
||||
zipFileName = $"huatuo-{tag}";
|
||||
break;
|
||||
case EFILE_NAME.IL2CPP:
|
||||
zipFileName = $"il2cpp_huatuo-{tag}";
|
||||
break;
|
||||
default:
|
||||
throw new Exception($"no support file type{nameof(nameType)}");
|
||||
}
|
||||
|
||||
return zipFileName;
|
||||
}
|
||||
public static string GetHuatuoZipInnerFolder(EFILE_NAME nameType, string tag)
|
||||
{
|
||||
switch (nameType)
|
||||
{
|
||||
case EFILE_NAME.HUATUO_MAIN:
|
||||
return $"/huatuo-main/huatuo";
|
||||
case EFILE_NAME.HUATUO:
|
||||
return $"/huatuo-{tag}/huatuo";
|
||||
}
|
||||
return "error param";
|
||||
}
|
||||
public string GetZipPath(EFILE_NAME nameType, string tag)
|
||||
{
|
||||
var zipFileName = "";
|
||||
switch (nameType)
|
||||
{
|
||||
case EFILE_NAME.HUATUO_MAIN:
|
||||
zipFileName = $"huatuo-{tag}";
|
||||
break;
|
||||
case EFILE_NAME.HUATUO:
|
||||
zipFileName = $"huatuo-{tag}";
|
||||
break;
|
||||
case EFILE_NAME.IL2CPP:
|
||||
zipFileName = $"il2cpp_huatuo-{tag}";
|
||||
break;
|
||||
default:
|
||||
throw new Exception($"no support file type{nameof(nameType)}");
|
||||
}
|
||||
|
||||
return Path.Combine(CacheBasePath, $"{zipFileName}.zip");
|
||||
}
|
||||
|
||||
public IEnumerator GetCache(EFILE_NAME nameType, string tag, string hashCode)
|
||||
{
|
||||
m_counter++;
|
||||
var downloadUrl = "";
|
||||
var zipFileName = "";
|
||||
switch (nameType)
|
||||
{
|
||||
case EFILE_NAME.HUATUO_MAIN:
|
||||
zipFileName = $"huatuo-{tag}";
|
||||
downloadUrl = $"{HTEditorConfig.huatuoPrefixGithub}/main.zip";
|
||||
break;
|
||||
case EFILE_NAME.HUATUO:
|
||||
zipFileName = $"huatuo-{tag}";
|
||||
downloadUrl = $"{huatuoTagPrefix}/{tag}.zip";
|
||||
break;
|
||||
case EFILE_NAME.IL2CPP:
|
||||
zipFileName = $"il2cpp_huatuo-{tag}";
|
||||
downloadUrl = $"{libil2cppTagPrefix}/{tag}.zip";
|
||||
break;
|
||||
default:
|
||||
throw new Exception($"no support file type{nameof(nameType)}");
|
||||
}
|
||||
|
||||
var downloadErr = false;
|
||||
var zipPath = Path.Combine(CacheBasePath, $"{zipFileName}.zip");
|
||||
if (File.Exists(zipPath))
|
||||
{
|
||||
// TODO 校验文件MD5
|
||||
Debug.Log($"Download {zipFileName}, use cache file: {zipPath}");
|
||||
yield return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var curRetryCnt = 0;
|
||||
var maxRetryCnt = 0;
|
||||
var itor = HTEditorUtility.DownloadFile(downloadUrl, zipPath,
|
||||
(curCnt, maxCnt) =>
|
||||
{
|
||||
curRetryCnt = curCnt;
|
||||
maxRetryCnt = maxCnt;
|
||||
},
|
||||
p =>
|
||||
{
|
||||
var msg = $"下载中{(curRetryCnt > 0 ? $"[重试{curRetryCnt}/{maxRetryCnt}]" : "...")}";
|
||||
EditorUtility.DisplayProgressBar(msg, $"{m_counter}/{m_nDownloadTotal}", p);
|
||||
},
|
||||
ret =>
|
||||
{
|
||||
EditorUtility.ClearProgressBar();
|
||||
if (!string.IsNullOrEmpty(ret))
|
||||
{
|
||||
downloadErr = true;
|
||||
EditorUtility.DisplayDialog("错误", $"下载{zipFileName}出错.\n{ret}", "ok");
|
||||
}
|
||||
});
|
||||
while (itor.MoveNext())
|
||||
{
|
||||
yield return itor.Current;
|
||||
}
|
||||
|
||||
if (!File.Exists(zipPath))
|
||||
{
|
||||
EditorUtility.DisplayDialog("错误", $"下载的文件{zipPath}不存在", "ok");
|
||||
downloadErr = false;
|
||||
}
|
||||
|
||||
//else if (MD5.ComputeFileMD5(zipPath).ToLower() != hashCode)
|
||||
//{
|
||||
// EditorUtility.DisplayDialog("错误", $"下载的文件{zipPath} hash不匹配,请重新下载", "ok");
|
||||
// downloadErr = false;
|
||||
//}
|
||||
}
|
||||
|
||||
if (downloadErr)
|
||||
{
|
||||
m_nFailedCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nSuccessCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4c3edb7dda7a5d43b76ce5a048e80d2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
50
Assets/TEngine/Runtime/HotUpdate/Editor/HTEditorConfig.cs
Normal file
50
Assets/TEngine/Runtime/HotUpdate/Editor/HTEditorConfig.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace Huatuo.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// 这个类存放各种常量信息
|
||||
/// </summary>
|
||||
public static class HTEditorConfig
|
||||
{
|
||||
public static string UnityFullVersion = "";
|
||||
public static string UnityVersionDigits = "";
|
||||
|
||||
//public static readonly string libil2cppPrefixGitee = "https://gitee.com/juvenior/il2cpp_huatuo/repository/archive";
|
||||
//public static readonly string libil2cppPrefixGithub = "https://github.com/pirunxi/il2cpp_huatuo/archive/refs/heads";
|
||||
//public static readonly string huatuoPrefixGitee = "https://gitee.com/focus-creative-games/huatuo/repository/archive";
|
||||
public static readonly string huatuoPrefixGithub = "https://github.com/focus-creative-games/huatuo/archive/refs/heads/";
|
||||
public static readonly string libil2cppTagPrefixGithub = "https://github.com/pirunxi/il2cpp_huatuo/archive/refs/tags";
|
||||
public static readonly string huatuoTagPrefixGithub = "https://github.com/focus-creative-games/huatuo/archive/refs/tags";
|
||||
public static readonly string urlVersionConfig = "https://focus-creative-games.github.io/huatuo_upm/Doc/version.json";
|
||||
public static readonly string urlHuatuoCommits = "https://api.github.com/repos/focus-creative-games/huatuo/commits";
|
||||
public static readonly string urlHuatuoTags = "https://api.github.com/repos/focus-creative-games/huatuo/tags";
|
||||
|
||||
private static readonly string WebSiteBase = "https://github.com/focus-creative-games/huatuo";
|
||||
public static readonly string WebSite = WebSiteBase;
|
||||
public static readonly string Document = WebSiteBase;
|
||||
public static readonly string Changelog = WebSiteBase;
|
||||
public static readonly string SupportedVersion = WebSiteBase + "/wiki/support_versions";
|
||||
|
||||
private static readonly string EditorBasePath = EditorApplication.applicationContentsPath;
|
||||
public static readonly string HuatuoIL2CPPPath = EditorBasePath + "/il2cpp/libil2cpp";
|
||||
public static readonly string HuatuoIL2CPPBackPath = EditorBasePath + "/il2cpp/libil2cpp_huatuo";
|
||||
public static readonly string Il2cppPath = Path.Combine(EditorBasePath, "il2cpp");
|
||||
public static readonly string Libil2cppPath = Path.Combine(Il2cppPath, "libil2cpp");
|
||||
public static readonly string Libil2cppOritinalPath = Path.Combine(Il2cppPath, "libil2cpp_original_unity");
|
||||
public static readonly string HuatuoPath = Path.Combine(HuatuoIL2CPPPath, "huatuo");
|
||||
|
||||
public static string DownloadCache = "";
|
||||
public static string HuatuoVersionPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, ".huatuo");
|
||||
public static void Init()
|
||||
{
|
||||
UnityFullVersion = InternalEditorUtility.GetFullUnityVersion();
|
||||
UnityVersionDigits = InternalEditorUtility.GetUnityVersionDigits();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4741bd22971475083f91e74c5434f77
|
||||
timeCreated: 1652082272
|
405
Assets/TEngine/Runtime/HotUpdate/Editor/HTEditorInstaller.cs
Normal file
405
Assets/TEngine/Runtime/HotUpdate/Editor/HTEditorInstaller.cs
Normal file
@@ -0,0 +1,405 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Huatuo.Editor
|
||||
{
|
||||
internal class HTEditorInstaller
|
||||
{
|
||||
private static HTEditorInstaller instance = null;
|
||||
|
||||
public static HTEditorInstaller Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new HTEditorInstaller();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
HTEditorInstaller()
|
||||
{
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
if (File.Exists(HTEditorConfig.HuatuoVersionPath))
|
||||
{
|
||||
var data = File.ReadAllText(HTEditorConfig.HuatuoVersionPath, Encoding.UTF8);
|
||||
m_HuatuoVersion = JsonUtility.FromJson<HuatuoVersion>(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_HuatuoVersion = default;
|
||||
}
|
||||
|
||||
HTEditorCache.Instance.SetCacheDirectory(m_HuatuoVersion.CacheDir);
|
||||
}
|
||||
|
||||
public void DoUninstall()
|
||||
{
|
||||
// backup libil2cpp
|
||||
if (Directory.Exists(HTEditorConfig.Libil2cppOritinalPath))
|
||||
{
|
||||
if (Directory.Exists(HTEditorConfig.Libil2cppPath))
|
||||
{
|
||||
Directory.Delete(HTEditorConfig.Libil2cppPath, true);
|
||||
}
|
||||
|
||||
Directory.Move(HTEditorConfig.Libil2cppOritinalPath, HTEditorConfig.Libil2cppPath);
|
||||
}
|
||||
|
||||
m_InstallVersion.huatuoTag = "";
|
||||
m_InstallVersion.il2cppTag = "";
|
||||
SaveVersionLog();
|
||||
// 不存在原始备份目录
|
||||
// TODO 这里考虑下是否帮用户下载libil2cpp
|
||||
}
|
||||
|
||||
public static void Enable(Action<string> callback)
|
||||
{
|
||||
var mv1 = HTEditorUtility.Mv(HTEditorConfig.Libil2cppPath, HTEditorConfig.Libil2cppOritinalPath);
|
||||
if (!string.IsNullOrEmpty(mv1))
|
||||
{
|
||||
Debug.LogError(mv1);
|
||||
callback?.Invoke(mv1);
|
||||
return;
|
||||
}
|
||||
|
||||
mv1 = HTEditorUtility.Mv(HTEditorConfig.HuatuoIL2CPPBackPath, HTEditorConfig.HuatuoIL2CPPPath);
|
||||
if (!string.IsNullOrEmpty(mv1))
|
||||
{
|
||||
Debug.LogError(mv1);
|
||||
callback?.Invoke(mv1);
|
||||
return;
|
||||
}
|
||||
|
||||
callback?.Invoke(null);
|
||||
}
|
||||
|
||||
public static void Disable(Action<string> callback)
|
||||
{
|
||||
var mv1 = HTEditorUtility.Mv(HTEditorConfig.HuatuoIL2CPPPath, HTEditorConfig.HuatuoIL2CPPBackPath);
|
||||
if (!string.IsNullOrEmpty(mv1))
|
||||
{
|
||||
Debug.LogError(mv1);
|
||||
callback?.Invoke(mv1);
|
||||
return;
|
||||
}
|
||||
|
||||
mv1 = HTEditorUtility.Mv(HTEditorConfig.Libil2cppOritinalPath, HTEditorConfig.Libil2cppPath);
|
||||
if (!string.IsNullOrEmpty(mv1))
|
||||
{
|
||||
Debug.LogError(mv1);
|
||||
callback?.Invoke(mv1);
|
||||
return;
|
||||
}
|
||||
|
||||
callback?.Invoke(null);
|
||||
}
|
||||
|
||||
public static void Uninstall(Action<string> callback)
|
||||
{
|
||||
Disable(ret =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ret))
|
||||
{
|
||||
callback?.Invoke(ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Directory.Exists(HTEditorConfig.HuatuoIL2CPPBackPath))
|
||||
{
|
||||
Directory.Delete(HTEditorConfig.HuatuoIL2CPPBackPath, true);
|
||||
}
|
||||
|
||||
callback?.Invoke(null);
|
||||
});
|
||||
}
|
||||
|
||||
public InstallVersion m_InstallVersion; // 当前安装临时使用的版本数据
|
||||
public HuatuoVersion m_HuatuoVersion; // 已安装的版本信息
|
||||
|
||||
private bool m_bDoBackup;
|
||||
private string m_sBackupFileName;
|
||||
|
||||
private IEnumerator Extract(Action<bool> callback)
|
||||
{
|
||||
var il2cppZip = HTEditorCache.Instance.GetZipPath(EFILE_NAME.IL2CPP, m_InstallVersion.il2cppTag);
|
||||
var huatuozip = HTEditorCache.Instance.GetZipPath(m_InstallVersion.huatuoType, m_InstallVersion.huatuoTag);
|
||||
|
||||
var il2cppCachePath = Path.GetDirectoryName(il2cppZip) + $"/il2cpp_huatuo-{m_InstallVersion.il2cppTag}";
|
||||
var huatuoCachePath = Path.GetDirectoryName(huatuozip) + $"/huatuo-{m_InstallVersion.huatuoTag}";
|
||||
|
||||
var cnt = 0;
|
||||
var haserr = false;
|
||||
var itor = HTEditorUtility.UnzipAsync(il2cppZip, il2cppCachePath, b => { cnt = b; },
|
||||
p => { EditorUtility.DisplayProgressBar("解压中...", $"il2cpp:{p}/{cnt}", (float) p / cnt); }, null,
|
||||
() => { haserr = true; });
|
||||
while (itor.MoveNext())
|
||||
{
|
||||
yield return itor.Current;
|
||||
}
|
||||
EditorUtility.ClearProgressBar();
|
||||
|
||||
if (haserr)
|
||||
{
|
||||
callback?.Invoke(true);
|
||||
yield break;
|
||||
}
|
||||
|
||||
cnt = 0;
|
||||
itor = HTEditorUtility.UnzipAsync(huatuozip, huatuoCachePath, b => { cnt = b; },
|
||||
p => { EditorUtility.DisplayProgressBar("解压中...", $"huatuo:{p}/{cnt}", (float) p / cnt); }, null,
|
||||
() => { haserr = true; });
|
||||
while (itor.MoveNext())
|
||||
{
|
||||
yield return itor.Current;
|
||||
}
|
||||
|
||||
EditorUtility.ClearProgressBar();
|
||||
|
||||
if (haserr)
|
||||
{
|
||||
callback?.Invoke(true);
|
||||
yield break;
|
||||
}
|
||||
|
||||
var il2cppDirName = il2cppCachePath + $"/il2cpp_huatuo-{m_InstallVersion.il2cppTag}/libil2cpp";
|
||||
var huatuoDirName = huatuoCachePath + HTEditorCache.GetHuatuoZipInnerFolder(m_InstallVersion.huatuoType, m_InstallVersion.huatuoTag);
|
||||
if (!Directory.Exists(il2cppDirName))
|
||||
{
|
||||
Debug.LogError($"{il2cppDirName} not exists!!!");
|
||||
callback?.Invoke(true);
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (!Directory.Exists(huatuoDirName))
|
||||
{
|
||||
Debug.LogError($"{huatuoDirName} not exists!!!");
|
||||
callback?.Invoke(true);
|
||||
yield break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(HTEditorConfig.Libil2cppPath))
|
||||
{
|
||||
Directory.Delete(HTEditorConfig.Libil2cppPath, true);
|
||||
}
|
||||
|
||||
HTEditorUtility.CopyFilesRecursively(il2cppDirName, HTEditorConfig.HuatuoIL2CPPPath);
|
||||
HTEditorUtility.CopyFilesRecursively(huatuoDirName, HTEditorConfig.HuatuoPath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogException(ex);
|
||||
haserr = true;
|
||||
}
|
||||
|
||||
callback?.Invoke(haserr);
|
||||
}
|
||||
|
||||
public IEnumerator Install(InstallVersion installVersion, Action<bool> callback)
|
||||
{
|
||||
this.m_InstallVersion = installVersion;
|
||||
|
||||
Debug.Log("备份il2cpp目录");
|
||||
var task = Task.Run(BackupLibil2cpp);
|
||||
while (!task.IsCompleted)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
var hasErr = false;
|
||||
var itor = Extract(r => { hasErr = r; });
|
||||
while (itor.MoveNext())
|
||||
{
|
||||
yield return itor.Current;
|
||||
}
|
||||
|
||||
if (hasErr)
|
||||
{
|
||||
RevertInstall();
|
||||
callback?.Invoke(false);
|
||||
yield break;
|
||||
}
|
||||
|
||||
task = Task.Run(SaveVersionLog);
|
||||
while (!task.IsCompleted)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
task = Task.Run(DelBackupLibil2cpp);
|
||||
while (!task.IsCompleted)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
callback?.Invoke(true);
|
||||
}
|
||||
|
||||
public void RevertInstall()
|
||||
{
|
||||
m_InstallVersion.huatuoTag = m_HuatuoVersion.HuatuoTag;
|
||||
m_InstallVersion.il2cppTag = m_HuatuoVersion.Il2cppTag;
|
||||
if (!m_bDoBackup)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string installPathBak = Path.Combine(HTEditorConfig.Il2cppPath, m_sBackupFileName);
|
||||
// backup libil2cpp
|
||||
if (Directory.Exists(installPathBak))
|
||||
{
|
||||
Directory.Delete(HTEditorConfig.Libil2cppPath, true);
|
||||
Directory.Move(installPathBak, HTEditorConfig.Libil2cppPath);
|
||||
}
|
||||
}
|
||||
|
||||
public void DelBackupLibil2cpp()
|
||||
{
|
||||
if (!m_bDoBackup)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string installPathBak = Path.Combine(HTEditorConfig.Il2cppPath, m_sBackupFileName);
|
||||
// backup libil2cpp
|
||||
if (Directory.Exists(installPathBak))
|
||||
{
|
||||
Directory.Delete(installPathBak, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void BackupLibil2cpp()
|
||||
{
|
||||
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
|
||||
m_sBackupFileName = $"libil2cpp_{ts.TotalSeconds}";
|
||||
string installPathBak = Path.Combine(HTEditorConfig.Il2cppPath, m_sBackupFileName);
|
||||
string original = Path.Combine(HTEditorConfig.Il2cppPath, "libil2cpp_original_unity");
|
||||
|
||||
if (!Directory.Exists(HTEditorConfig.Libil2cppPath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// backup libil2cpp original
|
||||
if (!Directory.Exists(original))
|
||||
{
|
||||
Directory.Move(HTEditorConfig.Libil2cppPath, original);
|
||||
}
|
||||
|
||||
if (Directory.Exists(HTEditorConfig.Libil2cppPath))
|
||||
{
|
||||
m_bDoBackup = true;
|
||||
Directory.Move(HTEditorConfig.Libil2cppPath, installPathBak);
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveVersionLog()
|
||||
{
|
||||
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
|
||||
|
||||
// TODO 记录libil2cpp 和 huatuo 版本信息
|
||||
m_HuatuoVersion.HuatuoTag = m_InstallVersion.huatuoTag;
|
||||
m_HuatuoVersion.Il2cppTag = m_InstallVersion.il2cppTag;
|
||||
//m_HuatuoVersion.Il2cppUrl = HTEditorCache.Instance.GetDownUrlWithTagIl2cpp(m_InstallVersion.il2cppTag);
|
||||
//m_HuatuoVersion.HuatuoUrl = HTEditorCache.Instance.GetDownUrlWithTagHuatuo(m_InstallVersion.huatuoTag);
|
||||
m_HuatuoVersion.InstallTime = DateTime.Now.ToString();
|
||||
m_HuatuoVersion.Timestamp = Convert.ToInt64(ts.TotalMilliseconds);
|
||||
Debug.Log($"Save huatuo install version, path: {HTEditorConfig.HuatuoVersionPath}");
|
||||
File.WriteAllText(HTEditorConfig.HuatuoVersionPath, JsonUtility.ToJson(m_HuatuoVersion, true),
|
||||
Encoding.UTF8);
|
||||
}
|
||||
|
||||
public void SaveCacheDir()
|
||||
{
|
||||
m_HuatuoVersion.CacheDir = HTEditorCache.Instance.CacheBasePath;
|
||||
File.WriteAllText(HTEditorConfig.HuatuoVersionPath, JsonUtility.ToJson(m_HuatuoVersion, true),
|
||||
Encoding.UTF8);
|
||||
}
|
||||
|
||||
/*
|
||||
public static HuatuoRemoteConfig GetVersionData()
|
||||
{
|
||||
var data = File.ReadAllText(HTEditorConfig.HuatuoVersionPath, Encoding.UTF8);
|
||||
return JsonUtility.FromJson<HuatuoRemoteConfig>(data);
|
||||
}
|
||||
|
||||
public static bool Extract(string zipPath, string extractDir, string installPath)
|
||||
{
|
||||
var result = ExtractZip(zipPath, extractDir, installPath);
|
||||
return result.Count > 0;
|
||||
}
|
||||
|
||||
public static List<string> ExtractZip(string zipFilePath, string relativePath, string destPath)
|
||||
{
|
||||
var result = new List<string>();
|
||||
|
||||
relativePath = relativePath.Replace(@"\", @"/");
|
||||
|
||||
using (FileStream zipToOpen = new FileStream(zipFilePath, FileMode.Open))
|
||||
{
|
||||
using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Read))
|
||||
{
|
||||
var entry = archive.Entries.FirstOrDefault(x => x.FullName.ToUpper() == relativePath.ToUpper());
|
||||
if (entry == null)
|
||||
entry = archive.Entries.FirstOrDefault(x =>
|
||||
x.FullName.ToUpper() == (relativePath + "/").ToUpper());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(entry.Name))
|
||||
{
|
||||
var path = Path.Combine(destPath, entry.Name);
|
||||
using (var file = new FileStream(path, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
entry.Open().CopyTo(file);
|
||||
file.Close();
|
||||
}
|
||||
|
||||
result.Add(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
var items = archive.Entries.Where(x => x.FullName.StartsWith(entry.FullName)).ToList();
|
||||
foreach (var item in items.Where(x => string.IsNullOrWhiteSpace(x.Name)).OrderBy(x => x.Length))
|
||||
{
|
||||
var path = Path.Combine(destPath, item.FullName.Substring(entry.FullName.Length));
|
||||
if (!Directory.Exists(path))
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
foreach (var item in items.Where(x => !string.IsNullOrWhiteSpace(x.Name))
|
||||
.OrderBy(x => x.Length))
|
||||
{
|
||||
var path = new FileInfo(Path.Combine(destPath,
|
||||
item.FullName.Substring(entry.FullName.Length))).Directory.FullName;
|
||||
path = Path.Combine(path, item.Name);
|
||||
using (var file = new FileStream(path, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
item.Open().CopyTo(file);
|
||||
file.Close();
|
||||
}
|
||||
|
||||
result.Add(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}*/
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b59a820a925dfaa4cad33934824d7a5d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user