mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
Compare commits
69 Commits
TEngine6.0
...
Unity6000
Author | SHA1 | Date | |
---|---|---|---|
![]() |
745efad95a | ||
![]() |
dc27547eeb | ||
![]() |
780766e2f0 | ||
![]() |
cc799ce426 | ||
![]() |
35a9729930 | ||
![]() |
0e34c99398 | ||
![]() |
240da47fc3 | ||
![]() |
04109a43b6 | ||
![]() |
bc82685ec7 | ||
![]() |
1894cd4d72 | ||
![]() |
4c903e8da5 | ||
![]() |
03aabf6b08 | ||
![]() |
c1d9fe5ca7 | ||
![]() |
122b5b27ad | ||
![]() |
9a8de43e95 | ||
![]() |
06d826d4b2 | ||
![]() |
afd0c6a24e | ||
![]() |
7f9dddaec0 | ||
![]() |
d97538481e | ||
![]() |
c72ef8e197 | ||
![]() |
7c9393051c | ||
![]() |
e4c3247546 | ||
![]() |
6e9d23b2dc | ||
![]() |
eae827a600 | ||
![]() |
f916adb71b | ||
![]() |
227283864f | ||
![]() |
32418326b1 | ||
![]() |
6570f87074 | ||
![]() |
81b00ae913 | ||
![]() |
322aaa0a46 | ||
![]() |
8f5b1b2117 | ||
![]() |
54a4c55f3c | ||
![]() |
e37c066f9f | ||
![]() |
b1d06ecef5 | ||
![]() |
27ce7e8ecc | ||
![]() |
8b715ffc8e | ||
![]() |
e8fa910f1f | ||
![]() |
3b3bc7822a | ||
![]() |
3c662e489e | ||
![]() |
5cebc82ba1 | ||
![]() |
5cb72e0b08 | ||
![]() |
500e012f2e | ||
![]() |
82332ba5b4 | ||
![]() |
55a6ab1ffb | ||
![]() |
24313b61ab | ||
![]() |
876b36b3b9 | ||
![]() |
2a62a1f320 | ||
![]() |
b6e6c1c423 | ||
![]() |
230f6a0be5 | ||
![]() |
25ca5f3f2b | ||
![]() |
66c5a41be5 | ||
![]() |
61ba472346 | ||
![]() |
9ce4fb9d88 | ||
![]() |
e405236d4d | ||
![]() |
2e27941755 | ||
![]() |
14bbb993f8 | ||
![]() |
0ba9d1a8b7 | ||
![]() |
2818edb575 | ||
![]() |
5210c1d36b | ||
![]() |
cdc7a8f688 | ||
![]() |
c20f8285d8 | ||
![]() |
f2a63978da | ||
![]() |
36db2f3aba | ||
![]() |
61b2baeaf7 | ||
![]() |
7aab91215c | ||
![]() |
4ae417337b | ||
![]() |
52ac77d5e4 | ||
![]() |
515d55e19a | ||
![]() |
a4221e36f8 |
29
Configs/GameConfig/CustomTemplate/ExternalTypeUtil.cs
Normal file
29
Configs/GameConfig/CustomTemplate/ExternalTypeUtil.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using UnityEngine;
|
||||
|
||||
public static class ExternalTypeUtil
|
||||
{
|
||||
public static Vector2 NewVector2(GameConfig.vector2 v)
|
||||
{
|
||||
return new Vector2(v.X, v.Y);
|
||||
}
|
||||
|
||||
public static Vector3 NewVector3(GameConfig.vector3 v)
|
||||
{
|
||||
return new Vector3(v.X, v.Y, v.Z);
|
||||
}
|
||||
|
||||
public static Vector4 NewVector4(GameConfig.vector4 v)
|
||||
{
|
||||
return new Vector4(v.X, v.Y, v.Z, v.W);
|
||||
}
|
||||
|
||||
public static Vector2Int NewVector2Int(GameConfig.vector2int v)
|
||||
{
|
||||
return new Vector2Int(v.X, v.Y);
|
||||
}
|
||||
|
||||
public static Vector3Int NewVector3Int(GameConfig.vector3int v)
|
||||
{
|
||||
return new Vector3Int(v.X, v.Y, v.Z);
|
||||
}
|
||||
}
|
@@ -1,17 +1,46 @@
|
||||
<module name="">
|
||||
<bean name="vector2" valueType="1" sep=",">
|
||||
<var name="x" type="float"/>
|
||||
<var name="y" type="float"/>
|
||||
<var name="x" type="float" />
|
||||
<var name="y" type="float" />
|
||||
<mapper target="client" codeTarget="cs-bin,cs-simple-json,cs-newtonsoft-json">
|
||||
<option name="type" value="UnityEngine.Vector2" />
|
||||
<option name="constructor" value="ExternalTypeUtil.NewVector2" />
|
||||
</mapper>
|
||||
</bean>
|
||||
<bean name="vector3" valueType="1" sep=",">
|
||||
<var name="x" type="float"/>
|
||||
<var name="y" type="float"/>
|
||||
<var name="z" type="float"/>
|
||||
<var name="x" type="float" />
|
||||
<var name="y" type="float" />
|
||||
<var name="z" type="float" />
|
||||
<mapper target="client" codeTarget="cs-bin,cs-simple-json,cs-newtonsoft-json">
|
||||
<option name="type" value="UnityEngine.Vector3" />
|
||||
<option name="constructor" value="ExternalTypeUtil.NewVector3" />
|
||||
</mapper>
|
||||
</bean>
|
||||
<bean name="vector4" valueType="1" sep=",">
|
||||
<var name="x" type="float"/>
|
||||
<var name="y" type="float"/>
|
||||
<var name="z" type="float"/>
|
||||
<var name="w" type="float"/>
|
||||
<var name="x" type="float" />
|
||||
<var name="y" type="float" />
|
||||
<var name="z" type="float" />
|
||||
<var name="w" type="float" />
|
||||
<mapper target="client" codeTarget="cs-bin,cs-simple-json,cs-newtonsoft-json">
|
||||
<option name="type" value="UnityEngine.Vector4" />
|
||||
<option name="constructor" value="ExternalTypeUtil.NewVector4" />
|
||||
</mapper>
|
||||
</bean>
|
||||
<bean name="vector2int" valueType="1" sep=",">
|
||||
<var name="x" type="int" />
|
||||
<var name="y" type="int" />
|
||||
<mapper target="client" codeTarget="cs-bin,cs-simple-json,cs-newtonsoft-json">
|
||||
<option name="type" value="UnityEngine.Vector2Int" />
|
||||
<option name="constructor" value="ExternalTypeUtil.NewVector2Int" />
|
||||
</mapper>
|
||||
</bean>
|
||||
<bean name="vector3int" valueType="1" sep=",">
|
||||
<var name="x" type="int" />
|
||||
<var name="y" type="int" />
|
||||
<var name="z" type="int" />
|
||||
<mapper target="client" codeTarget="cs-bin,cs-simple-json,cs-newtonsoft-json">
|
||||
<option name="type" value="UnityEngine.Vector3" />
|
||||
<option name="constructor" value="ExternalTypeUtil.NewVector3" />
|
||||
</mapper>
|
||||
</bean>
|
||||
</module>
|
@@ -8,12 +8,14 @@ set DATA_OUTPATH=%WORKSPACE%/UnityProject/Assets/AssetRaw/Configs/bytes/
|
||||
set CODE_OUTPATH=%WORKSPACE%/UnityProject/Assets/GameScripts/HotFix/GameProto/GameConfig/
|
||||
|
||||
xcopy /s /e /i /y "%CONF_ROOT%\CustomTemplate\ConfigSystem.cs" "%WORKSPACE%\UnityProject\Assets\GameScripts\HotFix\GameProto\ConfigSystem.cs"
|
||||
xcopy /s /e /i /y "%CONF_ROOT%\CustomTemplate\ExternalTypeUtil.cs" "%WORKSPACE%\UnityProject\Assets\GameScripts\HotFix\GameProto\ExternalTypeUtil.cs"
|
||||
|
||||
dotnet %LUBAN_DLL% ^
|
||||
-t client ^
|
||||
-c cs-bin ^
|
||||
-d bin^
|
||||
--conf %CONF_ROOT%\luban.conf ^
|
||||
-x code.lineEnding=crlf ^
|
||||
-x outputCodeDir=%CODE_OUTPATH% ^
|
||||
-x outputDataDir=%DATA_OUTPATH%
|
||||
pause
|
||||
|
@@ -11,12 +11,15 @@ export CODE_OUTPATH="${WORKSPACE}/UnityProject/Assets/GameScripts/HotFix/GamePro
|
||||
|
||||
cp -R "${CONF_ROOT}/CustomTemplate/ConfigSystem.cs" \
|
||||
"${WORKSPACE}/UnityProject/Assets/GameScripts/HotFix/GameProto/ConfigSystem.cs"
|
||||
cp -R "${CONF_ROOT}/CustomTemplate/ExternalTypeUtil.cs" \
|
||||
"${WORKSPACE}/UnityProject/Assets/GameScripts/HotFix/GameProto/ExternalTypeUtil.cs"
|
||||
|
||||
dotnet "${LUBAN_DLL}" \
|
||||
-t client \
|
||||
-c cs-bin \
|
||||
-d bin \
|
||||
--conf "${CONF_ROOT}/luban.conf" \
|
||||
-x code.lineEnding=crlf \
|
||||
-x outputCodeDir="${CODE_OUTPATH}" \
|
||||
-x outputDataDir="${DATA_OUTPATH}"
|
||||
|
||||
|
@@ -8,6 +8,7 @@ set DATA_OUTPATH=%WORKSPACE%/UnityProject/Assets/AssetRaw/Configs/bytes/
|
||||
set CODE_OUTPATH=%WORKSPACE%/UnityProject/Assets/GameScripts/HotFix/GameProto/GameConfig/
|
||||
|
||||
xcopy /s /e /i /y "%CONF_ROOT%\CustomTemplate\ConfigSystem.cs" "%WORKSPACE%\UnityProject\Assets\GameScripts\HotFix\GameProto\ConfigSystem.cs"
|
||||
xcopy /s /e /i /y "%CONF_ROOT%\CustomTemplate\ExternalTypeUtil.cs" "%WORKSPACE%\UnityProject\Assets\GameScripts\HotFix\GameProto\ExternalTypeUtil.cs"
|
||||
|
||||
dotnet %LUBAN_DLL% ^
|
||||
-t client ^
|
||||
@@ -15,6 +16,7 @@ dotnet %LUBAN_DLL% ^
|
||||
-d bin^
|
||||
--conf %CONF_ROOT%\luban.conf ^
|
||||
--customTemplateDir %CONF_ROOT%\CustomTemplate\CustomTemplate_Client_LazyLoad ^
|
||||
-x code.lineEnding=crlf ^
|
||||
-x outputCodeDir=%CODE_OUTPATH% ^
|
||||
-x outputDataDir=%DATA_OUTPATH%
|
||||
pause
|
||||
|
@@ -11,6 +11,8 @@ export CODE_OUTPATH="${WORKSPACE}/UnityProject/Assets/GameScripts/HotFix/GamePro
|
||||
|
||||
cp -R "${CONF_ROOT}/CustomTemplate/ConfigSystem.cs" \
|
||||
"${WORKSPACE}/UnityProject/Assets/GameScripts/HotFix/GameProto/ConfigSystem.cs"
|
||||
cp -R "${CONF_ROOT}/CustomTemplate/ExternalTypeUtil.cs" \
|
||||
"${WORKSPACE}/UnityProject/Assets/GameScripts/HotFix/GameProto/ExternalTypeUtil.cs"
|
||||
|
||||
dotnet "${LUBAN_DLL}" \
|
||||
-t client \
|
||||
@@ -18,6 +20,7 @@ dotnet "${LUBAN_DLL}" \
|
||||
-d bin \
|
||||
--conf "${CONF_ROOT}/luban.conf" \
|
||||
--customTemplateDir "${CONF_ROOT}/CustomTemplate/CustomTemplate_Client_LazyLoad" \
|
||||
-x code.lineEnding=crlf \
|
||||
-x outputCodeDir="${CODE_OUTPATH}" \
|
||||
-x outputDataDir="${DATA_OUTPATH}"
|
||||
|
||||
|
@@ -12,6 +12,7 @@ dotnet %LUBAN_DLL% ^
|
||||
-c cs-bin ^
|
||||
-d bin^
|
||||
--conf %CONF_ROOT%\luban.conf ^
|
||||
-x code.lineEnding=crlf ^
|
||||
-x outputCodeDir=%CODE_OUTPATH% ^
|
||||
-x outputDataDir=%DATA_OUTPATH%
|
||||
pause
|
||||
|
@@ -14,6 +14,7 @@ dotnet "${LUBAN_DLL}" \
|
||||
-c cs-bin \
|
||||
-d bin \
|
||||
--conf "${CONF_ROOT}/luban.conf" \
|
||||
-x code.lineEnding=crlf \
|
||||
-x outputCodeDir="${CODE_OUTPATH}" \
|
||||
-x outputDataDir="${DATA_OUTPATH}"
|
||||
|
||||
|
Binary file not shown.
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: caf4d6b8aba38514fa2d00c93b086073
|
||||
guid: cace8d5078f400048a8afde10e2bf41d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
@@ -0,0 +1,36 @@
|
||||
using TEngine;
|
||||
using UnityEditor;
|
||||
|
||||
public static class TEngineSettingsProvider
|
||||
{
|
||||
[MenuItem("TEngine/Settings/TEngine UpdateSettings", priority = -1)]
|
||||
public static void OpenSettings() => SettingsService.OpenProjectSettings("Project/TEngine/UpdateSettings");
|
||||
|
||||
private const string SettingsPath = "Project/TEngine/UpdateSettings";
|
||||
|
||||
[SettingsProvider]
|
||||
public static SettingsProvider CreateMySettingsProvider()
|
||||
{
|
||||
return new SettingsProvider(SettingsPath, SettingsScope.Project)
|
||||
{
|
||||
label = "TEngine/UpdateSettings",
|
||||
guiHandler = (searchContext) =>
|
||||
{
|
||||
var settings = Settings.UpdateSetting;
|
||||
var serializedObject = new SerializedObject(settings);
|
||||
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("projectName"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("HotUpdateAssemblies"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("AOTMetaAssemblies"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("LogicMainDllName"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("AssemblyTextAssetExtension"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("AssemblyTextAssetPath"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("UpdateStyle"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("ResDownLoadPath"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("FallbackResDownLoadPath"));
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
},
|
||||
keywords = new[] { "TEngine", "Settings", "Custom" }
|
||||
};
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 56ea224b45d314e4a86b558404e9b6c8
|
||||
guid: f1c738d23f551c84e9e12af687389aeb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
@@ -0,0 +1,32 @@
|
||||
using TEngine.Editor.UI;
|
||||
using UnityEditor;
|
||||
|
||||
public static class TEngineUISettingsProvider
|
||||
{
|
||||
[MenuItem("TEngine/Settings/TEngineUISettings", priority = -1)]
|
||||
public static void OpenSettings() => SettingsService.OpenProjectSettings("Project/TEngine/UISettings");
|
||||
|
||||
private const string SettingsPath = "Project/TEngine/UISettings";
|
||||
|
||||
[SettingsProvider]
|
||||
public static SettingsProvider CreateMySettingsProvider()
|
||||
{
|
||||
return new SettingsProvider(SettingsPath, SettingsScope.Project)
|
||||
{
|
||||
label = "TEngine/UISettings",
|
||||
guiHandler = (searchContext) =>
|
||||
{
|
||||
var scriptGeneratorSetting = ScriptGeneratorSetting.Instance;
|
||||
var scriptGenerator = new SerializedObject(scriptGeneratorSetting);
|
||||
|
||||
EditorGUILayout.PropertyField(scriptGenerator.FindProperty("_codePath"));
|
||||
EditorGUILayout.PropertyField(scriptGenerator.FindProperty("_namespace"));
|
||||
EditorGUILayout.PropertyField(scriptGenerator.FindProperty("_widgetName"));
|
||||
EditorGUILayout.PropertyField(scriptGenerator.FindProperty("CodeStyle"));
|
||||
EditorGUILayout.PropertyField(scriptGenerator.FindProperty("scriptGenerateRule"));
|
||||
scriptGenerator.ApplyModifiedProperties();
|
||||
},
|
||||
keywords = new[] { "TEngine", "Settings", "Custom" }
|
||||
};
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2672376ad13242bcb6869e90c4def052
|
||||
timeCreated: 1742814408
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b826e89349869884994512ad083e53cc
|
||||
guid: 2982073ed28ef744e96be44c7f55f5f7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
@@ -67,10 +67,8 @@ namespace TEngine
|
||||
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
|
||||
{
|
||||
// GUILayout.Label("资源加载模式:",ToolbarStyles.ToolBarTextStyle);
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
//GUILayout.Space(10);
|
||||
//GUILayout.FlexibleSpace();
|
||||
|
||||
// 资源模式
|
||||
int selectedIndex = EditorGUILayout.Popup("", _resourceModeIndex, _resourceModeNames, ToolbarStyles.ToolBarButtonGuiStyle);
|
||||
@@ -81,10 +79,8 @@ namespace TEngine
|
||||
_resourceModeIndex = selectedIndex;
|
||||
EditorPrefs.SetInt("EditorPlayMode", selectedIndex);
|
||||
}
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
GUILayout.Space(400);
|
||||
//GUILayout.FlexibleSpace();
|
||||
//GUILayout.Space(400);
|
||||
}
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
@@ -0,0 +1,126 @@
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityToolbarExtender;
|
||||
|
||||
namespace TEngine.SceneLauncher
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
public class SceneSwitchLeftButton
|
||||
{
|
||||
private const string PreviousSceneKey = "TEngine_PreviousScenePath"; // 用于存储之前场景路径的键
|
||||
private const string IsLauncherBtn = "TEngine_IsLauncher"; // 用于存储之前是否按下launcher
|
||||
|
||||
private static readonly string SceneMain = "main";
|
||||
|
||||
private static readonly string ButtonStyleName = "Tab middle";
|
||||
private static GUIStyle _buttonGuiStyle;
|
||||
|
||||
static SceneSwitchLeftButton()
|
||||
{
|
||||
ToolbarExtender.LeftToolbarGUI.Add(OnToolbarGUI);
|
||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||
EditorApplication.quitting += OnEditorQuit;
|
||||
}
|
||||
|
||||
private static void OnToolbarGUI()
|
||||
{
|
||||
_buttonGuiStyle ??= new GUIStyle(ButtonStyleName)
|
||||
{
|
||||
padding = new RectOffset(2, 8, 2, 2),
|
||||
alignment = TextAnchor.MiddleCenter,
|
||||
fontStyle = FontStyle.Bold
|
||||
};
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
if (GUILayout.Button(
|
||||
new GUIContent("Launcher", EditorGUIUtility.FindTexture("PlayButton"), "Start Scene Launcher"),
|
||||
_buttonGuiStyle))
|
||||
SceneHelper.StartScene(SceneMain);
|
||||
}
|
||||
|
||||
private static void OnPlayModeStateChanged(PlayModeStateChange state)
|
||||
{
|
||||
if (state == PlayModeStateChange.EnteredEditMode)
|
||||
{
|
||||
// 从 EditorPrefs 读取之前的场景路径
|
||||
var previousScenePath = EditorPrefs.GetString(PreviousSceneKey, string.Empty);
|
||||
if (!string.IsNullOrEmpty(previousScenePath) && EditorPrefs.GetBool(IsLauncherBtn))
|
||||
{
|
||||
EditorApplication.delayCall += () =>
|
||||
{
|
||||
if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
|
||||
EditorSceneManager.OpenScene(previousScenePath);
|
||||
};
|
||||
}
|
||||
|
||||
EditorPrefs.SetBool(IsLauncherBtn, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnEditorQuit()
|
||||
{
|
||||
EditorPrefs.SetString(PreviousSceneKey, "");
|
||||
EditorPrefs.SetBool(IsLauncherBtn, false);
|
||||
}
|
||||
|
||||
private static class SceneHelper
|
||||
{
|
||||
private static string _sceneToOpen;
|
||||
|
||||
public static void StartScene(string sceneName)
|
||||
{
|
||||
if (EditorApplication.isPlaying) EditorApplication.isPlaying = false;
|
||||
|
||||
// 记录当前场景路径到 EditorPrefs
|
||||
var activeScene = SceneManager.GetActiveScene();
|
||||
if (activeScene.isLoaded && activeScene.name != SceneMain)
|
||||
{
|
||||
EditorPrefs.SetString(PreviousSceneKey, activeScene.path);
|
||||
EditorPrefs.SetBool(IsLauncherBtn, true);
|
||||
}
|
||||
|
||||
_sceneToOpen = sceneName;
|
||||
EditorApplication.update += OnUpdate;
|
||||
}
|
||||
|
||||
private static void OnUpdate()
|
||||
{
|
||||
if (_sceneToOpen == null ||
|
||||
EditorApplication.isPlaying || EditorApplication.isPaused ||
|
||||
EditorApplication.isCompiling || EditorApplication.isPlayingOrWillChangePlaymode)
|
||||
return;
|
||||
|
||||
EditorApplication.update -= OnUpdate;
|
||||
|
||||
if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
|
||||
{
|
||||
string[] guids = AssetDatabase.FindAssets("t:scene " + _sceneToOpen, null);
|
||||
if (guids.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("Couldn't find scene file");
|
||||
}
|
||||
else
|
||||
{
|
||||
string scenePath = null;
|
||||
// 优先打开完全匹配_sceneToOpen的场景
|
||||
for (var i = 0; i < guids.Length; i++)
|
||||
{
|
||||
scenePath = AssetDatabase.GUIDToAssetPath(guids[i]);
|
||||
if (scenePath.EndsWith("/" + _sceneToOpen + ".unity")) break;
|
||||
}
|
||||
|
||||
// 如果没有完全匹配的场景,默认显示找到的第一个场景
|
||||
if (string.IsNullOrEmpty(scenePath)) scenePath = AssetDatabase.GUIDToAssetPath(guids[0]);
|
||||
|
||||
EditorSceneManager.OpenScene(scenePath);
|
||||
EditorApplication.isPlaying = true;
|
||||
}
|
||||
}
|
||||
|
||||
_sceneToOpen = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2f6d2ca3d3b34950a79294e49dd9d016
|
||||
timeCreated: 1742389721
|
@@ -0,0 +1,115 @@
|
||||
#if UNITY_EDITOR
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEditor.SceneManagement;
|
||||
|
||||
namespace UnityToolbarExtender.Examples
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
public sealed class SceneSwitchLeftButton
|
||||
{
|
||||
private static List<(string sceneName, string scenePath)> m_Scenes;
|
||||
private static string[] m_SceneName;
|
||||
private static string[] m_ScenePath;
|
||||
private static int sceneSelected = 0;
|
||||
|
||||
static SceneSwitchLeftButton()
|
||||
{
|
||||
EditorApplication.projectChanged += UpdateCurrent;
|
||||
UpdateCurrent();
|
||||
ToolbarExtender.RightToolbarGUI.Add(OnToolbarGUI);
|
||||
}
|
||||
|
||||
static void UpdateCurrent()
|
||||
{
|
||||
m_Scenes = SceneSwitcher.GetAllScenesInProject();
|
||||
m_SceneName = new string[m_Scenes.Count];
|
||||
m_ScenePath = new string[m_Scenes.Count];
|
||||
for (int i = 0; i < m_Scenes.Count; i++)
|
||||
{
|
||||
var (name, path) = m_Scenes[i];
|
||||
m_SceneName[i] = name;
|
||||
m_ScenePath[i] = path;
|
||||
if (SceneManager.GetActiveScene().path == path)
|
||||
sceneSelected = i;
|
||||
}
|
||||
}
|
||||
|
||||
static void OnToolbarGUI()
|
||||
{
|
||||
if (sceneSelected >= m_SceneName.Length) //空项目0场景判断
|
||||
return;
|
||||
var size = EditorStyles.popup.CalcSize(new GUIContent(m_SceneName[sceneSelected]));
|
||||
// 创建水平布局
|
||||
//EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Space(20);
|
||||
// 将控件推到左边和右边
|
||||
//GUILayout.FlexibleSpace(); // 先占用左边的所有空间
|
||||
EditorGUILayout.LabelField("当前场景:", GUILayout.Width(55));
|
||||
int sceneSelectedNew = EditorGUILayout.Popup(sceneSelected, m_SceneName, GUILayout.Width(size.x + 5f),
|
||||
GUILayout.MinWidth(55));
|
||||
GUILayout.FlexibleSpace();
|
||||
// 结束水平布局
|
||||
//EditorGUILayout.EndHorizontal();
|
||||
if (sceneSelectedNew != sceneSelected)
|
||||
{
|
||||
sceneSelected = sceneSelectedNew;
|
||||
SceneSwitcher.PromptSaveCurrentScene();
|
||||
EditorSceneManager.OpenScene(m_ScenePath[sceneSelectedNew]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class SceneSwitcher
|
||||
{
|
||||
public static bool PromptSaveCurrentScene()
|
||||
{
|
||||
// 检查当前场景是否已保存
|
||||
if (SceneManager.GetActiveScene().isDirty)
|
||||
{
|
||||
// 提示用户是否要保存当前场景
|
||||
bool saveScene = EditorUtility.DisplayDialog(
|
||||
"Save Current Scene",
|
||||
"The current scene has unsaved changes. Do you want to save it?",
|
||||
"Save",
|
||||
"Cancel"
|
||||
);
|
||||
|
||||
// 如果用户选择“保存”,则保存当前场景
|
||||
if (saveScene)
|
||||
{
|
||||
EditorSceneManager.SaveScene(SceneManager.GetActiveScene());
|
||||
}
|
||||
|
||||
return saveScene;
|
||||
}
|
||||
|
||||
// 如果场景已保存或者用户选择了“取消”,则返回 true,表示继续执行后续操作
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取项目中所有的场景文件,并以 (场景名, 场景路径) 的形式返回。
|
||||
/// </summary>
|
||||
public static List<(string sceneName, string scenePath)> GetAllScenesInProject()
|
||||
{
|
||||
List<(string sceneName, string scenePath)> scenes = new List<(string sceneName, string scenePath)>();
|
||||
|
||||
// 查找所有场景文件
|
||||
string[] guids = AssetDatabase.FindAssets("t:Scene");
|
||||
for (int i = 0; i < guids.Length; i++)
|
||||
{
|
||||
var guid = guids[i];
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
string sceneName = $"{i + 1}_{Path.GetFileNameWithoutExtension(path)}";
|
||||
scenes.Add((sceneName, path));
|
||||
}
|
||||
|
||||
return scenes;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45017e4df12424c4fb16db4708d239f0
|
||||
guid: 1fb6885a187ff8449a9cc083b7fbee28
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
@@ -60,8 +60,18 @@ namespace TEngine.Editor.UI
|
||||
strFile.Append("using TEngine;\n\n");
|
||||
strFile.Append($"namespace {ScriptGeneratorSetting.GetUINameSpace()}\n");
|
||||
strFile.Append("{\n");
|
||||
strFile.Append("\t[Window(UILayer.UI)]\n");
|
||||
strFile.Append("\tclass " + root.name + " : UIWindow\n");
|
||||
|
||||
var widgetPrefix = $"{(ScriptGeneratorSetting.GetCodeStyle() == UIFieldCodeStyle.MPrefix ? "m_" : "_")}{ScriptGeneratorSetting.GetWidgetName()}";
|
||||
if (root.name.StartsWith(widgetPrefix))
|
||||
{
|
||||
strFile.Append("\tclass " + root.name.Replace(widgetPrefix, "") + " : UIWidget\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
strFile.Append("\t[Window(UILayer.UI)]\n");
|
||||
strFile.Append("\tclass " + root.name + " : UIWindow\n");
|
||||
}
|
||||
|
||||
strFile.Append("\t{\n");
|
||||
}
|
||||
|
||||
|
@@ -65,6 +65,9 @@ MonoBehaviour:
|
||||
- uiElementRegex: m_slider
|
||||
componentName: Slider
|
||||
isUIWidget: 0
|
||||
- uiElementRegex: m_toggle
|
||||
componentName: Toggle
|
||||
isUIWidget: 0
|
||||
- uiElementRegex: m_group
|
||||
componentName: ToggleGroup
|
||||
isUIWidget: 0
|
||||
|
@@ -181,5 +181,15 @@ namespace TEngine.Editor.UI
|
||||
|
||||
return Instance.CodePath;
|
||||
}
|
||||
|
||||
public static string GetWidgetName()
|
||||
{
|
||||
if (Instance == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return Instance.WidgetName;
|
||||
}
|
||||
}
|
||||
}
|
@@ -22,7 +22,7 @@ public partial class GameApp
|
||||
_hotfixAssembly = (List<Assembly>)objects[0];
|
||||
Log.Warning("======= 看到此条日志代表你成功运行了热更新代码 =======");
|
||||
Log.Warning("======= Entrance GameApp =======");
|
||||
ModuleSystem.GetModule<IUpdateDriver>().AddDestroyListener(Release);
|
||||
Utility.Unity.AddDestroyListener(Release);
|
||||
StartGameLogic();
|
||||
}
|
||||
|
||||
|
@@ -405,6 +405,7 @@ namespace GameLogic
|
||||
return;
|
||||
}
|
||||
|
||||
window.CancelHideToCloseTimer();
|
||||
window.Visible = false;
|
||||
window.IsHide = true;
|
||||
window.HideTimerId = GameModule.Timer.AddTimer((arg) =>
|
||||
|
@@ -57,6 +57,8 @@ namespace GameLogic
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void OnRelease();
|
||||
protected virtual void OnRelease()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@@ -18,7 +18,7 @@ namespace Procedure
|
||||
LauncherMgr.Show(UIDefine.UILoadUpdate, $"下载完成...");
|
||||
|
||||
// 下载完成之后再保存本地版本。
|
||||
PlayerPrefs.SetString("GAME_VERSION", _resourceModule.PackageVersion);
|
||||
Utility.PlayerPrefs.SetString("GAME_VERSION", _resourceModule.PackageVersion);
|
||||
}
|
||||
|
||||
protected override void OnUpdate(ProcedureOwner procedureOwner, float elapseSeconds, float realElapseSeconds)
|
||||
|
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using System.Collections;
|
||||
using Launcher;
|
||||
using TEngine;
|
||||
using UnityEngine;
|
||||
using YooAsset;
|
||||
using ProcedureOwner = TEngine.IFsm<TEngine.IProcedureModule>;
|
||||
|
||||
@@ -14,8 +13,12 @@ namespace Procedure
|
||||
|
||||
public override bool UseNativeDialog => true;
|
||||
|
||||
private ProcedureOwner _procedureOwner;
|
||||
|
||||
protected override void OnEnter(ProcedureOwner procedureOwner)
|
||||
{
|
||||
_procedureOwner = procedureOwner;
|
||||
|
||||
base.OnEnter(procedureOwner);
|
||||
|
||||
_initResourcesComplete = false;
|
||||
@@ -23,7 +26,12 @@ namespace Procedure
|
||||
LauncherMgr.Show(UIDefine.UILoadUpdate, "初始化资源中...");
|
||||
|
||||
// 注意:使用单机模式并初始化资源前,需要先构建 AssetBundle 并复制到 StreamingAssets 中,否则会产生 HTTP 404 错误
|
||||
ModuleSystem.GetModule<IUpdateDriver>().StartCoroutine(InitResources(procedureOwner));
|
||||
Utility.Unity.StartCoroutine(InitResources(procedureOwner));
|
||||
}
|
||||
|
||||
private void ChangeToCreateDownloaderState(ProcedureOwner procedureOwner)
|
||||
{
|
||||
ChangeState<ProcedureCreateDownloader>(procedureOwner);
|
||||
}
|
||||
|
||||
protected override void OnUpdate(ProcedureOwner procedureOwner, float elapseSeconds, float realElapseSeconds)
|
||||
@@ -36,25 +44,35 @@ namespace Procedure
|
||||
return;
|
||||
}
|
||||
|
||||
if ((_resourceModule.PlayMode == EPlayMode.HostPlayMode || _resourceModule.PlayMode == EPlayMode.WebPlayMode))
|
||||
if (_resourceModule.PlayMode == EPlayMode.HostPlayMode || _resourceModule.PlayMode == EPlayMode.WebPlayMode)
|
||||
{
|
||||
//线上最新版本operation.PackageVersion
|
||||
Log.Debug($"Updated package Version : from {_resourceModule.GetPackageVersion()} to {_resourceModule.PackageVersion}");
|
||||
ChangeState<ProcedureUpdateManifest>(procedureOwner);
|
||||
//注意:保存资源版本号作为下次默认启动的版本!
|
||||
// 如果当前是WebGL或者是边玩边下载直接进入预加载阶段。
|
||||
if (_resourceModule.PlayMode == EPlayMode.WebPlayMode ||
|
||||
_resourceModule.UpdatableWhilePlaying)
|
||||
{
|
||||
// 边玩边下载还可以拓展首包支持。
|
||||
ChangeToPreloadState(procedureOwner);
|
||||
return;
|
||||
}
|
||||
|
||||
ChangeToCreateDownloaderState(procedureOwner);
|
||||
return;
|
||||
}
|
||||
|
||||
ChangeState<ProcedurePreload>(procedureOwner);
|
||||
ChangeToPreloadState(procedureOwner);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 编辑器与单机保持相同流程。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
//// <summary>
|
||||
/// 初始化资源流程。
|
||||
/// <remarks>YooAsset 需要保持编辑器、单机、联机模式流程一致。</remarks>
|
||||
private IEnumerator InitResources(ProcedureOwner procedureOwner)
|
||||
{
|
||||
string packageVersion;
|
||||
|
||||
Log.Info("更新资源清单!!!");
|
||||
LauncherMgr.Show(UIDefine.UILoadUpdate, $"更新清单文件...");
|
||||
|
||||
// 1. 获取资源清单的版本信息
|
||||
var operation1 = _resourceModule.RequestPackageVersionAsync();
|
||||
yield return operation1;
|
||||
@@ -64,11 +82,16 @@ namespace Procedure
|
||||
yield break;
|
||||
}
|
||||
|
||||
packageVersion = operation1.PackageVersion;
|
||||
var packageVersion = operation1.PackageVersion;
|
||||
_resourceModule.PackageVersion = packageVersion;
|
||||
|
||||
|
||||
if (Utility.PlayerPrefs.HasKey("GAME_VERSION"))
|
||||
{
|
||||
Utility.PlayerPrefs.SetString("GAME_VERSION", _resourceModule.PackageVersion);
|
||||
}
|
||||
|
||||
Log.Info($"Init resource package version : {packageVersion}");
|
||||
|
||||
|
||||
// 2. 传入的版本信息更新资源清单
|
||||
var operation2 = _resourceModule.UpdatePackageManifestAsync(packageVersion);
|
||||
yield return operation2;
|
||||
@@ -77,19 +100,75 @@ namespace Procedure
|
||||
OnInitResourcesError(procedureOwner, operation2.Error);
|
||||
yield break;
|
||||
}
|
||||
|
||||
|
||||
_initResourcesComplete = true;
|
||||
}
|
||||
|
||||
|
||||
private void ChangeToPreloadState(ProcedureOwner procedureOwner)
|
||||
{
|
||||
ChangeState<ProcedurePreload>(procedureOwner);
|
||||
}
|
||||
|
||||
private void OnInitResourcesError(ProcedureOwner procedureOwner, string message)
|
||||
{
|
||||
// 检查设备网络连接状态。
|
||||
if (_resourceModule.PlayMode == EPlayMode.HostPlayMode)
|
||||
{
|
||||
if (!IsNeedUpdate())
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error(message);
|
||||
LauncherMgr.ShowMessageBox($"获取远程版本失败!点击确认重试\n <color=#FF0000>{message}</color>", MessageShowType.TwoButton,
|
||||
LoadStyle.StyleEnum.Style_Retry,
|
||||
Application.Quit);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Log.Error(message);
|
||||
LauncherMgr.ShowMessageBox($"初始化资源失败!点击确认重试 \n <color=#FF0000>{message}</color>", MessageShowType.TwoButton,
|
||||
LoadStyle.StyleEnum.Style_Retry
|
||||
, () =>
|
||||
LoadStyle.StyleEnum.Style_Retry, () => { Utility.Unity.StartCoroutine(InitResources(procedureOwner)); }, Application.Quit);
|
||||
}
|
||||
|
||||
private bool IsNeedUpdate()
|
||||
{
|
||||
// 如果不能联网且当前游戏非强制(不更新可以进入游戏。)
|
||||
if (Settings.UpdateSetting.UpdateStyle == UpdateStyle.Optional && !_resourceModule.UpdatableWhilePlaying)
|
||||
{
|
||||
// 获取上次成功记录的版本
|
||||
string packageVersion = Utility.PlayerPrefs.GetString("GAME_VERSION", string.Empty);
|
||||
if (string.IsNullOrEmpty(packageVersion))
|
||||
{
|
||||
ModuleSystem.GetModule<IUpdateDriver>().StartCoroutine(InitResources(procedureOwner));
|
||||
}, UnityEngine.Application.Quit);
|
||||
LauncherMgr.Show(UIDefine.UILoadUpdate, LoadText.Instance.Label_Net_UnReachable);
|
||||
LauncherMgr.ShowMessageBox("没有找到本地版本记录,需要更新资源!", MessageShowType.TwoButton,
|
||||
LoadStyle.StyleEnum.Style_Retry,
|
||||
() => { Utility.Unity.StartCoroutine(InitResources(_procedureOwner)); },
|
||||
Application.Quit);
|
||||
return false;
|
||||
}
|
||||
|
||||
_resourceModule.PackageVersion = packageVersion;
|
||||
|
||||
if (Settings.UpdateSetting.UpdateNotice == UpdateNotice.Notice)
|
||||
{
|
||||
LauncherMgr.Show(UIDefine.UILoadUpdate, LoadText.Instance.Label_Load_Notice);
|
||||
LauncherMgr.ShowMessageBox($"更新失败,检测到可选资源更新,推荐完成更新提升游戏体验! \\n \\n 确定再试一次,取消进入游戏", MessageShowType.TwoButton,
|
||||
LoadStyle.StyleEnum.Style_Retry,
|
||||
() => { Utility.Unity.StartCoroutine(InitResources(_procedureOwner)); },
|
||||
() => { ChangeState<ProcedurePreload>(_procedureOwner); });
|
||||
}
|
||||
else
|
||||
{
|
||||
ChangeState<ProcedurePreload>(_procedureOwner);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@@ -129,7 +129,7 @@ namespace Procedure
|
||||
#endif
|
||||
if (_mainLogicAssembly == null)
|
||||
{
|
||||
Log.Fatal($"Main logic assembly missing.");
|
||||
Log.Fatal($"Main logic assembly missing. Please check \'ENABLE_HYBRIDCLR\' is defined in Player Settings And check the file of {_setting.LogicMainDllName}.bytes is exits.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -1,58 +0,0 @@
|
||||
using System;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Launcher;
|
||||
using TEngine;
|
||||
using YooAsset;
|
||||
using ProcedureOwner = TEngine.IFsm<TEngine.IProcedureModule>;
|
||||
|
||||
namespace Procedure
|
||||
{
|
||||
/// <summary>
|
||||
/// 流程 => 用户尝试更新清单
|
||||
/// </summary>
|
||||
public class ProcedureUpdateManifest: ProcedureBase
|
||||
{
|
||||
public override bool UseNativeDialog { get; }
|
||||
|
||||
protected override void OnEnter(ProcedureOwner procedureOwner)
|
||||
{
|
||||
Log.Info("更新资源清单!!!");
|
||||
|
||||
LauncherMgr.Show(UIDefine.UILoadUpdate,$"更新清单文件...");
|
||||
|
||||
UpdateManifest(procedureOwner).Forget();
|
||||
}
|
||||
|
||||
private async UniTaskVoid UpdateManifest(ProcedureOwner procedureOwner)
|
||||
{
|
||||
await UniTask.Delay(TimeSpan.FromSeconds(0.5f));
|
||||
|
||||
var operation = _resourceModule.UpdatePackageManifestAsync(_resourceModule.PackageVersion);
|
||||
|
||||
await operation.ToUniTask();
|
||||
|
||||
if(operation.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
//更新成功
|
||||
//注意:保存资源版本号作为下次默认启动的版本!
|
||||
|
||||
if (_resourceModule.PlayMode == EPlayMode.WebPlayMode ||
|
||||
_resourceModule.UpdatableWhilePlaying)
|
||||
{
|
||||
// 边玩边下载还可以拓展首包支持。
|
||||
ChangeState<ProcedurePreload>(procedureOwner);
|
||||
return;
|
||||
}
|
||||
ChangeState<ProcedureCreateDownloader>(procedureOwner);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error(operation.Error);
|
||||
|
||||
LauncherMgr.ShowMessageBox($"用户尝试更新清单失败!点击确认重试 \n \n <color=#FF0000>原因{operation.Error}</color>", MessageShowType.TwoButton,
|
||||
LoadStyle.StyleEnum.Style_Retry
|
||||
, () => { ChangeState<ProcedureUpdateManifest>(procedureOwner); }, UnityEngine.Application.Quit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3f0ff55ed6ee4711a65cc396946bb43f
|
||||
timeCreated: 1679634395
|
@@ -1,127 +0,0 @@
|
||||
using System;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Launcher;
|
||||
using UnityEngine;
|
||||
using TEngine;
|
||||
using YooAsset;
|
||||
using ProcedureOwner = TEngine.IFsm<TEngine.IProcedureModule>;
|
||||
|
||||
namespace Procedure
|
||||
{
|
||||
/// <summary>
|
||||
/// 流程 => 用户尝试更新静态版本
|
||||
/// </summary>
|
||||
public class ProcedureUpdateVersion : ProcedureBase
|
||||
{
|
||||
public override bool UseNativeDialog => true;
|
||||
|
||||
private ProcedureOwner _procedureOwner;
|
||||
|
||||
protected override void OnEnter(ProcedureOwner procedureOwner)
|
||||
{
|
||||
_procedureOwner = procedureOwner;
|
||||
|
||||
base.OnEnter(procedureOwner);
|
||||
|
||||
LauncherMgr.Show(UIDefine.UILoadUpdate, $"更新静态版本文件...");
|
||||
|
||||
// 检查设备是否能够访问互联网。
|
||||
if (Application.internetReachability == NetworkReachability.NotReachable)
|
||||
{
|
||||
if (!IsNeedUpdate())
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error("The device is not connected to the network");
|
||||
LauncherMgr.ShowMessageBox(LoadText.Instance.Label_Net_UnReachable, MessageShowType.TwoButton,
|
||||
LoadStyle.StyleEnum.Style_Retry,
|
||||
Application.Quit);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LauncherMgr.Show(UIDefine.UILoadUpdate, LoadText.Instance.Label_RequestVersionIng);
|
||||
|
||||
// 用户尝试更新静态版本。
|
||||
GetStaticVersion().Forget();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向用户尝试更新静态版本。
|
||||
/// </summary>
|
||||
private async UniTaskVoid GetStaticVersion()
|
||||
{
|
||||
await UniTask.Delay(TimeSpan.FromSeconds(0.5f));
|
||||
|
||||
var operation = _resourceModule.RequestPackageVersionAsync();
|
||||
|
||||
try
|
||||
{
|
||||
await operation.ToUniTask();
|
||||
|
||||
if (operation.Status == EOperationStatus.Succeed)
|
||||
{
|
||||
//线上最新版本operation.PackageVersion
|
||||
_resourceModule.PackageVersion = operation.PackageVersion;
|
||||
Log.Debug($"Updated package Version : from {_resourceModule.GetPackageVersion()} to {operation.PackageVersion}");
|
||||
ChangeState<ProcedureUpdateManifest>(_procedureOwner);
|
||||
}
|
||||
else
|
||||
{
|
||||
OnGetStaticVersionError(operation.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
OnGetStaticVersionError(e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGetStaticVersionError(string error)
|
||||
{
|
||||
Log.Error(error);
|
||||
|
||||
if (!IsNeedUpdate())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LauncherMgr.ShowMessageBox($"用户尝试更新静态版本失败!点击确认重试 \n \n <color=#FF0000>原因{error}</color>", MessageShowType.TwoButton,
|
||||
LoadStyle.StyleEnum.Style_Retry
|
||||
, () => { ChangeState<ProcedureUpdateVersion>(_procedureOwner); }, UnityEngine.Application.Quit);
|
||||
}
|
||||
|
||||
private bool IsNeedUpdate()
|
||||
{
|
||||
// 如果不能联网且当前游戏非强制(不更新可以进入游戏。)
|
||||
if (Settings.UpdateSetting.UpdateStyle == UpdateStyle.Optional)
|
||||
{
|
||||
Log.Warning("The device is not connected to the network");
|
||||
|
||||
// 获取上次成功记录的版本
|
||||
string packageVersion = PlayerPrefs.GetString("GAME_VERSION", string.Empty);
|
||||
if(string.IsNullOrEmpty(packageVersion))
|
||||
{
|
||||
LauncherMgr.Show(UIDefine.UILoadUpdate, LoadText.Instance.Label_Net_UnReachable);
|
||||
LauncherMgr.ShowMessageBox("没有找到本地版本记录,需要更新资源!", MessageShowType.TwoButton,
|
||||
LoadStyle.StyleEnum.Style_Retry,
|
||||
GetStaticVersion().Forget,
|
||||
Application.Quit);
|
||||
return false;
|
||||
}
|
||||
|
||||
_resourceModule.PackageVersion = packageVersion;
|
||||
|
||||
LauncherMgr.Show(UIDefine.UILoadUpdate, LoadText.Instance.Label_Net_UnReachable);
|
||||
LauncherMgr.ShowMessageBox(LoadText.Instance.Label_Net_UnReachable, MessageShowType.TwoButton,
|
||||
LoadStyle.StyleEnum.Style_Retry,
|
||||
GetStaticVersion().Forget,
|
||||
() => { ChangeState<ProcedureInitResources>(_procedureOwner); });
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6f0ff5df84e44adcb8064f46662a1b10
|
||||
timeCreated: 1665651883
|
@@ -4,8 +4,8 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
[HybridCLR.Editor.Settings.FilePath("ProjectSettings/AtlasConfiguration.asset")]
|
||||
public class AtlasConfiguration : HybridCLR.Editor.Settings.ScriptableSingleton<AtlasConfiguration>
|
||||
[FilePath("ProjectSettings/AtlasConfiguration.asset")]
|
||||
public class AtlasConfiguration : EditorScriptableSingleton<AtlasConfiguration>
|
||||
{
|
||||
[Header("目录设置")]
|
||||
[Tooltip("生成的图集输出目录")]
|
||||
|
@@ -88,9 +88,8 @@
|
||||
|
||||
public static void MarkParentAtlasesDirty(string assetPath)
|
||||
{
|
||||
var currentPath = Path.GetDirectoryName(assetPath);
|
||||
var currentPath = Path.GetDirectoryName(assetPath).Replace("\\", "/");
|
||||
var rootPath = Config.sourceAtlasRoot.Replace("\\", "/").TrimEnd('/');
|
||||
|
||||
while (currentPath != null && currentPath.StartsWith(rootPath))
|
||||
{
|
||||
var parentAtlasName = GetAtlasNameForDirectory(currentPath);
|
||||
@@ -202,11 +201,15 @@
|
||||
|
||||
private static List<Sprite> LoadValidSprites(string atlasName)
|
||||
{
|
||||
return _atlasMap[atlasName]
|
||||
.Where(File.Exists)
|
||||
.Select(p => AssetDatabase.LoadAssetAtPath<Sprite>(p))
|
||||
.Where(s => s != null)
|
||||
.ToList();
|
||||
if (_atlasMap.TryGetValue(atlasName, out List<string> spriteList))
|
||||
{
|
||||
return spriteList
|
||||
.Where(File.Exists)
|
||||
.Select(AssetDatabase.LoadAssetAtPath<Sprite>)
|
||||
.Where(s => s)
|
||||
.ToList();
|
||||
}
|
||||
return new List<Sprite>();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -17,8 +17,10 @@ public static class BuildDLLCommand
|
||||
public static void Disable()
|
||||
{
|
||||
ScriptingDefineSymbols.RemoveScriptingDefineSymbol(EnableHybridClrScriptingDefineSymbol);
|
||||
#if ENABLE_HYBRIDCLR
|
||||
HybridCLR.Editor.SettingsUtil.Enable = false;
|
||||
// SyncAssemblyContent.RefreshAssembly();
|
||||
UpdateSettingEditor.ForceUpdateAssemblies();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -29,8 +31,10 @@ public static class BuildDLLCommand
|
||||
{
|
||||
ScriptingDefineSymbols.RemoveScriptingDefineSymbol(EnableHybridClrScriptingDefineSymbol);
|
||||
ScriptingDefineSymbols.AddScriptingDefineSymbol(EnableHybridClrScriptingDefineSymbol);
|
||||
#if ENABLE_HYBRIDCLR
|
||||
HybridCLR.Editor.SettingsUtil.Enable = true;
|
||||
// SyncAssemblyContent.RefreshAssembly();
|
||||
UpdateSettingEditor.ForceUpdateAssemblies();
|
||||
#endif
|
||||
}
|
||||
|
||||
[MenuItem("HybridCLR/Build/BuildAssets And CopyTo AssemblyTextAssetPath")]
|
||||
|
@@ -17,6 +17,7 @@ namespace TEngine.Editor.Inspector
|
||||
};
|
||||
|
||||
private SerializedProperty _playMode = null;
|
||||
private SerializedProperty _encryptionType = null;
|
||||
private SerializedProperty _updatableWhilePlaying = null;
|
||||
private SerializedProperty _milliseconds = null;
|
||||
private SerializedProperty _minUnloadUnusedAssetsInterval = null;
|
||||
@@ -56,6 +57,8 @@ namespace TEngine.Editor.Inspector
|
||||
_playMode.enumValueIndex = selectedIndex;
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(_encryptionType);
|
||||
}
|
||||
EditorGUILayout.PropertyField(_updatableWhilePlaying);
|
||||
|
||||
@@ -220,6 +223,7 @@ namespace TEngine.Editor.Inspector
|
||||
private void OnEnable()
|
||||
{
|
||||
_playMode = serializedObject.FindProperty("playMode");
|
||||
_encryptionType = serializedObject.FindProperty("encryptionType");
|
||||
_updatableWhilePlaying = serializedObject.FindProperty("updatableWhilePlaying");
|
||||
_milliseconds = serializedObject.FindProperty("milliseconds");
|
||||
_minUnloadUnusedAssetsInterval = serializedObject.FindProperty("minUnloadUnusedAssetsInterval");
|
||||
|
@@ -724,7 +724,12 @@ namespace TEngine.Localization
|
||||
{
|
||||
if (s_RecycledEditor==null)
|
||||
{
|
||||
FieldInfo info = typeof(EditorGUI).GetField("s_RecycledEditor", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
FieldInfo info = typeof(EditorGUI).GetField("s_RecycledEditorInternal", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
#else
|
||||
FieldInfo info = typeof(EditorGUI).GetField("s_RecycledEditor", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
#endif
|
||||
|
||||
s_RecycledEditor = info.GetValue(null);
|
||||
}
|
||||
|
||||
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d4139bd1a1fd4d258b671e8e45fdd9f7
|
||||
timeCreated: 1705986748
|
@@ -1,84 +0,0 @@
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityToolbarExtender;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
public class SceneSwitchLeftButton
|
||||
{
|
||||
private static readonly string SceneMain = "main";
|
||||
|
||||
static SceneSwitchLeftButton()
|
||||
{
|
||||
ToolbarExtender.LeftToolbarGUI.Add(OnToolbarGUI);
|
||||
}
|
||||
|
||||
static readonly string ButtonStyleName = "Tab middle";
|
||||
static GUIStyle _buttonGuiStyle;
|
||||
|
||||
static void OnToolbarGUI()
|
||||
{
|
||||
_buttonGuiStyle ??= new GUIStyle(ButtonStyleName)
|
||||
{
|
||||
padding = new RectOffset(2, 8, 2, 2),
|
||||
alignment = TextAnchor.MiddleCenter,
|
||||
fontStyle = FontStyle.Bold
|
||||
};
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
if (GUILayout.Button(
|
||||
new GUIContent("Launcher", EditorGUIUtility.FindTexture("PlayButton"), $"Start Scene Launcher"),
|
||||
_buttonGuiStyle))
|
||||
{
|
||||
SceneHelper.StartScene(SceneMain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class SceneHelper
|
||||
{
|
||||
static string _sceneToOpen;
|
||||
|
||||
public static void StartScene(string sceneName)
|
||||
{
|
||||
if (EditorApplication.isPlaying)
|
||||
{
|
||||
EditorApplication.isPlaying = false;
|
||||
}
|
||||
|
||||
_sceneToOpen = sceneName;
|
||||
EditorApplication.update += OnUpdate;
|
||||
}
|
||||
|
||||
static void OnUpdate()
|
||||
{
|
||||
if (_sceneToOpen == null ||
|
||||
EditorApplication.isPlaying || EditorApplication.isPaused ||
|
||||
EditorApplication.isCompiling || EditorApplication.isPlayingOrWillChangePlaymode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EditorApplication.update -= OnUpdate;
|
||||
|
||||
if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
|
||||
{
|
||||
string[] guids = AssetDatabase.FindAssets("t:scene " + _sceneToOpen, null);
|
||||
if (guids.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("Couldn't find scene file");
|
||||
}
|
||||
else
|
||||
{
|
||||
string scenePath = AssetDatabase.GUIDToAssetPath(guids[0]);
|
||||
EditorSceneManager.OpenScene(scenePath);
|
||||
EditorApplication.isPlaying = true;
|
||||
}
|
||||
}
|
||||
|
||||
_sceneToOpen = null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine.Editor
|
||||
{
|
||||
public class EditorScriptableSingleton<T> : ScriptableObject where T : ScriptableObject
|
||||
{
|
||||
private static T _instance;
|
||||
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_instance)
|
||||
{
|
||||
LoadOrCreate();
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public static T LoadOrCreate()
|
||||
{
|
||||
string filePath = GetFilePath();
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
var arr = InternalEditorUtility.LoadSerializedFileAndForget(filePath);
|
||||
_instance = arr.Length > 0 ? arr[0] as T : _instance ?? CreateInstance<T>();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"save location of {nameof(EditorScriptableSingleton<T>)} is invalid");
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
|
||||
public static void Save(bool saveAsText = true)
|
||||
{
|
||||
if (!_instance)
|
||||
{
|
||||
Debug.LogError("Cannot save ScriptableSingleton: no instance!");
|
||||
return;
|
||||
}
|
||||
|
||||
string filePath = GetFilePath();
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
string directoryName = Path.GetDirectoryName(filePath);
|
||||
if (!Directory.Exists(directoryName))
|
||||
{
|
||||
if (directoryName != null)
|
||||
{
|
||||
Directory.CreateDirectory(directoryName);
|
||||
}
|
||||
}
|
||||
|
||||
UnityEngine.Object[] obj = { _instance };
|
||||
InternalEditorUtility.SaveToSerializedFileAndForget(obj, filePath, saveAsText);
|
||||
}
|
||||
}
|
||||
|
||||
protected static string GetFilePath()
|
||||
{
|
||||
return typeof(T).GetCustomAttributes(inherit: true)
|
||||
.Where(v => v is FilePathAttribute)
|
||||
.Cast<FilePathAttribute>()
|
||||
.FirstOrDefault()
|
||||
?.Filepath;
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class FilePathAttribute : Attribute
|
||||
{
|
||||
internal readonly string Filepath;
|
||||
|
||||
/// <summary>
|
||||
/// 单例存放路径。
|
||||
/// </summary>
|
||||
/// <param name="path">相对 Project 路径。</param>
|
||||
public FilePathAttribute(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
throw new ArgumentException("Invalid relative path (it is empty)");
|
||||
}
|
||||
|
||||
if (path[0] == '/')
|
||||
{
|
||||
path = path.Substring(1);
|
||||
}
|
||||
|
||||
Filepath = path;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bec53acfb41d41a29b3664015d318e39
|
||||
timeCreated: 1742523496
|
@@ -1,8 +1,9 @@
|
||||
#if ENABLE_HYBRIDCLR
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using HybridCLR.Editor.Settings;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using HybridCLR.Editor.Settings;
|
||||
|
||||
namespace TEngine.Editor
|
||||
{
|
||||
@@ -40,11 +41,17 @@ namespace TEngine.Editor
|
||||
// 标记对象为“已修改”,确保修改能被保存
|
||||
EditorUtility.SetDirty(updateSetting);
|
||||
|
||||
bool isHotChanged = HotUpdateAssemblies.SequenceEqual(updateSetting.HotUpdateAssemblies);
|
||||
bool isAOTChanged = AOTMetaAssemblies.SequenceEqual(updateSetting.AOTMetaAssemblies);
|
||||
bool isHotChanged = !HotUpdateAssemblies.SequenceEqual(updateSetting.HotUpdateAssemblies);
|
||||
bool isAOTChanged = !AOTMetaAssemblies.SequenceEqual(updateSetting.AOTMetaAssemblies);
|
||||
if (isHotChanged)
|
||||
{
|
||||
HybridCLRSettings.Instance.hotUpdateAssemblies = updateSetting.HotUpdateAssemblies.ToArray();
|
||||
for (int i = 0; i < updateSetting.HotUpdateAssemblies.Count; i++)
|
||||
{
|
||||
var assemblyName = updateSetting.HotUpdateAssemblies[i];
|
||||
string assemblyNameWithoutExtension = assemblyName.Substring(0, assemblyName.LastIndexOf('.'));
|
||||
HybridCLRSettings.Instance.hotUpdateAssemblies[i] = assemblyNameWithoutExtension;
|
||||
}
|
||||
Debug.Log("HotUpdateAssemblies changed");
|
||||
}
|
||||
if (isAOTChanged)
|
||||
@@ -52,7 +59,45 @@ namespace TEngine.Editor
|
||||
HybridCLRSettings.Instance.patchAOTAssemblies = updateSetting.AOTMetaAssemblies.ToArray();
|
||||
Debug.Log("AOTMetaAssemblies changed");
|
||||
}
|
||||
|
||||
if (isAOTChanged || isHotChanged)
|
||||
{
|
||||
// 在修改HybridCLRSettings后添加
|
||||
EditorUtility.SetDirty(HybridCLRSettings.Instance);
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void ForceUpdateAssemblies()
|
||||
{
|
||||
|
||||
UpdateSetting updateSetting = null;
|
||||
string[] guids = AssetDatabase.FindAssets("t:UpdateSetting");
|
||||
if (guids.Length >= 1)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guids[0]);
|
||||
updateSetting = AssetDatabase.LoadAssetAtPath<UpdateSetting>(path);
|
||||
}
|
||||
|
||||
if (updateSetting == null)
|
||||
{
|
||||
Log.Error("Can not find UpdateSetting");
|
||||
return;
|
||||
}
|
||||
|
||||
HybridCLRSettings.Instance.hotUpdateAssemblies = updateSetting.HotUpdateAssemblies.ToArray();
|
||||
for (int i = 0; i < updateSetting.HotUpdateAssemblies.Count; i++)
|
||||
{
|
||||
var assemblyName = updateSetting.HotUpdateAssemblies[i];
|
||||
string assemblyNameWithoutExtension = assemblyName.Substring(0, assemblyName.LastIndexOf('.'));
|
||||
HybridCLRSettings.Instance.hotUpdateAssemblies[i] = assemblyNameWithoutExtension;
|
||||
}
|
||||
|
||||
HybridCLRSettings.Instance.patchAOTAssemblies = updateSetting.AOTMetaAssemblies.ToArray();
|
||||
|
||||
Debug.Log("HotUpdateAssemblies changed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -1,638 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#region Class Documentation
|
||||
|
||||
/************************************************************************************************************
|
||||
Class Name: ActorEventDispatcher.cs 局部单位事件分发器。
|
||||
Type: Actor, Event
|
||||
Example:
|
||||
private ActorEventDispatcher _event;
|
||||
|
||||
/// <summary>
|
||||
/// 局部事件管理器。
|
||||
/// <remark>只分发和监听这个Event内部的事件</remark>
|
||||
/// </summary>
|
||||
public ActorEventDispatcher Event => _event ??= MemoryPool.Acquire<ActorEventDispatcher>();
|
||||
|
||||
// owner局部发送事件。
|
||||
owner.Event.Send(eventId,xxx);
|
||||
|
||||
// owner监听自身事件并绑定持有对象为owner。 比如是组件的情况下。移除时调用RemoveAllListenerByOwner(owner)会根据持有对象(组件)移除。
|
||||
owner.Event.AddEventListener(eventId,xxx,owner);
|
||||
************************************************************************************************************/
|
||||
|
||||
#endregion
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 局部单位事件分发器。
|
||||
/// </summary>
|
||||
public class ActorEventDispatcher : IMemory
|
||||
{
|
||||
/// <summary>
|
||||
/// 所有事件。
|
||||
/// </summary>
|
||||
private readonly Dictionary<int, List<EventRegInfo>> _allEventListenerMap = new();
|
||||
|
||||
/// <summary>
|
||||
/// 用于标记一个事件是不是正在处理。
|
||||
/// </summary>
|
||||
private readonly List<int> _processEventList = new();
|
||||
|
||||
/// <summary>
|
||||
/// 用于标记一个事件是不是被移除。
|
||||
/// </summary>
|
||||
private readonly List<int> _delayDeleteEventList = new();
|
||||
|
||||
/// <summary>
|
||||
/// 移除所有事件监听。
|
||||
/// </summary>
|
||||
public void DestroyAllEventListener()
|
||||
{
|
||||
var itr = _allEventListenerMap.GetEnumerator();
|
||||
while (itr.MoveNext())
|
||||
{
|
||||
var kv = itr.Current;
|
||||
List<EventRegInfo> list = kv.Value;
|
||||
foreach (var eventRegInfo in list)
|
||||
{
|
||||
EventRegInfo.Release(eventRegInfo);
|
||||
}
|
||||
|
||||
kv.Value.Clear();
|
||||
}
|
||||
|
||||
_processEventList.Clear();
|
||||
_delayDeleteEventList.Clear();
|
||||
itr.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 延迟移除事件。
|
||||
/// </summary>
|
||||
/// <param name="eventId"></param>
|
||||
private void AddDelayDelete(int eventId)
|
||||
{
|
||||
if (!_delayDeleteEventList.Contains(eventId))
|
||||
{
|
||||
_delayDeleteEventList.Add(eventId);
|
||||
Log.Info("delay delete eventId[{0}]", eventId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 如果找到eventId对应的监听,删除所有标记为delete的监听。
|
||||
/// </summary>
|
||||
/// <param name="eventId">事件Id。</param>
|
||||
private void CheckDelayDelete(int eventId)
|
||||
{
|
||||
if (_delayDeleteEventList.Contains(eventId))
|
||||
{
|
||||
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
|
||||
{
|
||||
for (int i = listListener.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (listListener[i].IsDeleted)
|
||||
{
|
||||
Log.Info("remove delay delete eventId[{0}]", eventId);
|
||||
EventRegInfo.Release(listListener[i]);
|
||||
listListener.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_delayDeleteEventList.Remove(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送事件。
|
||||
/// </summary>
|
||||
/// <param name="eventId">事件Id。</param>
|
||||
public void SendEvent(int eventId)
|
||||
{
|
||||
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
|
||||
{
|
||||
_processEventList.Add(eventId);
|
||||
#if UNITY_EDITOR
|
||||
int iEventCnt = _processEventList.Count;
|
||||
#endif
|
||||
|
||||
var count = listListener.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var node = listListener[i];
|
||||
if (node.IsDeleted)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (listListener[i].Callback is Action callBack)
|
||||
{
|
||||
callBack();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Fatal("Invalid event data type: {0}", eventId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
Log.Assert(iEventCnt == _processEventList.Count);
|
||||
Log.Assert(eventId == _processEventList[^1]);
|
||||
#endif
|
||||
_processEventList.RemoveAt(_processEventList.Count - 1);
|
||||
|
||||
CheckDelayDelete(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送事件。
|
||||
/// </summary>
|
||||
/// <param name="eventId">事件Id。</param>
|
||||
/// <param name="arg1">事件参数。</param>
|
||||
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
|
||||
public void SendEvent<TArg1>(int eventId, TArg1 arg1)
|
||||
{
|
||||
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
|
||||
{
|
||||
_processEventList.Add(eventId);
|
||||
#if UNITY_EDITOR
|
||||
int iEventCnt = _processEventList.Count;
|
||||
#endif
|
||||
|
||||
var count = listListener.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var node = listListener[i];
|
||||
if (node.IsDeleted)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (listListener[i].Callback is Action<TArg1> callBack)
|
||||
{
|
||||
callBack(arg1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Fatal("Invalid event data type: {0}", eventId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
Log.Assert(iEventCnt == _processEventList.Count);
|
||||
Log.Assert(eventId == _processEventList[^1]);
|
||||
#endif
|
||||
|
||||
_processEventList.RemoveAt(_processEventList.Count - 1);
|
||||
|
||||
CheckDelayDelete(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送事件。
|
||||
/// </summary>
|
||||
/// <param name="eventId">事件Id。</param>
|
||||
/// <param name="arg1">事件参数1。</param>
|
||||
/// <param name="arg2">事件参数2。</param>
|
||||
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
|
||||
/// <typeparam name="TArg2">事件参数类型2。</typeparam>
|
||||
public void SendEvent<TArg1, TArg2>(int eventId, TArg1 arg1, TArg2 arg2)
|
||||
{
|
||||
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
|
||||
{
|
||||
_processEventList.Add(eventId);
|
||||
#if UNITY_EDITOR
|
||||
int iEventCnt = _processEventList.Count;
|
||||
#endif
|
||||
|
||||
var count = listListener.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var node = listListener[i];
|
||||
if (node.IsDeleted)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (listListener[i].Callback is Action<TArg1, TArg2> callBack)
|
||||
{
|
||||
callBack(arg1, arg2);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Fatal("Invalid event data type: {0}", eventId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
Log.Assert(iEventCnt == _processEventList.Count);
|
||||
Log.Assert(eventId == _processEventList[^1]);
|
||||
#endif
|
||||
_processEventList.RemoveAt(_processEventList.Count - 1);
|
||||
|
||||
CheckDelayDelete(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送事件。
|
||||
/// </summary>
|
||||
/// <param name="eventId">事件Id。</param>
|
||||
/// <param name="arg1">事件参数1。</param>
|
||||
/// <param name="arg2">事件参数2。</param>
|
||||
/// <param name="arg3">事件参数3。</param>
|
||||
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
|
||||
/// <typeparam name="TArg2">事件参数类型2。</typeparam>
|
||||
/// <typeparam name="TArg3">事件参数类型3。</typeparam>
|
||||
public void SendEvent<TArg1, TArg2, TArg3>(int eventId, TArg1 arg1, TArg2 arg2, TArg3 arg3)
|
||||
{
|
||||
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
|
||||
{
|
||||
_processEventList.Add(eventId);
|
||||
#if UNITY_EDITOR
|
||||
int iEventCnt = _processEventList.Count;
|
||||
#endif
|
||||
|
||||
var count = listListener.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var node = listListener[i];
|
||||
if (node.IsDeleted)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node.Callback is Action<TArg1, TArg2, TArg3> callBack)
|
||||
{
|
||||
callBack(arg1, arg2, arg3);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Fatal("Invalid event data type: {0}", eventId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
Log.Assert(iEventCnt == _processEventList.Count);
|
||||
Log.Assert(eventId == _processEventList[^1]);
|
||||
#endif
|
||||
_processEventList.RemoveAt(_processEventList.Count - 1);
|
||||
|
||||
CheckDelayDelete(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送事件。
|
||||
/// </summary>
|
||||
/// <param name="eventId">事件Id。</param>
|
||||
/// <param name="arg1">事件参数1。</param>
|
||||
/// <param name="arg2">事件参数2。</param>
|
||||
/// <param name="arg3">事件参数3。</param>
|
||||
/// <param name="arg4">事件参数4。</param>
|
||||
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
|
||||
/// <typeparam name="TArg2">事件参数类型2。</typeparam>
|
||||
/// <typeparam name="TArg3">事件参数类型3。</typeparam>
|
||||
/// <typeparam name="TArg4">事件参数类型4。</typeparam>
|
||||
public void SendEvent<TArg1, TArg2, TArg3, TArg4>(int eventId, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4)
|
||||
{
|
||||
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
|
||||
{
|
||||
_processEventList.Add(eventId);
|
||||
#if UNITY_EDITOR
|
||||
int iEventCnt = _processEventList.Count;
|
||||
#endif
|
||||
|
||||
|
||||
var count = listListener.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var node = listListener[i];
|
||||
if (node.IsDeleted)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (listListener[i].Callback is Action<TArg1, TArg2, TArg3, TArg4> callBack)
|
||||
{
|
||||
callBack(arg1, arg2, arg3, arg4);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Fatal("Invalid event data type: {0}", eventId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
Log.Assert(iEventCnt == _processEventList.Count);
|
||||
Log.Assert(eventId == _processEventList[^1]);
|
||||
#endif
|
||||
_processEventList.RemoveAt(_processEventList.Count - 1);
|
||||
|
||||
CheckDelayDelete(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加事件监听。
|
||||
/// </summary>
|
||||
/// <param name="eventId">事件Id。</param>
|
||||
/// <param name="eventCallback">事件回调。</param>
|
||||
/// <param name="owner">持有者Tag。</param>
|
||||
public void AddEventListener(int eventId, Action eventCallback, object owner)
|
||||
{
|
||||
AddEventListenerImp(eventId, eventCallback, owner);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加事件监听。
|
||||
/// </summary>
|
||||
/// <param name="eventId">事件Id。</param>
|
||||
/// <param name="eventCallback">事件回调。</param>
|
||||
/// <param name="owner">持有者Tag。</param>
|
||||
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
|
||||
public void AddEventListener<TArg1>(int eventId, Action<TArg1> eventCallback, object owner)
|
||||
{
|
||||
AddEventListenerImp(eventId, eventCallback, owner);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加事件监听。
|
||||
/// </summary>
|
||||
/// <param name="eventId">事件Id。</param>
|
||||
/// <param name="eventCallback">事件回调。</param>
|
||||
/// <param name="owner">持有者Tag。</param>
|
||||
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
|
||||
/// <typeparam name="TArg2">事件参数类型2。</typeparam>
|
||||
public void AddEventListener<TArg1, TArg2>(int eventId, Action<TArg1, TArg2> eventCallback, object owner)
|
||||
{
|
||||
AddEventListenerImp(eventId, eventCallback, owner);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加事件监听。
|
||||
/// </summary>
|
||||
/// <param name="eventId">事件Id。</param>
|
||||
/// <param name="eventCallback">事件回调。</param>
|
||||
/// <param name="owner">持有者Tag。</param>
|
||||
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
|
||||
/// <typeparam name="TArg2">事件参数类型2。</typeparam>
|
||||
/// <typeparam name="TArg3">事件参数类型3。</typeparam>
|
||||
public void AddEventListener<TArg1, TArg2, TArg3>(int eventId, Action<TArg1, TArg2, TArg3> eventCallback, object owner)
|
||||
{
|
||||
AddEventListenerImp(eventId, eventCallback, owner);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加事件监听。
|
||||
/// </summary>
|
||||
/// <param name="eventId">事件Id。</param>
|
||||
/// <param name="eventCallback">事件回调。</param>
|
||||
/// <param name="owner">持有者Tag。</param>
|
||||
/// <typeparam name="TArg1">事件参数类型1。</typeparam>
|
||||
/// <typeparam name="TArg2">事件参数类型2。</typeparam>
|
||||
/// <typeparam name="TArg3">事件参数类型3。</typeparam>
|
||||
/// <typeparam name="TArg4">事件参数类型4。</typeparam>
|
||||
public void AddEventListener<TArg1, TArg2, TArg3, TArg4>(int eventId, Action<TArg1, TArg2, TArg3, TArg4> eventCallback, object owner)
|
||||
{
|
||||
AddEventListenerImp(eventId, eventCallback, owner);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 增加事件监听具体实现。
|
||||
/// </summary>
|
||||
/// <param name="eventId">事件Id。</param>
|
||||
/// <param name="listener">事件回调。</param>
|
||||
/// <param name="owner">持有者Tag。</param>
|
||||
private void AddEventListenerImp(int eventId, Delegate listener, object owner)
|
||||
{
|
||||
if (!_allEventListenerMap.TryGetValue(eventId, out var listListener))
|
||||
{
|
||||
listListener = new List<EventRegInfo>();
|
||||
_allEventListenerMap.Add(eventId, listListener);
|
||||
}
|
||||
|
||||
var existNode = listListener.Find((node) => node.Callback == listener);
|
||||
if (existNode != null)
|
||||
{
|
||||
if (existNode.IsDeleted)
|
||||
{
|
||||
existNode.IsDeleted = false;
|
||||
Log.Warning("AddEvent hashId deleted, repeat add: {0}", eventId);
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Fatal("AddEvent hashId repeated: {0}", eventId);
|
||||
return;
|
||||
}
|
||||
|
||||
listListener.Add(EventRegInfo.Alloc(listener, owner));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过持有者Tag移除监听。
|
||||
/// </summary>
|
||||
/// <param name="owner">持有者Tag。</param>
|
||||
public void RemoveAllListenerByOwner(object owner)
|
||||
{
|
||||
var itr = _allEventListenerMap.GetEnumerator();
|
||||
while (itr.MoveNext())
|
||||
{
|
||||
var kv = itr.Current;
|
||||
var list = kv.Value;
|
||||
|
||||
int eventId = kv.Key;
|
||||
bool isProcessing = _processEventList.Contains(eventId);
|
||||
bool delayDeleted = false;
|
||||
|
||||
for (int i = list.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var regInfo = list[i];
|
||||
if (regInfo.Owner == owner)
|
||||
{
|
||||
if (isProcessing)
|
||||
{
|
||||
regInfo.IsDeleted = true;
|
||||
delayDeleted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
EventRegInfo.Release(list[i]);
|
||||
list.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (delayDeleted)
|
||||
{
|
||||
AddDelayDelete(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
itr.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除事件监听。
|
||||
/// </summary>
|
||||
/// <param name="eventId">事件Id。</param>
|
||||
/// <param name="eventCallback">消息回调。</param>
|
||||
public void RemoveEventListener(int eventId, Action eventCallback)
|
||||
{
|
||||
RemoveEventListenerImp(eventId, eventCallback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除事件监听。
|
||||
/// </summary>
|
||||
/// <param name="eventId">事件Id。</param>
|
||||
/// <param name="eventCallback">消息回调。</param>
|
||||
/// <typeparam name="TArg1">参数类型1。</typeparam>
|
||||
public void RemoveEventListener<TArg1>(int eventId, Action<TArg1> eventCallback)
|
||||
{
|
||||
RemoveEventListenerImp(eventId, eventCallback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除事件监听。
|
||||
/// </summary>
|
||||
/// <param name="eventId">事件Id。</param>
|
||||
/// <param name="eventCallback">消息回调。</param>
|
||||
/// <typeparam name="TArg1">参数类型1。</typeparam>
|
||||
/// <typeparam name="TArg2">参数类型2。</typeparam>
|
||||
public void RemoveEventListener<TArg1, TArg2>(int eventId, Action<TArg1, TArg2> eventCallback)
|
||||
{
|
||||
RemoveEventListenerImp(eventId, eventCallback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除事件监听。
|
||||
/// </summary>
|
||||
/// <param name="eventId">事件Id。</param>
|
||||
/// <param name="eventCallback">消息回调。</param>
|
||||
/// <typeparam name="TArg1">参数类型1。</typeparam>
|
||||
/// <typeparam name="TArg2">参数类型2。</typeparam>
|
||||
/// <typeparam name="TArg3">参数类型3。</typeparam>
|
||||
public void RemoveEventListener<TArg1, TArg2, TArg3>(int eventId, Action<TArg1, TArg2, TArg3> eventCallback)
|
||||
{
|
||||
RemoveEventListenerImp(eventId, eventCallback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除事件监听。
|
||||
/// </summary>
|
||||
/// <param name="eventId">事件Id。</param>
|
||||
/// <param name="eventCallback">消息回调。</param>
|
||||
/// <typeparam name="TArg1">参数类型1。</typeparam>
|
||||
/// <typeparam name="TArg2">参数类型2。</typeparam>
|
||||
/// <typeparam name="TArg3">参数类型3。</typeparam>
|
||||
/// <typeparam name="TArg4">参数类型4。</typeparam>
|
||||
public void RemoveEventListener<TArg1, TArg2, TArg3, TArg4>(int eventId, Action<TArg1, TArg2, TArg3, TArg4> eventCallback)
|
||||
{
|
||||
RemoveEventListenerImp(eventId, eventCallback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除监听,如果是正在处理的监听则标记为删除
|
||||
/// </summary>
|
||||
/// <param name="eventId">事件Id。</param>
|
||||
/// <param name="listener">事件监听。</param>
|
||||
protected void RemoveEventListenerImp(int eventId, Delegate listener)
|
||||
{
|
||||
if (_allEventListenerMap.TryGetValue(eventId, out var listListener))
|
||||
{
|
||||
bool isProcessing = _processEventList.Contains(eventId);
|
||||
if (!isProcessing)
|
||||
{
|
||||
listListener.RemoveAll(node => node.Callback == listener);
|
||||
}
|
||||
else
|
||||
{
|
||||
int listenCnt = listListener.Count;
|
||||
for (int i = 0; i < listenCnt; i++)
|
||||
{
|
||||
var node = listListener[i];
|
||||
if (node.Callback == listener)
|
||||
{
|
||||
node.IsDeleted = true;
|
||||
AddDelayDelete(eventId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除回收接口。
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
DestroyAllEventListener();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 事件注册信息。
|
||||
/// </summary>
|
||||
public class EventRegInfo : IMemory
|
||||
{
|
||||
/// <summary>
|
||||
/// 事件回调。
|
||||
/// </summary>
|
||||
public Delegate Callback;
|
||||
|
||||
/// <summary>
|
||||
/// 事件持有者。
|
||||
/// </summary>
|
||||
public object Owner;
|
||||
|
||||
/// <summary>
|
||||
/// 事件是否删除。
|
||||
/// </summary>
|
||||
public bool IsDeleted;
|
||||
|
||||
public EventRegInfo(Delegate callback, object owner)
|
||||
{
|
||||
this.Callback = callback;
|
||||
Owner = owner;
|
||||
IsDeleted = false;
|
||||
}
|
||||
|
||||
public EventRegInfo()
|
||||
{
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Callback = null;
|
||||
Owner = null;
|
||||
IsDeleted = false;
|
||||
}
|
||||
|
||||
public static EventRegInfo Alloc(Delegate callback, object owner)
|
||||
{
|
||||
EventRegInfo ret = MemoryPool.Acquire<EventRegInfo>();
|
||||
ret.Callback = callback;
|
||||
ret.Owner = owner;
|
||||
ret.IsDeleted = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void Release(EventRegInfo eventRegInfo)
|
||||
{
|
||||
MemoryPool.Release(eventRegInfo);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 222c2a26f3b14d42950d0e9a10b61b38
|
||||
timeCreated: 1673511406
|
Binary file not shown.
@@ -62,7 +62,7 @@ namespace TEngine
|
||||
public List<string> HotUpdateAssemblies = new List<string>() {"GameProto.dll", "GameLogic.dll" };
|
||||
|
||||
[Header("Need manual setting!")]
|
||||
public List<string> AOTMetaAssemblies = new List<string>() { "mscorlib.dll", "System.dll", "System.Core.dll", "TEngine.Runtime.dll" };
|
||||
public List<string> AOTMetaAssemblies = new List<string>() { "mscorlib.dll", "System.dll", "System.Core.dll", "TEngine.Runtime.dll" ,"UniTask.dll", "YooAsset.dll"};
|
||||
|
||||
/// <summary>
|
||||
/// Dll of main business logic assembly
|
||||
|
@@ -43,7 +43,11 @@ namespace TEngine
|
||||
var cts = new CancellationTokenSource();
|
||||
cts.CancelAfterSlim(TimeSpan.FromSeconds(timeout));
|
||||
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
using UnityWebRequest unityWebRequest = UnityWebRequest.PostWwwForm(url, postData);
|
||||
#else
|
||||
using UnityWebRequest unityWebRequest = UnityWebRequest.Post(url, postData);
|
||||
#endif
|
||||
return await SendWebRequest(unityWebRequest, cts);
|
||||
}
|
||||
|
||||
|
@@ -322,6 +322,19 @@ namespace TEngine
|
||||
|
||||
_updateDriver = ModuleSystem.GetModule<IUpdateDriver>();
|
||||
}
|
||||
|
||||
#region FindObjectOfType
|
||||
public static T FindObjectOfType<T>() where T : UnityEngine.Object
|
||||
{
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
return UnityEngine.Object.FindFirstObjectByType<T>();
|
||||
#else
|
||||
return UnityEngine.Object.FindObjectOfType<T>();
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class GameCoroutine
|
||||
|
@@ -290,18 +290,6 @@ namespace TEngine
|
||||
public long UIFillAmount(UnityEngine.UI.Image target, Single startValue, Single endValue, float duration, Ease ease = Ease.Default, int cycles = 1,
|
||||
CycleMode cycleMode = CycleMode.Restart, float startDelay = 0, float endDelay = 0, bool useUnscaledTime = false);
|
||||
|
||||
public long RotationAdditive(UnityEngine.Transform target, UnityEngine.Vector3 deltaValue, float duration, Ease ease = Ease.Default, int cycles = 1,
|
||||
CycleMode cycleMode = CycleMode.Restart, float startDelay = 0, float endDelay = 0, bool useUnscaledTime = false);
|
||||
|
||||
public long LocalRotationAdditive(UnityEngine.Transform target, UnityEngine.Vector3 deltaValue, float duration, Ease ease = Ease.Default, int cycles = 1,
|
||||
CycleMode cycleMode = CycleMode.Restart, float startDelay = 0, float endDelay = 0, bool useUnscaledTime = false);
|
||||
|
||||
public long RotationAdditive(UnityEngine.Transform target, UnityEngine.Quaternion deltaValue, float duration, Ease ease = Ease.Default, int cycles = 1,
|
||||
CycleMode cycleMode = CycleMode.Restart, float startDelay = 0, float endDelay = 0, bool useUnscaledTime = false);
|
||||
|
||||
public long LocalRotationAdditive(UnityEngine.Transform target, UnityEngine.Quaternion deltaValue, float duration, Ease ease = Ease.Default,
|
||||
int cycles = 1, CycleMode cycleMode = CycleMode.Restart, float startDelay = 0, float endDelay = 0, bool useUnscaledTime = false);
|
||||
|
||||
public long MoveBezierPath(UnityEngine.Transform target, UnityEngine.Vector3[] path, float duration, Ease ease = Ease.Default, int cycles = 1,
|
||||
CycleMode cycleMode = CycleMode.Restart, float startDelay = 0, float endDelay = 0, bool useUnscaledTime = false);
|
||||
|
||||
@@ -309,10 +297,6 @@ namespace TEngine
|
||||
Ease ease = Ease.Default, int cycles = 1, CycleMode cycleMode = CycleMode.Restart, float startDelay = 0, float endDelay = 0, bool useUnscaledTime = false)
|
||||
where T : class;
|
||||
|
||||
public long Custom<T>(T target, uint startValue, uint endValue, float duration, Action<T, uint> onValueChange,
|
||||
Ease ease = Ease.Default, int cycles = 1, CycleMode cycleMode = CycleMode.Restart, float startDelay = 0, float endDelay = 0, bool useUnscaledTime = false)
|
||||
where T : class;
|
||||
|
||||
public long Custom<T>(T target, long startValue, long endValue, float duration, Action<T, long> onValueChange,
|
||||
Ease ease = Ease.Default, int cycles = 1, CycleMode cycleMode = CycleMode.Restart, float startDelay = 0, float endDelay = 0, bool useUnscaledTime = false)
|
||||
where T : class;
|
||||
|
@@ -14,7 +14,7 @@ namespace TEngine
|
||||
/// <summary>
|
||||
/// 设置动画辅助器。
|
||||
/// </summary>
|
||||
/// <param name="textHelper">要设置的字符辅助器。</param>
|
||||
/// <param name="textHelper">要设置的动画辅助器。</param>
|
||||
public static void SetTweenHelper(ITweenHelper textHelper)
|
||||
{
|
||||
_tweenHelper = textHelper;
|
||||
@@ -779,48 +779,6 @@ namespace TEngine
|
||||
return _tweenHelper.UIFillAmount(target, startValue, endValue, duration, ease, cycles, cycleMode, startDelay, endDelay, useUnscaledTime);
|
||||
}
|
||||
|
||||
public static long RotationAdditive(UnityEngine.Transform target, UnityEngine.Vector3 deltaValue, float duration, Ease ease = Ease.Default, int cycles = 1,
|
||||
CycleMode cycleMode = CycleMode.Restart, float startDelay = 0, float endDelay = 0, bool useUnscaledTime = false)
|
||||
{
|
||||
if (_tweenHelper == null)
|
||||
{
|
||||
throw new GameFrameworkException("ITweenHelper is invalid.");
|
||||
}
|
||||
return _tweenHelper.RotationAdditive(target, deltaValue, duration, ease, cycles, cycleMode, startDelay, endDelay, useUnscaledTime);
|
||||
}
|
||||
|
||||
|
||||
public static long LocalRotationAdditive(UnityEngine.Transform target, UnityEngine.Vector3 deltaValue, float duration, Ease ease = Ease.Default, int cycles = 1,
|
||||
CycleMode cycleMode = CycleMode.Restart, float startDelay = 0, float endDelay = 0, bool useUnscaledTime = false)
|
||||
{
|
||||
if (_tweenHelper == null)
|
||||
{
|
||||
throw new GameFrameworkException("ITweenHelper is invalid.");
|
||||
}
|
||||
return _tweenHelper.LocalRotationAdditive(target, deltaValue, duration, ease, cycles, cycleMode, startDelay, endDelay, useUnscaledTime);
|
||||
}
|
||||
|
||||
|
||||
public static long RotationAdditive(UnityEngine.Transform target, UnityEngine.Quaternion deltaValue, float duration, Ease ease = Ease.Default, int cycles = 1,
|
||||
CycleMode cycleMode = CycleMode.Restart, float startDelay = 0, float endDelay = 0, bool useUnscaledTime = false)
|
||||
{
|
||||
if (_tweenHelper == null)
|
||||
{
|
||||
throw new GameFrameworkException("ITweenHelper is invalid.");
|
||||
}
|
||||
return _tweenHelper.RotationAdditive(target, deltaValue, duration, ease, cycles, cycleMode, startDelay, endDelay, useUnscaledTime);
|
||||
}
|
||||
|
||||
public static long LocalRotationAdditive(UnityEngine.Transform target, UnityEngine.Quaternion deltaValue, float duration, Ease ease = Ease.Default,
|
||||
int cycles = 1, CycleMode cycleMode = CycleMode.Restart, float startDelay = 0, float endDelay = 0, bool useUnscaledTime = false)
|
||||
{
|
||||
if (_tweenHelper == null)
|
||||
{
|
||||
throw new GameFrameworkException("ITweenHelper is invalid.");
|
||||
}
|
||||
return _tweenHelper.LocalRotationAdditive(target, deltaValue, duration, ease, cycles, cycleMode, startDelay, endDelay, useUnscaledTime);
|
||||
}
|
||||
|
||||
public static long MoveBezierPath(UnityEngine.Transform target, UnityEngine.Vector3[] path, float duration, Ease ease = Ease.Default, int cycles = 1,
|
||||
CycleMode cycleMode = CycleMode.Restart, float startDelay = 0, float endDelay = 0, bool useUnscaledTime = false)
|
||||
{
|
||||
@@ -842,17 +800,6 @@ namespace TEngine
|
||||
return _tweenHelper.Custom(target, startValue, endValue, duration, onValueChange, ease, cycles, cycleMode, startDelay, endDelay, useUnscaledTime);
|
||||
}
|
||||
|
||||
public static long Custom<T>(T target, uint startValue, uint endValue, float duration, Action<T, uint> onValueChange,
|
||||
Ease ease = Ease.Default, int cycles = 1, CycleMode cycleMode = CycleMode.Restart, float startDelay = 0, float endDelay = 0, bool useUnscaledTime = false)
|
||||
where T : class
|
||||
{
|
||||
if (_tweenHelper == null)
|
||||
{
|
||||
throw new GameFrameworkException("ITweenHelper is invalid.");
|
||||
}
|
||||
return _tweenHelper.Custom(target, startValue, endValue, duration, onValueChange, ease, cycles, cycleMode, startDelay, endDelay, useUnscaledTime);
|
||||
}
|
||||
|
||||
public static long Custom<T>(T target, long startValue, long endValue, float duration, Action<T, long> onValueChange,
|
||||
Ease ease = Ease.Default, int cycles = 1, CycleMode cycleMode = CycleMode.Restart, float startDelay = 0, float endDelay = 0, bool useUnscaledTime = false)
|
||||
where T : class
|
||||
@@ -877,7 +824,7 @@ namespace TEngine
|
||||
}
|
||||
}
|
||||
|
||||
public static class DTweenExtensions
|
||||
public static class TweenExtensions
|
||||
{
|
||||
public static long OnComplete(this long tweenId, Action onComplete)
|
||||
{
|
||||
|
@@ -25,7 +25,9 @@ namespace TEngine.Localization
|
||||
|
||||
public static void AutoLoadGlobalParamManagers()
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
foreach (var manager in Object.FindObjectsOfType<LocalizationParamsManager>())
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
{
|
||||
if (manager._IsGlobalManager && !ParamManagers.Contains(manager))
|
||||
{
|
||||
|
@@ -20,7 +20,7 @@ namespace TEngine.Localization
|
||||
bool changed = mInstance==null;
|
||||
|
||||
if (mInstance==null)
|
||||
mInstance = (ResourceManager)FindObjectOfType(typeof(ResourceManager));
|
||||
mInstance = Utility.Unity.FindObjectOfType<ResourceManager>();
|
||||
|
||||
if (mInstance==null)
|
||||
{
|
||||
|
@@ -71,8 +71,8 @@ namespace TEngine
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Dictionary<Language, string> s_LanguageMap = new Dictionary<Language, string>();
|
||||
private static readonly Dictionary<string, Language> s_LanguageStrMap = new Dictionary<string, Language>();
|
||||
private static readonly Dictionary<Language, string> _languageMap = new Dictionary<Language, string>();
|
||||
private static readonly Dictionary<string, Language> _languageStrMap = new Dictionary<string, Language>();
|
||||
|
||||
static LocalizationUtility()
|
||||
{
|
||||
@@ -90,8 +90,8 @@ namespace TEngine
|
||||
str = language.ToString();
|
||||
}
|
||||
|
||||
s_LanguageMap[language] = str;
|
||||
s_LanguageStrMap[str] = language;
|
||||
_languageMap[language] = str;
|
||||
_languageStrMap[str] = language;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -106,7 +106,7 @@ namespace TEngine
|
||||
return Language.Unspecified;
|
||||
}
|
||||
|
||||
if (s_LanguageStrMap.TryGetValue(str, out var language))
|
||||
if (_languageStrMap.TryGetValue(str, out var language))
|
||||
{
|
||||
return language;
|
||||
}
|
||||
@@ -122,7 +122,7 @@ namespace TEngine
|
||||
/// <returns>语言字符串。</returns>
|
||||
public static string GetLanguageStr(Language language)
|
||||
{
|
||||
if (s_LanguageMap.TryGetValue(language, out var ret))
|
||||
if (_languageMap.TryGetValue(language, out var ret))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
@@ -69,5 +69,14 @@ namespace TEngine
|
||||
/// <param name="procedureType">要获取的流程类型。</param>
|
||||
/// <returns>要获取的流程。</returns>
|
||||
ProcedureBase GetProcedure(Type procedureType);
|
||||
|
||||
/// <summary>
|
||||
/// 重启流程。
|
||||
/// <remarks>默认使用第一个流程作为启动流程。</remarks>
|
||||
/// </summary>
|
||||
/// <param name="procedures">新的的流程。</param>
|
||||
/// <returns>是否重启成功。</returns>
|
||||
/// <exception cref="GameFrameworkException">重启异常。</exception>
|
||||
bool RestartProcedure(params ProcedureBase[] procedures);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,27 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 资源模块的加密类型枚举。
|
||||
/// <remarks>用于定义资源加载时的不同加密方式。</remarks>
|
||||
/// </summary>
|
||||
public enum EncryptionType
|
||||
{
|
||||
/// <summary>
|
||||
/// 无加密。
|
||||
/// <remarks>资源将以原始形式加载,不进行任何加密处理。</remarks>
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// 文件偏移加密。
|
||||
/// <remarks>通过在文件开头添加偏移量来隐藏真实文件内容的加密方式。</remarks>
|
||||
/// </summary>
|
||||
FileOffSet,
|
||||
|
||||
/// <summary>
|
||||
/// 文件流加密。
|
||||
/// <remarks>使用加密流对文件内容进行加密处理的加密方式。</remarks>
|
||||
/// </summary>
|
||||
FileStream,
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18468bde9ea948729cd7eab8a2d6e598
|
||||
timeCreated: 1742356779
|
@@ -1,4 +1,5 @@
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using TEngine;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
@@ -27,4 +28,29 @@ public static class SetSpriteExtensions
|
||||
{
|
||||
ResourceExtComponent.Instance.SetAssetByResources<Sprite>(SetSpriteObject.Create(spriteRenderer, location, cancellationToken)).Forget();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置子图片。
|
||||
/// </summary>
|
||||
/// <param name="image">UI/Image。</param>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="spriteName">子图片名称。</param>
|
||||
/// <param name="setNativeSize">是否使用原始分辨率。</param>
|
||||
/// <param name="cancellationToken">取消设置资源的Token。</param>
|
||||
public static void SetSubSprite(this Image image, string location, string spriteName, bool setNativeSize = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ResourceExtComponent.Instance.SetSubSprite(image, location, spriteName, setNativeSize, cancellationToken).Forget();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置子图片。
|
||||
/// </summary>
|
||||
/// <param name="spriteRenderer">2D/SpriteRender。</param>
|
||||
/// <param name="location">资源定位地址。</param>
|
||||
/// <param name="spriteName">子图片名称。</param>
|
||||
/// <param name="cancellationToken">取消设置资源的Token。</param>
|
||||
public static void SetSubSprite(this SpriteRenderer spriteRenderer, string location, string spriteName, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ResourceExtComponent.Instance.SetSubSprite(spriteRenderer, location, spriteName, cancellationToken).Forget();
|
||||
}
|
||||
}
|
@@ -22,7 +22,7 @@ namespace TEngine
|
||||
private void OnLoadAssetFailure(string assetName, LoadResourceStatus status, string errormessage, object userdata)
|
||||
{
|
||||
_assetLoadingList.Remove(assetName);
|
||||
Log.Error("Can not load asset from '{1}' with error message '{2}'.", assetName, errormessage);
|
||||
Log.Error("Can not load asset from '{0}' with error message '{1}'.", assetName, errormessage);
|
||||
}
|
||||
|
||||
private void OnLoadAssetSuccess(string assetName, object asset, float duration, object userdata)
|
||||
|
@@ -0,0 +1,125 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using YooAsset;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 资源组件拓展。
|
||||
/// </summary>
|
||||
internal partial class ResourceExtComponent
|
||||
{
|
||||
private readonly Dictionary<string, SubAssetsHandle> _subAssetsHandles = new Dictionary<string, SubAssetsHandle>();
|
||||
private readonly Dictionary<string, int> _subSpriteReferences = new Dictionary<string, int>();
|
||||
|
||||
public async UniTask SetSubSprite(Image image, string location, string spriteName, bool setNativeSize = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var subSprite = await GetSubSpriteImp(location, spriteName, cancellationToken);
|
||||
|
||||
if (image == null)
|
||||
{
|
||||
Log.Warning($"SetSubAssets Image is null");
|
||||
return;
|
||||
}
|
||||
|
||||
image.sprite = subSprite;
|
||||
if (setNativeSize)
|
||||
{
|
||||
image.SetNativeSize();
|
||||
}
|
||||
AddReference(image.gameObject, location);
|
||||
}
|
||||
|
||||
public async UniTask SetSubSprite(SpriteRenderer spriteRenderer, string location, string spriteName, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var subSprite = await GetSubSpriteImp(location, spriteName, cancellationToken);
|
||||
|
||||
if (spriteRenderer == null)
|
||||
{
|
||||
Log.Warning($"SetSubAssets Image is null");
|
||||
return;
|
||||
}
|
||||
|
||||
spriteRenderer.sprite = subSprite;
|
||||
AddReference(spriteRenderer.gameObject, location);
|
||||
}
|
||||
|
||||
private async UniTask<Sprite> GetSubSpriteImp(string location, string spriteName, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var assetInfo = YooAssets.GetAssetInfo(location);
|
||||
if (assetInfo.IsInvalid)
|
||||
{
|
||||
throw new GameFrameworkException($"Invalid location: {location}");
|
||||
}
|
||||
|
||||
await TryWaitingLoading(location);
|
||||
|
||||
if (!_subAssetsHandles.TryGetValue(location, out var subAssetsHandle))
|
||||
{
|
||||
subAssetsHandle = YooAssets.LoadSubAssetsAsync<Sprite>(location);
|
||||
await subAssetsHandle.ToUniTask(cancellationToken: cancellationToken);
|
||||
_subAssetsHandles[location] = subAssetsHandle;
|
||||
}
|
||||
|
||||
var subSprite = subAssetsHandle.GetSubAssetObject<Sprite>(spriteName);
|
||||
if (subSprite == null)
|
||||
{
|
||||
throw new GameFrameworkException($"Invalid sprite name: {spriteName}");
|
||||
}
|
||||
return subSprite;
|
||||
}
|
||||
|
||||
private void AddReference(GameObject target,string location)
|
||||
{
|
||||
var subSpriteReference = target.GetComponent<SubSpriteReference>();
|
||||
if (subSpriteReference == null)
|
||||
{
|
||||
subSpriteReference = target.AddComponent<SubSpriteReference>();
|
||||
}
|
||||
_subSpriteReferences[location] = _subSpriteReferences.TryGetValue(location, out var count) ? count + 1 : 1;
|
||||
subSpriteReference.Reference(location);
|
||||
}
|
||||
|
||||
internal void DeleteReference(string location)
|
||||
{
|
||||
if (string.IsNullOrEmpty(location))
|
||||
{
|
||||
return;
|
||||
}
|
||||
_subSpriteReferences[location] = _subSpriteReferences.TryGetValue(location, out var count) ? count - 1 : 0;
|
||||
if (_subSpriteReferences[location] <= 0)
|
||||
{
|
||||
var subAssetsHandle = _subAssetsHandles[location];
|
||||
subAssetsHandle.Dispose();
|
||||
_subAssetsHandles.Remove(location);
|
||||
_subSpriteReferences.Remove(location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DisallowMultipleComponent]
|
||||
public class SubSpriteReference : MonoBehaviour
|
||||
{
|
||||
private string _location;
|
||||
|
||||
public void Reference(string location)
|
||||
{
|
||||
if (_location != null && _location != location)
|
||||
{
|
||||
ResourceExtComponent.Instance?.DeleteReference(_location);
|
||||
}
|
||||
_location = location;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (_location != null)
|
||||
{
|
||||
ResourceExtComponent.Instance?.DeleteReference(_location);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6ff32785e2bb42d085e53a36eb09038d
|
||||
timeCreated: 1746582361
|
@@ -25,6 +25,11 @@ namespace TEngine
|
||||
/// 获取或设置运行模式。
|
||||
/// </summary>
|
||||
EPlayMode PlayMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源加密方式。
|
||||
/// </summary>
|
||||
EncryptionType EncryptionType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否边玩边下载。
|
||||
@@ -202,22 +207,6 @@ namespace TEngine
|
||||
/// <typeparam name="T">要加载资源的类型。</typeparam>
|
||||
UniTaskVoid LoadAsset<T>(string location, Action<T> callback, string packageName = "") where T : UnityEngine.Object;
|
||||
|
||||
/// <summary>
|
||||
/// 同步加载子资源对象。
|
||||
/// </summary>
|
||||
/// <typeparam name="TObject">资源类型。</typeparam>
|
||||
/// <param name="location">资源的定位地址。</param>
|
||||
/// <param name="packageName">指定资源包的名称。不传使用默认资源包</param>
|
||||
public TObject[] LoadSubAssetsSync<TObject>(string location, string packageName = "") where TObject : UnityEngine.Object;
|
||||
|
||||
/// <summary>
|
||||
/// 异步加载子资源对象。
|
||||
/// </summary>
|
||||
/// <typeparam name="TObject">资源类型。</typeparam>
|
||||
/// <param name="location">资源的定位地址。</param>
|
||||
/// <param name="packageName">指定资源包的名称。不传使用默认资源包</param>
|
||||
public UniTask<TObject[]> LoadSubAssetsAsync<TObject>(string location, string packageName = "") where TObject : UnityEngine.Object;
|
||||
|
||||
/// <summary>
|
||||
/// 异步加载资源。
|
||||
/// </summary>
|
||||
|
@@ -67,7 +67,7 @@ namespace TEngine
|
||||
DecryptResult decryptResult = new DecryptResult();
|
||||
decryptResult.ManagedStream = bundleStream;
|
||||
decryptResult.Result =
|
||||
AssetBundle.LoadFromStream(bundleStream, fileInfo.FileLoadCRC, GetManagedReadBufferSize());
|
||||
AssetBundle.LoadFromStream(bundleStream, 0, GetManagedReadBufferSize());
|
||||
return decryptResult;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace TEngine
|
||||
DecryptResult decryptResult = new DecryptResult();
|
||||
decryptResult.ManagedStream = bundleStream;
|
||||
decryptResult.CreateRequest =
|
||||
AssetBundle.LoadFromStreamAsync(bundleStream, fileInfo.FileLoadCRC, GetManagedReadBufferSize());
|
||||
AssetBundle.LoadFromStreamAsync(bundleStream, 0, GetManagedReadBufferSize());
|
||||
return decryptResult;
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ namespace TEngine
|
||||
DecryptResult decryptResult = new DecryptResult();
|
||||
decryptResult.ManagedStream = null;
|
||||
decryptResult.Result =
|
||||
AssetBundle.LoadFromFile(fileInfo.FileLoadPath, fileInfo.FileLoadCRC, GetFileOffset());
|
||||
AssetBundle.LoadFromFile(fileInfo.FileLoadPath, 0, GetFileOffset());
|
||||
return decryptResult;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace TEngine
|
||||
DecryptResult decryptResult = new DecryptResult();
|
||||
decryptResult.ManagedStream = null;
|
||||
decryptResult.CreateRequest =
|
||||
AssetBundle.LoadFromFileAsync(fileInfo.FileLoadPath, fileInfo.FileLoadCRC, GetFileOffset());
|
||||
AssetBundle.LoadFromFileAsync(fileInfo.FileLoadPath, 0, GetFileOffset());
|
||||
return decryptResult;
|
||||
}
|
||||
|
||||
@@ -179,6 +179,50 @@ namespace TEngine
|
||||
return 32;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region WebDecryptionServices
|
||||
/// <summary>
|
||||
/// 资源文件偏移加载解密类
|
||||
/// </summary>
|
||||
public class FileOffsetWebDecryption : IWebDecryptionServices
|
||||
{
|
||||
public WebDecryptResult LoadAssetBundle(WebDecryptFileInfo fileInfo)
|
||||
{
|
||||
int offset = GetFileOffset();
|
||||
byte[] decryptedData = new byte[fileInfo.FileData.Length - offset];
|
||||
Buffer.BlockCopy(fileInfo.FileData, offset, decryptedData, 0, decryptedData.Length);
|
||||
// 从内存中加载AssetBundle
|
||||
WebDecryptResult decryptResult = new WebDecryptResult();
|
||||
decryptResult.Result = AssetBundle.LoadFromMemory(decryptedData);
|
||||
return decryptResult;
|
||||
}
|
||||
|
||||
private static int GetFileOffset()
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
}
|
||||
|
||||
public class FileStreamWebDecryption : IWebDecryptionServices
|
||||
{
|
||||
public WebDecryptResult LoadAssetBundle(WebDecryptFileInfo fileInfo)
|
||||
{
|
||||
// 优化:使用Buffer批量操作替代逐字节异或
|
||||
byte[] decryptedData = new byte[fileInfo.FileData.Length];
|
||||
Buffer.BlockCopy(fileInfo.FileData, 0, decryptedData, 0, fileInfo.FileData.Length);
|
||||
|
||||
for (int i = 0; i < decryptedData.Length; i++)
|
||||
{
|
||||
decryptedData[i] ^= BundleStream.KEY;
|
||||
}
|
||||
|
||||
WebDecryptResult decryptResult = new WebDecryptResult();
|
||||
decryptResult.Result = AssetBundle.LoadFromMemory(decryptedData);
|
||||
return decryptResult;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -204,7 +248,6 @@ public class BundleStream : FileStream
|
||||
{
|
||||
array[i] ^= KEY;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
}
|
@@ -5,6 +5,9 @@ using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using YooAsset;
|
||||
#if UNITY_WEBGL && WEIXINMINIGAME && !UNITY_EDITOR
|
||||
using WeChatWASM;
|
||||
#endif
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
@@ -22,6 +25,8 @@ namespace TEngine
|
||||
/// 资源系统运行模式。
|
||||
/// </summary>
|
||||
public EPlayMode PlayMode { get; set; } = EPlayMode.OfflinePlayMode;
|
||||
|
||||
public EncryptionType EncryptionType { get; set; } = EncryptionType.None;
|
||||
|
||||
/// <summary>
|
||||
/// 设置异步系统参数,每帧执行消耗的最大时间切片(单位:毫秒)
|
||||
@@ -164,12 +169,14 @@ namespace TEngine
|
||||
createParameters.EditorFileSystemParameters = FileSystemParameters.CreateDefaultEditorFileSystemParameters(packageRoot);
|
||||
initializationOperation = package.InitializeAsync(createParameters);
|
||||
}
|
||||
|
||||
|
||||
IDecryptionServices decryptionServices = CreateDecryptionServices();
|
||||
|
||||
// 单机运行模式
|
||||
if (playMode == EPlayMode.OfflinePlayMode)
|
||||
{
|
||||
var createParameters = new OfflinePlayModeParameters();
|
||||
createParameters.BuildinFileSystemParameters = FileSystemParameters.CreateDefaultBuildinFileSystemParameters();
|
||||
createParameters.BuildinFileSystemParameters = FileSystemParameters.CreateDefaultBuildinFileSystemParameters(decryptionServices);
|
||||
initializationOperation = package.InitializeAsync(createParameters);
|
||||
}
|
||||
|
||||
@@ -180,8 +187,8 @@ namespace TEngine
|
||||
string fallbackHostServer = FallbackHostServerURL;
|
||||
IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
|
||||
var createParameters = new HostPlayModeParameters();
|
||||
createParameters.BuildinFileSystemParameters = FileSystemParameters.CreateDefaultBuildinFileSystemParameters();
|
||||
createParameters.CacheFileSystemParameters = FileSystemParameters.CreateDefaultCacheFileSystemParameters(remoteServices);
|
||||
createParameters.BuildinFileSystemParameters = FileSystemParameters.CreateDefaultBuildinFileSystemParameters(decryptionServices);
|
||||
createParameters.CacheFileSystemParameters = FileSystemParameters.CreateDefaultCacheFileSystemParameters(remoteServices, decryptionServices);
|
||||
initializationOperation = package.InitializeAsync(createParameters);
|
||||
}
|
||||
|
||||
@@ -189,13 +196,19 @@ namespace TEngine
|
||||
if (playMode == EPlayMode.WebPlayMode)
|
||||
{
|
||||
var createParameters = new WebPlayModeParameters();
|
||||
#if UNITY_WEBGL && WEIXINMINIGAME && !UNITY_EDITOR
|
||||
string defaultHostServer = HostServerURL;
|
||||
IWebDecryptionServices webDecryptionServices = CreateWebDecryptionServices();
|
||||
string defaultHostServer = HostServerURL;
|
||||
string fallbackHostServer = FallbackHostServerURL;
|
||||
IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
|
||||
createParameters.WebServerFileSystemParameters = WechatFileSystemCreater.CreateWechatFileSystemParameters(remoteServices);
|
||||
#if UNITY_WEBGL && WEIXINMINIGAME && !UNITY_EDITOR
|
||||
Log.Info("=======================WEIXINMINIGAME=======================");
|
||||
// 注意:如果有子目录,请修改此处!
|
||||
string packageRoot = $"{WeChatWASM.WX.env.USER_DATA_PATH}/__GAME_FILE_CACHE";
|
||||
createParameters.WebServerFileSystemParameters = WechatFileSystemCreater.CreateFileSystemParameters(packageRoot, remoteServices, webDecryptionServices);
|
||||
#else
|
||||
createParameters.WebServerFileSystemParameters = FileSystemParameters.CreateDefaultWebServerFileSystemParameters();
|
||||
Log.Info("=======================UNITY_WEBGL=======================");
|
||||
createParameters.WebRemoteFileSystemParameters = FileSystemParameters.CreateDefaultWebRemoteFileSystemParameters(remoteServices, webDecryptionServices);
|
||||
createParameters.WebServerFileSystemParameters = FileSystemParameters.CreateDefaultWebServerFileSystemParameters(webDecryptionServices);
|
||||
#endif
|
||||
initializationOperation = package.InitializeAsync(createParameters);
|
||||
}
|
||||
@@ -207,6 +220,32 @@ namespace TEngine
|
||||
return initializationOperation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建解密服务。
|
||||
/// </summary>
|
||||
private IDecryptionServices CreateDecryptionServices()
|
||||
{
|
||||
return EncryptionType switch
|
||||
{
|
||||
EncryptionType.FileOffSet => new FileOffsetDecryption(),
|
||||
EncryptionType.FileStream => new FileStreamDecryption(),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建Web解密服务。
|
||||
/// </summary>
|
||||
private IWebDecryptionServices CreateWebDecryptionServices()
|
||||
{
|
||||
return EncryptionType switch
|
||||
{
|
||||
EncryptionType.FileOffSet => new FileOffsetWebDecryption(),
|
||||
EncryptionType.FileStream => new FileStreamWebDecryption(),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前资源包版本。
|
||||
/// </summary>
|
||||
@@ -717,26 +756,6 @@ namespace TEngine
|
||||
};
|
||||
}
|
||||
|
||||
public TObject[] LoadSubAssetsSync<TObject>(string location, string packageName = "") where TObject : UnityEngine.Object
|
||||
{
|
||||
if (string.IsNullOrEmpty(location))
|
||||
{
|
||||
throw new GameFrameworkException("Asset name is invalid.");
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public UniTask<TObject[]> LoadSubAssetsAsync<TObject>(string location, string packageName = "") where TObject : UnityEngine.Object
|
||||
{
|
||||
if (string.IsNullOrEmpty(location))
|
||||
{
|
||||
throw new GameFrameworkException("Asset name is invalid.");
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async UniTask<T> LoadAssetAsync<T>(string location, CancellationToken cancellationToken = default, string packageName = "") where T : UnityEngine.Object
|
||||
{
|
||||
if (string.IsNullOrEmpty(location))
|
||||
|
@@ -89,6 +89,14 @@ namespace TEngine
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private EncryptionType encryptionType = EncryptionType.None;
|
||||
|
||||
/// <summary>
|
||||
/// 资源模块的加密类型。
|
||||
/// </summary>
|
||||
public EncryptionType EncryptionType => encryptionType;
|
||||
|
||||
/// <summary>
|
||||
/// 是否支持边玩边下载。
|
||||
@@ -238,6 +246,7 @@ namespace TEngine
|
||||
|
||||
_resourceModule.DefaultPackageName = PackageName;
|
||||
_resourceModule.PlayMode = PlayMode;
|
||||
_resourceModule.EncryptionType = encryptionType;
|
||||
_resourceModule.Milliseconds = milliseconds;
|
||||
_resourceModule.HostServerURL = Settings.UpdateSetting.GetResDownLoadPath();
|
||||
_resourceModule.FallbackHostServerURL = Settings.UpdateSetting.GetFallbackResDownLoadPath();
|
||||
|
@@ -17,7 +17,7 @@ namespace TEngine
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = FindObjectOfType<RootModule>();
|
||||
_instance = Utility.Unity.FindObjectOfType<RootModule>();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace TEngine
|
||||
@@ -10,6 +11,18 @@ namespace TEngine
|
||||
/// </summary>
|
||||
public string CurrentMainSceneName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 加载场景。
|
||||
/// </summary>
|
||||
/// <param name="location">场景的定位地址</param>
|
||||
/// <param name="sceneMode">场景加载模式</param>
|
||||
/// <param name="suspendLoad">加载完毕时是否主动挂起</param>
|
||||
/// <param name="priority">优先级</param>
|
||||
/// <param name="gcCollect">加载主场景是否回收垃圾。</param>
|
||||
/// <param name="progressCallBack">加载进度回调。</param>
|
||||
public UniTask<Scene> LoadSceneAsync(string location, LoadSceneMode sceneMode = LoadSceneMode.Single, bool suspendLoad = false, uint priority = 100, bool gcCollect = true,
|
||||
Action<float> progressCallBack = null);
|
||||
|
||||
/// <summary>
|
||||
/// 加载场景。
|
||||
/// </summary>
|
||||
@@ -20,7 +33,7 @@ namespace TEngine
|
||||
/// <param name="callBack">加载回调。</param>
|
||||
/// <param name="gcCollect">加载主场景是否回收垃圾。</param>
|
||||
/// <param name="progressCallBack">加载进度回调。</param>
|
||||
public Scene LoadScene(string location,
|
||||
public void LoadScene(string location,
|
||||
LoadSceneMode sceneMode = LoadSceneMode.Single,
|
||||
bool suspendLoad = false,
|
||||
uint priority = 100,
|
||||
@@ -49,13 +62,20 @@ namespace TEngine
|
||||
/// <returns>是否主场景。</returns>
|
||||
public bool IsMainScene(string location);
|
||||
|
||||
/// <summary>
|
||||
/// 异步卸载子场景。
|
||||
/// </summary>
|
||||
/// <param name="location">场景资源定位地址。</param>
|
||||
/// <param name="progressCallBack">进度回调。</param>
|
||||
public UniTask<bool> UnloadAsync(string location, Action<float> progressCallBack = null);
|
||||
|
||||
/// <summary>
|
||||
/// 异步卸载子场景。
|
||||
/// </summary>
|
||||
/// <param name="location">场景资源定位地址。</param>
|
||||
/// <param name="callBack">卸载完成回调。</param>
|
||||
/// <param name="progressCallBack">进度回调。</param>
|
||||
public void UnloadAsync(string location, Action callBack = null, Action<float> progressCallBack = null);
|
||||
public void Unload(string location, Action callBack = null, Action<float> progressCallBack = null);
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含场景。
|
||||
|
@@ -13,6 +13,8 @@ namespace TEngine
|
||||
private SceneHandle _currentMainScene;
|
||||
|
||||
private readonly Dictionary<string, SceneHandle> _subScenes = new Dictionary<string, SceneHandle>();
|
||||
|
||||
private readonly HashSet<string> _handlingScene = new HashSet<string>();
|
||||
|
||||
/// <summary>
|
||||
/// 当前主场景名称。
|
||||
@@ -39,9 +41,87 @@ namespace TEngine
|
||||
|
||||
iter.Dispose();
|
||||
_subScenes.Clear();
|
||||
_handlingScene.Clear();
|
||||
_currentMainSceneName = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载场景。
|
||||
/// </summary>
|
||||
/// <param name="location">场景的定位地址</param>
|
||||
/// <param name="sceneMode">场景加载模式</param>
|
||||
/// <param name="suspendLoad">加载完毕时是否主动挂起</param>
|
||||
/// <param name="priority">优先级</param>
|
||||
/// <param name="gcCollect">加载主场景是否回收垃圾。</param>
|
||||
/// <param name="progressCallBack">加载进度回调。</param>
|
||||
public async UniTask<Scene> LoadSceneAsync(string location, LoadSceneMode sceneMode = LoadSceneMode.Single, bool suspendLoad = false, uint priority = 100, bool gcCollect = true, Action<float> progressCallBack = null)
|
||||
{
|
||||
if (!_handlingScene.Add(location))
|
||||
{
|
||||
Log.Error($"Could not load scene while loading. Scene: {location}");
|
||||
return default;
|
||||
}
|
||||
|
||||
if (sceneMode == LoadSceneMode.Additive)
|
||||
{
|
||||
if (_subScenes.TryGetValue(location, out SceneHandle subScene))
|
||||
{
|
||||
throw new Exception($"Could not load subScene while already loaded. Scene: {location}");
|
||||
}
|
||||
|
||||
subScene = YooAssets.LoadSceneAsync(location, sceneMode, LocalPhysicsMode.None, suspendLoad, priority);
|
||||
|
||||
if (progressCallBack != null)
|
||||
{
|
||||
while (!subScene.IsDone && subScene.IsValid)
|
||||
{
|
||||
progressCallBack.Invoke(subScene.Progress);
|
||||
await UniTask.Yield();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await subScene.ToUniTask();
|
||||
}
|
||||
|
||||
_subScenes.Add(location, subScene);
|
||||
|
||||
_handlingScene.Remove(location);
|
||||
|
||||
return subScene.SceneObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_currentMainScene is { IsDone: false })
|
||||
{
|
||||
throw new Exception($"Could not load MainScene while loading. CurrentMainScene: {_currentMainSceneName}.");
|
||||
}
|
||||
|
||||
_currentMainSceneName = location;
|
||||
|
||||
_currentMainScene = YooAssets.LoadSceneAsync(location, sceneMode, LocalPhysicsMode.None, suspendLoad, priority);
|
||||
|
||||
if (progressCallBack != null)
|
||||
{
|
||||
while (!_currentMainScene.IsDone && _currentMainScene.IsValid)
|
||||
{
|
||||
progressCallBack.Invoke(_currentMainScene.Progress);
|
||||
await UniTask.Yield();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await _currentMainScene.ToUniTask();
|
||||
}
|
||||
|
||||
ModuleSystem.GetModule<IResourceModule>().ForceUnloadUnusedAssets(gcCollect);
|
||||
|
||||
_handlingScene.Remove(location);
|
||||
|
||||
return _currentMainScene.SceneObject;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载场景。
|
||||
/// </summary>
|
||||
@@ -52,24 +132,32 @@ namespace TEngine
|
||||
/// <param name="callBack">加载回调。</param>
|
||||
/// <param name="gcCollect">加载主场景是否回收垃圾。</param>
|
||||
/// <param name="progressCallBack">加载进度回调。</param>
|
||||
public Scene LoadScene(string location, LoadSceneMode sceneMode = LoadSceneMode.Single, bool suspendLoad = false, uint priority = 100,
|
||||
public void LoadScene(string location, LoadSceneMode sceneMode = LoadSceneMode.Single, bool suspendLoad = false, uint priority = 100,
|
||||
Action<Scene> callBack = null,
|
||||
bool gcCollect = true, Action<float> progressCallBack = null)
|
||||
{
|
||||
|
||||
if (!_handlingScene.Add(location))
|
||||
{
|
||||
Log.Error($"Could not load scene while loading. Scene: {location}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sceneMode == LoadSceneMode.Additive)
|
||||
{
|
||||
if (_subScenes.TryGetValue(location, out SceneHandle subScene))
|
||||
{
|
||||
Log.Warning($"Could not load subScene while already loaded. Scene: {location}");
|
||||
return default;
|
||||
return;
|
||||
}
|
||||
|
||||
subScene = YooAssets.LoadSceneAsync(location, sceneMode, LocalPhysicsMode.None, suspendLoad, priority);
|
||||
|
||||
if (callBack != null)
|
||||
subScene.Completed += handle =>
|
||||
{
|
||||
subScene.Completed += handle => { callBack.Invoke(handle.SceneObject); };
|
||||
}
|
||||
_handlingScene.Remove(location);
|
||||
callBack?.Invoke(handle.SceneObject);
|
||||
};
|
||||
|
||||
if (progressCallBack != null)
|
||||
{
|
||||
@@ -77,25 +165,24 @@ namespace TEngine
|
||||
}
|
||||
|
||||
_subScenes.Add(location, subScene);
|
||||
|
||||
return default;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_currentMainScene is { IsDone: false })
|
||||
{
|
||||
Log.Warning($"Could not load MainScene while loading. CurrentMainScene: {_currentMainSceneName}.");
|
||||
return default;
|
||||
return;
|
||||
}
|
||||
|
||||
_currentMainSceneName = location;
|
||||
|
||||
_currentMainScene = YooAssets.LoadSceneAsync(location, sceneMode, LocalPhysicsMode.None, suspendLoad, priority);
|
||||
|
||||
if (callBack != null)
|
||||
_currentMainScene.Completed += handle =>
|
||||
{
|
||||
_currentMainScene.Completed += handle => { callBack.Invoke(handle.SceneObject); };
|
||||
}
|
||||
_handlingScene.Remove(location);
|
||||
callBack?.Invoke(handle.SceneObject);
|
||||
};
|
||||
|
||||
if (progressCallBack != null)
|
||||
{
|
||||
@@ -103,8 +190,6 @@ namespace TEngine
|
||||
}
|
||||
|
||||
ModuleSystem.GetModule<IResourceModule>().ForceUnloadUnusedAssets(gcCollect);
|
||||
|
||||
return _currentMainScene.SceneObject;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,13 +298,61 @@ namespace TEngine
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步卸载子场景。
|
||||
/// </summary>
|
||||
/// <param name="location">场景资源定位地址。</param>
|
||||
/// <param name="progressCallBack">进度回调。</param>
|
||||
public async UniTask<bool> UnloadAsync(string location, Action<float> progressCallBack = null)
|
||||
{
|
||||
_subScenes.TryGetValue(location, out SceneHandle subScene);
|
||||
if (subScene != null)
|
||||
{
|
||||
if (subScene.SceneObject == default)
|
||||
{
|
||||
Log.Error($"Could not unload Scene while not loaded. Scene: {location}");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_handlingScene.Add(location))
|
||||
{
|
||||
Log.Warning($"Could not unload Scene while loading. Scene: {location}");
|
||||
return false;
|
||||
}
|
||||
|
||||
var unloadOperation = subScene.UnloadAsync();
|
||||
|
||||
if (progressCallBack != null)
|
||||
{
|
||||
while (!unloadOperation.IsDone && unloadOperation.Status != EOperationStatus.Failed)
|
||||
{
|
||||
progressCallBack.Invoke(unloadOperation.Progress);
|
||||
await UniTask.Yield();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await unloadOperation.ToUniTask();
|
||||
}
|
||||
|
||||
_subScenes.Remove(location);
|
||||
|
||||
_handlingScene.Remove(location);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Log.Warning($"UnloadAsync invalid location:{location}");
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步卸载子场景。
|
||||
/// </summary>
|
||||
/// <param name="location">场景资源定位地址。</param>
|
||||
/// <param name="callBack">卸载完成回调。</param>
|
||||
/// <param name="progressCallBack">进度回调。</param>
|
||||
public void UnloadAsync(string location, Action callBack = null, Action<float> progressCallBack = null)
|
||||
public void Unload(string location, Action callBack = null, Action<float> progressCallBack = null)
|
||||
{
|
||||
_subScenes.TryGetValue(location, out SceneHandle subScene);
|
||||
if (subScene != null)
|
||||
@@ -229,19 +362,26 @@ namespace TEngine
|
||||
Log.Error($"Could not unload Scene while not loaded. Scene: {location}");
|
||||
return;
|
||||
}
|
||||
|
||||
_subScenes.Remove(location);
|
||||
subScene.UnloadAsync();
|
||||
if (callBack != null)
|
||||
|
||||
if (!_handlingScene.Add(location))
|
||||
{
|
||||
subScene.UnloadAsync().Completed += @base => { callBack.Invoke(); };
|
||||
Log.Warning($"Could not unload Scene while loading. Scene: {location}");
|
||||
return;
|
||||
}
|
||||
|
||||
subScene.UnloadAsync();
|
||||
subScene.UnloadAsync().Completed += @base =>
|
||||
{
|
||||
_subScenes.Remove(location);
|
||||
_handlingScene.Remove(location);
|
||||
callBack?.Invoke();
|
||||
};
|
||||
|
||||
if (progressCallBack != null)
|
||||
{
|
||||
InvokeProgress(subScene, progressCallBack).Forget();
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -12,7 +12,7 @@ namespace TEngine
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = GameObject.FindObjectOfType<Settings>();
|
||||
_instance = Utility.Unity.FindObjectOfType<Settings>();
|
||||
|
||||
if (_instance != null)
|
||||
{
|
||||
@@ -44,7 +44,12 @@ namespace TEngine
|
||||
#if UNITY_EDITOR
|
||||
if (Instance == null)
|
||||
{
|
||||
return UnityEditor.AssetDatabase.LoadAssetAtPath<UpdateSetting>("Assets/TEngine/Settings/UpdateSetting.asset");
|
||||
string[] guids = UnityEditor.AssetDatabase.FindAssets("t:UpdateSetting");
|
||||
if (guids.Length >= 1)
|
||||
{
|
||||
string path = UnityEditor.AssetDatabase.GUIDToAssetPath(guids[0]);
|
||||
return UnityEditor.AssetDatabase.LoadAssetAtPath<UpdateSetting>(path);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return Instance.updateSetting;
|
||||
|
@@ -3,8 +3,12 @@
|
||||
"rootNamespace": "TEngine",
|
||||
"references": [
|
||||
"GUID:e34a5702dd353724aa315fb8011f08c3",
|
||||
"GUID:3fe1a3e70da50184f9897101cad7e4f2",
|
||||
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
||||
"GUID:6055be8ebefd69e48b49212b09b47b2f"
|
||||
"GUID:6055be8ebefd69e48b49212b09b47b2f",
|
||||
"GUID:5efd170ecd8084500bed5692932fe14e",
|
||||
"GUID:d7fc4d49301802c4d997d63a24928ab3",
|
||||
"GUID:75469ad4d38634e559750d17036d5f7c"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
@@ -13,6 +17,12 @@
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.inputsystem",
|
||||
"expression": "",
|
||||
"define": "ENABLE_INPUT_SYSTEM"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
@@ -24,6 +24,4 @@ MonoBehaviour:
|
||||
- Procedure.ProcedurePreload
|
||||
- Procedure.ProcedureSplash
|
||||
- Procedure.ProcedureStartGame
|
||||
- Procedure.ProcedureUpdateManifest
|
||||
- Procedure.ProcedureUpdateVersion
|
||||
entranceProcedureTypeName: Procedure.ProcedureLaunch
|
||||
|
@@ -21,10 +21,12 @@ MonoBehaviour:
|
||||
- System.dll
|
||||
- System.Core.dll
|
||||
- TEngine.Runtime.dll
|
||||
- UniTask.dll
|
||||
- YooAsset.dll
|
||||
LogicMainDllName: GameLogic.dll
|
||||
AssemblyTextAssetExtension: .bytes
|
||||
AssemblyTextAssetPath: AssetRaw/DLL
|
||||
UpdateStyle: 2
|
||||
UpdateStyle: 1
|
||||
UpdateNotice: 1
|
||||
ResDownLoadPath: http://127.0.0.1:8081
|
||||
FallbackResDownLoadPath: http://127.0.0.1:8082
|
||||
|
@@ -2,12 +2,130 @@
|
||||
|
||||
All notable changes to this package will be documented in this file.
|
||||
|
||||
## [2.3.8] - 2025-04-17
|
||||
|
||||
### Improvements
|
||||
|
||||
- 扩展工程里增加了“图集丢失变白块的解决方案”的相关代码。
|
||||
|
||||
### Fixed
|
||||
|
||||
- (#528) 修复了微信小游戏平台WXFSClearUnusedBundleFiles无法清理的问题。
|
||||
- (#531) 修复了微信小游戏平台WXFSClearUnusedBundleFiles没有适配BundleName_HashName命名方式。
|
||||
- (#533) 修复了Editor程序集下无法访问YooAsset.Editor程序集里的internal字段的问题。
|
||||
- (#534) 修复了资源报告窗口AssetView视图里,依赖资源包列表显示不准确的问题。
|
||||
|
||||
## [2.3.7] - 2025-04-01
|
||||
|
||||
### Improvements
|
||||
|
||||
- (#526) 运行时资源清单的哈希值验证兼容了MD5和CRC32两种方式。
|
||||
- (#515) 优化了资源路径大小写不敏感的逻辑代码,减少字符串操作产生的GC。
|
||||
- (#523) UnloadUnusedAssetsOperation方法支持了分帧处理。
|
||||
|
||||
### Fixed
|
||||
|
||||
- (#520) 修复了UWP平台获取WWW加载路径未适配的问题。
|
||||
|
||||
### Added
|
||||
|
||||
- 新增了文件系统初始化参数:INSTALL_CLEAR_MODE
|
||||
|
||||
```csharp
|
||||
/// <summary>
|
||||
/// 覆盖安装清理模式
|
||||
/// </summary>
|
||||
public enum EOverwriteInstallClearMode
|
||||
{
|
||||
/// <summary>
|
||||
/// 不做任何处理
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 清理所有缓存文件(包含资源文件和清单文件)
|
||||
/// </summary>
|
||||
ClearAllCacheFiles = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 清理所有缓存的资源文件
|
||||
/// </summary>
|
||||
ClearAllBundleFiles = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 清理所有缓存的清单文件
|
||||
/// </summary>
|
||||
ClearAllManifestFiles = 3,
|
||||
}
|
||||
```
|
||||
|
||||
- 新增了初始化参数:BundleLoadingMaxConcurrency
|
||||
|
||||
```csharp
|
||||
public abstract class InitializeParameters
|
||||
{
|
||||
/// <summary>
|
||||
/// 同时加载Bundle文件的最大并发数
|
||||
/// </summary>
|
||||
public int BundleLoadingMaxConcurrency = int.MaxValue;
|
||||
}
|
||||
```
|
||||
|
||||
## [2.3.6] - 2025-03-25
|
||||
|
||||
### Improvements
|
||||
|
||||
- 构建管线新增了TaskCreateCatalog任务节点。
|
||||
- 内置文件系统的catalog文件现在存储在streammingAssets目录下。
|
||||
|
||||
### Fixed
|
||||
|
||||
- (#486) 修复了微信小游戏文件系统调用ClearUnusedBundleFiles时候的异常。
|
||||
|
||||
## [2.3.5-preview] - 2025-03-14
|
||||
|
||||
### Fixed
|
||||
|
||||
- (#502) 修复了原生缓存文件由于文件格式变动导致的加载本地缓存文件失败的问题。
|
||||
- (#504) 修复了MacOS平台Offline Play Mode模式请求本地资源清单失败的问题。
|
||||
- (#506) 修复了v2.3x版本LoadAllAssets方法计算依赖Bundle不完整的问题。
|
||||
- (#506) 修复了微信小游戏文件系统,在启用加密算法后卸载bundle报错的问题。
|
||||
|
||||
## [2.3.4-preview] - 2025-03-08
|
||||
|
||||
### Improvements
|
||||
|
||||
- YooAsset支持了版本宏定义。
|
||||
|
||||
```csharp
|
||||
YOO_ASSET_2
|
||||
YOO_ASSET_2_3
|
||||
YOO_ASSET_2_3_OR_NEWER
|
||||
```
|
||||
|
||||
### Fixed
|
||||
|
||||
- (#389) 修复了禁用域重载(Reload Domain)的情况下,再次启动游戏报错的问题。
|
||||
- (#496) 修复了文件系统参数RESUME_DOWNLOAD_MINMUM_SIZE传入int值会导致异常的错误。
|
||||
- (#498) 修复了v2.3版本尝试加载安卓包内的原生资源包失败的问题。
|
||||
|
||||
### Added
|
||||
|
||||
- 新增了YooAssets.GetAllPackages()方法
|
||||
|
||||
```csharp
|
||||
/// <summary>
|
||||
/// 获取所有资源包裹
|
||||
/// </summary>
|
||||
public static List<ResourcePackage> GetAllPackages()
|
||||
```
|
||||
|
||||
## [2.3.3-preview] - 2025-03-06
|
||||
|
||||
### Improvements
|
||||
|
||||
- 新增了异步操作任务调试器,AssetBundleDebugger窗口-->OperationView视图模式
|
||||
- 编辑器下模拟构建默认启用依赖关系数据库,可以大幅增加编辑器下开始游戏时间。
|
||||
- 编辑器下模拟构建默认启用依赖关系数据库,可以大幅降低编辑器下启动游戏的时间。
|
||||
- 单元测试用例增加加密解密测试用例。
|
||||
|
||||
### Fixed
|
||||
|
8
UnityProject/Packages/YooAsset/Editor/Assembly.meta
Normal file
8
UnityProject/Packages/YooAsset/Editor/Assembly.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fab3cd742c11be2479b07f5d447a78c9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,5 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// 外部友元
|
||||
[assembly: InternalsVisibleTo("YooAsset.EditorExtension")]
|
||||
[assembly: InternalsVisibleTo("Assembly-CSharp-Editor")]
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ef774f01e50ab0a4d88122041938a6b9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,19 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if YOO_ASSET_EXPERIMENT
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class MacroDefine
|
||||
{
|
||||
/// <summary>
|
||||
/// YooAsset版本宏定义
|
||||
/// </summary>
|
||||
public static readonly List<string> Macros = new List<string>()
|
||||
{
|
||||
"YOO_ASSET_2",
|
||||
"YOO_ASSET_2_3",
|
||||
"YOO_ASSET_2_3_OR_NEWER",
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a61e5c2ca04aab647b1ed0492086aa8f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
106
UnityProject/Packages/YooAsset/Editor/Assembly/MacroProcessor.cs
Normal file
106
UnityProject/Packages/YooAsset/Editor/Assembly/MacroProcessor.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using UnityEditor;
|
||||
|
||||
#if YOO_ASSET_EXPERIMENT
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
public class MacroProcessor : AssetPostprocessor
|
||||
{
|
||||
static string OnGeneratedCSProject(string path, string content)
|
||||
{
|
||||
XmlDocument xmlDoc = new XmlDocument();
|
||||
xmlDoc.LoadXml(content);
|
||||
|
||||
if (IsCSProjectReferenced(xmlDoc.DocumentElement) == false)
|
||||
return content;
|
||||
|
||||
if (ProcessDefineConstants(xmlDoc.DocumentElement) == false)
|
||||
return content;
|
||||
|
||||
// 将修改后的XML结构重新输出为文本
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
var writerSettings = new XmlWriterSettings
|
||||
{
|
||||
Indent = true,
|
||||
Encoding = new UTF8Encoding(false), //无BOM
|
||||
OmitXmlDeclaration = false
|
||||
};
|
||||
|
||||
using (var xmlWriter = XmlWriter.Create(memoryStream, writerSettings))
|
||||
{
|
||||
xmlDoc.Save(xmlWriter);
|
||||
}
|
||||
return Encoding.UTF8.GetString(memoryStream.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理宏定义
|
||||
/// </summary>
|
||||
private static bool ProcessDefineConstants(XmlElement element)
|
||||
{
|
||||
if (element == null)
|
||||
return false;
|
||||
|
||||
bool processed = false;
|
||||
foreach (XmlNode node in element.ChildNodes)
|
||||
{
|
||||
if (node.Name != "PropertyGroup")
|
||||
continue;
|
||||
|
||||
foreach (XmlNode childNode in node.ChildNodes)
|
||||
{
|
||||
if (childNode.Name != "DefineConstants")
|
||||
continue;
|
||||
|
||||
string[] defines = childNode.InnerText.Split(';');
|
||||
HashSet<string> hashSets = new HashSet<string>(defines);
|
||||
foreach (string yooMacro in MacroDefine.Macros)
|
||||
{
|
||||
string tmpMacro = yooMacro.Trim();
|
||||
if (hashSets.Contains(tmpMacro) == false)
|
||||
hashSets.Add(tmpMacro);
|
||||
}
|
||||
childNode.InnerText = string.Join(";", hashSets.ToArray());
|
||||
processed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测工程是否引用了YooAsset
|
||||
/// </summary>
|
||||
private static bool IsCSProjectReferenced(XmlElement element)
|
||||
{
|
||||
if (element == null)
|
||||
return false;
|
||||
|
||||
foreach (XmlNode node in element.ChildNodes)
|
||||
{
|
||||
if (node.Name != "ItemGroup")
|
||||
continue;
|
||||
|
||||
foreach (XmlNode childNode in node.ChildNodes)
|
||||
{
|
||||
if (childNode.Name != "Reference" && childNode.Name != "ProjectReference")
|
||||
continue;
|
||||
|
||||
string include = childNode.Attributes["Include"].Value;
|
||||
if (include.Contains("YooAsset"))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88d5a41d078a82e40b82265ed4c3631a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
115
UnityProject/Packages/YooAsset/Editor/Assembly/RspGenerator.cs
Normal file
115
UnityProject/Packages/YooAsset/Editor/Assembly/RspGenerator.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
#if YOO_ASSET_EXPERIMENT
|
||||
namespace YooAsset.Editor.Experiment
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
public class RspGenerator
|
||||
{
|
||||
// csc.rsp文件路径
|
||||
private static string RspFilePath => Path.Combine(Application.dataPath, "csc.rsp");
|
||||
|
||||
static RspGenerator()
|
||||
{
|
||||
UpdateRspFile(MacroDefine.Macros, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新csc.rsp文件
|
||||
/// </summary>
|
||||
private static void UpdateRspFile(List<string> addMacros, List<string> removeMacros)
|
||||
{
|
||||
var existingDefines = new HashSet<string>();
|
||||
var otherLines = new List<string>();
|
||||
|
||||
// 1. 读取现有内容
|
||||
ReadRspFile(existingDefines, otherLines);
|
||||
|
||||
// 2. 添加新宏
|
||||
if (addMacros != null && addMacros.Count > 0)
|
||||
{
|
||||
addMacros.ForEach(x =>
|
||||
{
|
||||
if (existingDefines.Contains(x) == false)
|
||||
existingDefines.Add(x);
|
||||
});
|
||||
}
|
||||
|
||||
// 3. 移除指定宏
|
||||
if (removeMacros != null && removeMacros.Count > 0)
|
||||
{
|
||||
removeMacros.ForEach(x =>
|
||||
{
|
||||
existingDefines.Remove(x);
|
||||
});
|
||||
}
|
||||
|
||||
// 4. 重新生成内容
|
||||
WriteRspFile(existingDefines, otherLines);
|
||||
|
||||
// 5. 刷新AssetDatabase
|
||||
AssetDatabase.Refresh();
|
||||
EditorUtility.RequestScriptReload();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取csc.rsp文件,返回宏定义和其他行
|
||||
/// </summary>
|
||||
private static void ReadRspFile(HashSet<string> defines, List<string> others)
|
||||
{
|
||||
if (defines == null)
|
||||
defines = new HashSet<string>();
|
||||
|
||||
if (others == null)
|
||||
others = new List<string>();
|
||||
|
||||
if (File.Exists(RspFilePath) == false)
|
||||
return;
|
||||
|
||||
foreach (string line in File.ReadAllLines(RspFilePath))
|
||||
{
|
||||
if (line.StartsWith("-define:"))
|
||||
{
|
||||
string[] parts = line.Split(new[] { ':' }, 2);
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
defines.Add(parts[1].Trim());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
others.Add(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重新写入csc.rsp文件
|
||||
/// </summary>
|
||||
private static void WriteRspFile(HashSet<string> defines, List<string> others)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (others != null && others.Count > 0)
|
||||
{
|
||||
others.ForEach(o => sb.AppendLine(o));
|
||||
}
|
||||
|
||||
if (defines != null && defines.Count > 0)
|
||||
{
|
||||
foreach (string define in defines)
|
||||
{
|
||||
sb.AppendLine($"-define:{define}");
|
||||
}
|
||||
}
|
||||
|
||||
File.WriteAllText(RspFilePath, sb.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c2662e1d33b1eea469695b68d18b1739
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -32,8 +32,9 @@ namespace YooAsset.Editor
|
||||
var buildParametersContext = new BuildParametersContext(buildParameters);
|
||||
_buildContext.SetContextObject(buildParametersContext);
|
||||
|
||||
// 初始化日志
|
||||
BuildLogger.InitLogger(enableLog);
|
||||
// 初始化日志系统
|
||||
string logFilePath = $"{buildParametersContext.GetPipelineOutputDirectory()}/buildInfo.log";
|
||||
BuildLogger.InitLogger(enableLog, logFilePath);
|
||||
|
||||
// 执行构建流程
|
||||
BuildLogger.Log($"Begin to build package : {buildParameters.PackageName} by {buildParameters.BuildPipeline}");
|
||||
@@ -50,6 +51,9 @@ namespace YooAsset.Editor
|
||||
BuildLogger.Error(buildResult.ErrorInfo);
|
||||
}
|
||||
|
||||
// 关闭日志系统
|
||||
BuildLogger.Shuntdown();
|
||||
|
||||
return buildResult;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class TaskCreateCatalog
|
||||
{
|
||||
/// <summary>
|
||||
/// 生成内置资源记录文件
|
||||
/// </summary>
|
||||
internal void CreateCatalogFile(BuildParametersContext buildParametersContext)
|
||||
{
|
||||
string buildinRootDirectory = buildParametersContext.GetBuildinRootDirectory();
|
||||
string buildPackageName = buildParametersContext.Parameters.PackageName;
|
||||
DefaultBuildinFileSystemBuild.CreateBuildinCatalogFile(buildPackageName, buildinRootDirectory);
|
||||
|
||||
// 刷新目录
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d2c835e5e40ca34d93480587c8125df
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -30,7 +30,7 @@ namespace YooAsset.Editor
|
||||
|
||||
// 创建新补丁清单
|
||||
PackageManifest manifest = new PackageManifest();
|
||||
manifest.FileVersion = YooAssetSettings.ManifestFileVersion;
|
||||
manifest.FileVersion = ManifestDefine.FileVersion;
|
||||
manifest.EnableAddressable = buildMapContext.Command.EnableAddressable;
|
||||
manifest.LocationToLower = buildMapContext.Command.LocationToLower;
|
||||
manifest.IncludeAssetGUID = buildMapContext.Command.IncludeAssetGUID;
|
||||
|
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class TaskCreateCatalog_BBP : TaskCreateCatalog, IBuildTask
|
||||
{
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||
if (buildParametersContext.Parameters.BuildinFileCopyOption != EBuildinFileCopyOption.None)
|
||||
{
|
||||
CreateCatalogFile(buildParametersContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8fe3d00b03dc9c64a96b7acfdf99b54c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -36,6 +36,7 @@ namespace YooAsset.Editor
|
||||
new TaskCreateReport_BBP(),
|
||||
new TaskCreatePackage_BBP(),
|
||||
new TaskCopyBuildinFiles_BBP(),
|
||||
new TaskCreateCatalog_BBP()
|
||||
};
|
||||
return pipeline;
|
||||
}
|
||||
|
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class TaskCreateCatalog_RFBP : TaskCreateCatalog, IBuildTask
|
||||
{
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||
if (buildParametersContext.Parameters.BuildinFileCopyOption != EBuildinFileCopyOption.None)
|
||||
{
|
||||
CreateCatalogFile(buildParametersContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 563771ecaff17ee498b5fda7c1132e62
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -38,6 +38,7 @@ namespace YooAsset.Editor
|
||||
new TaskCreateReport_RFBP(),
|
||||
new TaskCreatePackage_RFBP(),
|
||||
new TaskCopyBuildinFiles_RFBP(),
|
||||
new TaskCreateCatalog_RFBP()
|
||||
};
|
||||
return pipeline;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user