安卓优化

This commit is contained in:
2025-12-22 21:10:37 +08:00
parent 0cd5c55789
commit 43cad617af
29 changed files with 11047 additions and 4877 deletions
+21 -13
View File
@@ -1,9 +1,10 @@
using System;
using UnityEngine;
using AibisDream.Utility;
namespace AibisDream.Kit
{
internal class LogKit : MonoBehaviour
internal static class LogKit
{
/// <summary>
/// 文件名称格式
@@ -11,11 +12,6 @@ namespace AibisDream.Kit
/// </summary>
public static string LogFileName => "Log{0:_yyyy_MM_dd}.txt";
/// <summary>
/// 日志文件路径
/// </summary>
public static string LogPath => Application.streamingAssetsPath + "/LogFile";
/// <summary>
/// 日志保存最近几天的内容
/// </summary>
@@ -26,29 +22,41 @@ namespace AibisDream.Kit
/// </summary>
private static string LogContent => Time + ": {0}\n{1}";
private FileLogger _fileLogger;
private static FileLogger _fileLogger;
private static bool _isInitialized;
private static string Time => DateTime.Now.ToString("[HH:mm:ss.fffd]");
private void Awake()
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Initialize()
{
#if !UNITY_EDITOR
DontDestroyOnLoad(gameObject);
_fileLogger = new FileLogger(LogFileName, LogPath, SaveDays, Application.version);
if (_isInitialized)
return;
_fileLogger = new FileLogger(LogFileName, ConstRef.LogFilePath, SaveDays);
LogMessage($"Ver.{Application.version}", "", LogType.Log);
Application.logMessageReceivedThreaded += LogMessage;
Application.quitting += Shutdown;
_isInitialized = true;
#endif
}
private void LogMessage(string condition, string stackTrace, LogType type)
private static void LogMessage(string condition, string stackTrace, LogType type)
{
_fileLogger?.Write(string.Format(LogContent, condition, stackTrace));
}
private void OnDestroy()
private static void Shutdown()
{
if (!_isInitialized)
return;
Application.logMessageReceivedThreaded -= LogMessage;
Application.quitting -= Shutdown;
_fileLogger?.OnDestroy();
_fileLogger = null;
Application.logMessageReceivedThreaded -= LogMessage;
_isInitialized = false;
}
}
}
+46 -1
View File
@@ -4,6 +4,8 @@ using AibisDream.Framework;
using AibisDream.Kit;
using AibisDream.UI;
using UnityEngine;
using System.IO;
using AibisDream.Utility;
namespace AibisDream
{
@@ -12,12 +14,15 @@ namespace AibisDream
/// </summary>
public class SettingLoader
{
private static readonly string SettingPath = Application.streamingAssetsPath + "/Config/setting.json";
private static readonly string SettingPath = Path.Combine(Application.persistentDataPath, "AllOurBrokenParts", "Config", "setting.json");
private static readonly string SettingDefaultPath = Path.Combine(Application.streamingAssetsPath, "Config", "setting.json");
private readonly ConfigContainer _container;
private SettingLoader()
{
// 初始化设置文件(如果不存在)
InitSettingFile();
// 读取数据
_container = new ConfigContainer(SettingPath);
LoadAllSetting();
@@ -30,6 +35,44 @@ namespace AibisDream
_container.OnWrite -= OnSettingChanged;
}
private void InitSettingFile()
{
// 如果文件存在,则直接返回
if (File.Exists(SettingPath))
{
return;
}
// 如果文件不存在,则复制默认设置并根据系统语言设置初始语言值
var defaultSetting = JsonUtil.ReadJObject(SettingDefaultPath);
// 根据当前系统语言设置初始语言值
string systemLanguage = GetLanguageBySystemLanguage();
defaultSetting["Language"] = systemLanguage;
// 保存设置文件
JsonUtil.SaveJObject(defaultSetting, SettingPath);
}
/// <summary>
/// 根据系统语言获取对应的语言代码
/// </summary>
/// <returns>语言代码:zh-Hans、en、ja-JP,默认返回 en</returns>
private string GetLanguageBySystemLanguage()
{
SystemLanguage systemLang = Application.systemLanguage;
return systemLang switch
{
SystemLanguage.Chinese => "zh-Hans",
SystemLanguage.ChineseSimplified => "zh-Hans",
SystemLanguage.ChineseTraditional => "zh-Hans",
SystemLanguage.Japanese => "ja-JP",
SystemLanguage.English => "en",
_ => "en",
};
}
private void LoadAllSetting()
{
var settingConfig = _container.ReadAll();
@@ -55,7 +98,9 @@ namespace AibisDream
break;
case "WindowMode":
// 屏幕模式
#if !UNITY_ANDROID && !UNITY_IOS
GameManager.Instance.SetScreenMode(value);
#endif
break;
case "Language":
// 确保本地化系统已初始化
+11
View File
@@ -5,6 +5,7 @@ namespace AibisDream.UI
public class InfoPanel : MonoBehaviour, IUIPanel
{
[SerializeField] private DemoTimer demoTimer;
[SerializeField] private GameObject loading;
[SerializeField] private VariableBar variableBar;
public void SetTimerActive(bool isOpen)
@@ -35,6 +36,16 @@ namespace AibisDream.UI
gameObject.SetActive(false);
}
public void ShowLoading()
{
loading.SetActive(true);
}
public void HideLoading()
{
loading.SetActive(false);
}
public bool IsOpen => gameObject.activeSelf;
public bool IsCloseable => false;
+11 -9
View File
@@ -1,3 +1,4 @@
using System.IO;
using UnityEngine;
namespace AibisDream.Utility
@@ -14,6 +15,7 @@ namespace AibisDream.Utility
public const string SurveyURL_CN = "https://jsj.top/f/HkmCnH";
public const string SurveyURL_EN = "https://jsj.top/f/y501LX";
public const string SurveyURL_JP = "https://jsj.top/f/icnVug";
public const string WishlistURL = "https://store.steampowered.com/app/3473430/_All_Our_Broken_Parts?utm_source=playtest";
@@ -22,14 +24,18 @@ namespace AibisDream.Utility
#if UnityEditor
public static readonly string SaveFilePath = Application.persistentDataPath + "/SaveFiles/";
#else
public static readonly string SaveFilePath = Application.persistentDataPath + "/AllOurBrokenParts/saves/";
public static readonly string SaveFilePath = Path.Combine(Application.persistentDataPath, "AllOurBrokenParts", "saves");
#endif
public static readonly string ChapterProgressPath = $"{Application.streamingAssetsPath}/Config/chapter.json";
public static readonly string ChapterProgressPath = Path.Combine(Application.persistentDataPath, "AllOurBrokenParts", "Config", "chapter.json");
public static readonly string CharacterConfigPath = Path.Combine(Application.streamingAssetsPath, "Config", "character.csv");
public static readonly string LogFilePath = Path.Combine(Application.persistentDataPath, "LogFile");
public static readonly string BlockPuzzleDataPath = Path.Combine(Application.streamingAssetsPath, "LevelData", "BlockPuzzle", "BlockPuzzleData.json");
public static readonly string BlockShapeDataPath = Path.Combine(Application.streamingAssetsPath, "LevelData", "BlockPuzzle", "BlockShapeData.json");
public static readonly string BlockShapeDataPath = $"{Application.streamingAssetsPath}/LevelData/BlockPuzzle/BlockShapeData.json";
public static readonly string BlockPuzzleDataPath = $"{Application.streamingAssetsPath}/LevelData/BlockPuzzle/BlockPuzzleData.json";
#region
@@ -63,10 +69,6 @@ namespace AibisDream.Utility
public const string RecordPrefab = "RecordItem";
public const string BlockShapePrefab = "BlockShape";
public const string ShapeCreateButtonPrefab = "ShapeCreateButton";
#endregion
#region
@@ -82,7 +84,7 @@ namespace AibisDream.Utility
public const int CharacterDelayTime = 70;
public const int LineMaxDelay = 2800;
public const int LineMinDelay = 600;
public const int AutoHideDelay = 300;
public const int AutoHideDelay = 150;
public const int FixedDelay = 200;
#endregion
+92 -12
View File
@@ -9,6 +9,8 @@ using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using UnityEngine;
using UnityEngine.Networking;
namespace AibisDream.Utility
{
@@ -20,13 +22,89 @@ namespace AibisDream.Utility
// 默认分隔符
private const char FieldSeparator = ',';
/// <summary>
/// 根据平台读取文件内容
/// </summary>
private static string ReadFileText(string filePath)
{
#if UNITY_ANDROID && !UNITY_EDITOR
// Android 平台需要使用 UnityWebRequest 读取 StreamingAssets
if (filePath.Contains(Application.streamingAssetsPath))
{
// Android 上 StreamingAssets 在 APK 中,需要构建正确的 URL
string url = filePath;
// 确保使用正确的路径分隔符
url = url.Replace("\\", "/");
// 如果路径不包含协议前缀,添加 file://
if (!url.StartsWith("file://") && !url.StartsWith("jar:file://"))
{
// 对于 Android APK 中的文件,使用 jar:file:// 协议
string relativePath = url.Replace(Application.streamingAssetsPath, "").TrimStart('/');
url = "jar:file://" + Application.dataPath + "!/assets/" + relativePath;
}
using (UnityWebRequest www = UnityWebRequest.Get(url))
{
www.SendWebRequest();
// 等待请求完成(同步等待)
while (!www.isDone)
{
// 在主线程中等待
}
if (www.result == UnityWebRequest.Result.Success)
{
return www.downloadHandler.text;
}
else
{
throw new IOException($"无法读取文件: {filePath}, URL: {url}, 错误: {www.error}");
}
}
}
else
{
// 非 StreamingAssets 路径,使用普通文件读取
return File.ReadAllText(filePath, DefaultEncode);
}
#else
// 其他平台直接使用 File 类
return File.ReadAllText(filePath, DefaultEncode);
#endif
}
/// <summary>
/// 根据平台创建 StreamReader
/// </summary>
private static StreamReader CreateStreamReader(string filePath)
{
#if UNITY_ANDROID && !UNITY_EDITOR
// Android 平台需要使用 UnityWebRequest 读取 StreamingAssets
if (filePath.Contains(Application.streamingAssetsPath))
{
string fileText = ReadFileText(filePath);
MemoryStream stream = new MemoryStream(DefaultEncode.GetBytes(fileText));
return new StreamReader(stream, DefaultEncode);
}
else
{
// 非 StreamingAssets 路径,使用普通文件读取
return new StreamReader(filePath, DefaultEncode);
}
#else
// 其他平台直接使用 File 类
return new StreamReader(filePath, DefaultEncode);
#endif
}
public static List<string[]> Read(string filePath)
{
List<string[]> dataList = new List<string[]>();
StreamReader reader;
StreamReader reader = null;
try
{
using (reader = new StreamReader(filePath, DefaultEncode))
using (reader = CreateStreamReader(filePath))
{
while (!reader.EndOfStream)
{
@@ -48,7 +126,7 @@ namespace AibisDream.Utility
GC.Collect();
Thread.Sleep(50);
Console.WriteLine(ex.StackTrace);
using (reader = new StreamReader(filePath, DefaultEncode))
using (reader = CreateStreamReader(filePath))
{
while (!reader.EndOfStream)
{
@@ -59,8 +137,10 @@ namespace AibisDream.Utility
}
}
}
reader.Close();
finally
{
reader?.Close();
}
return dataList;
}
@@ -82,7 +162,7 @@ namespace AibisDream.Utility
var props = targetType.GetProperties();
// 读取CSV
using var reader = new StreamReader(filePath, DefaultEncode);
using var reader = CreateStreamReader(filePath);
// 第一行是注释
reader.ReadLine();
@@ -90,7 +170,7 @@ namespace AibisDream.Utility
var titles = reader.ReadLine()?.Split(FieldSeparator);
if (titles == null)
{
Debug.WriteLine("csv无标题");
System.Diagnostics.Debug.WriteLine("csv无标题");
throw new Exception("csv无标题");
}
@@ -100,7 +180,7 @@ namespace AibisDream.Utility
{
string newLine = reader.ReadLine();
if (string.IsNullOrEmpty(newLine)) break;
string[] rowData = newLine.Split(FieldSeparator);
if (rowData == null || rowData.Length == 0) continue;
@@ -109,13 +189,13 @@ namespace AibisDream.Utility
foreach (var prop in props)
{
string name = prop.Name;
if (!titles.Contains(prop.Name))
if (!titles.Contains(prop.Name))
continue;
int idx = Array.IndexOf(titles, prop.Name);
prop.SetValue(obj, GetDefaultValue(prop, rowData[idx]));
}
res.Add(obj as T);
}
@@ -130,7 +210,7 @@ namespace AibisDream.Utility
{
bool blnFlag = true;
StreamReader reader = new StreamReader(strPath, DefaultEncode);
StreamReader reader = CreateStreamReader(strPath);
myCsvDt = new DataTable();
while (reader.ReadLine() is { } strLine)
{
@@ -218,7 +298,7 @@ namespace AibisDream.Utility
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
System.Diagnostics.Debug.WriteLine(ex.Message);
sw.Close();
}
}
+63 -6
View File
@@ -4,6 +4,8 @@ using System.IO;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;
using UnityEngine.Networking;
namespace AibisDream.Utility
{
@@ -11,6 +13,58 @@ namespace AibisDream.Utility
{
public const string JsonSuffix = ".json";
/// <summary>
/// 根据平台读取文件内容
/// </summary>
private static string ReadFileText(string filePath)
{
#if UNITY_ANDROID && !UNITY_EDITOR
// Android 平台需要使用 UnityWebRequest 读取 StreamingAssets
if (filePath.Contains(Application.streamingAssetsPath))
{
// Android 上 StreamingAssets 在 APK 中,需要构建正确的 URL
string url = filePath;
// 确保使用正确的路径分隔符
url = url.Replace("\\", "/");
// 如果路径不包含协议前缀,添加 file://
if (!url.StartsWith("file://") && !url.StartsWith("jar:file://"))
{
// 对于 Android APK 中的文件,使用 jar:file:// 协议
string relativePath = url.Replace(Application.streamingAssetsPath, "").TrimStart('/');
url = "jar:file://" + Application.dataPath + "!/assets/" + relativePath;
}
using (UnityWebRequest www = UnityWebRequest.Get(url))
{
www.SendWebRequest();
// 等待请求完成(同步等待)
while (!www.isDone)
{
// 在主线程中等待
}
if (www.result == UnityWebRequest.Result.Success)
{
return www.downloadHandler.text;
}
else
{
throw new IOException($"无法读取文件: {filePath}, URL: {url}, 错误: {www.error}");
}
}
}
else
{
// 非 StreamingAssets 路径,使用普通文件读取
return File.ReadAllText(filePath);
}
#else
// 其他平台直接使用 File 类
return File.ReadAllText(filePath);
#endif
}
/// <summary>
/// 按路径和Key加载
/// </summary>
@@ -21,7 +75,7 @@ namespace AibisDream.Utility
/// <exception cref="Exception">错误</exception>
public static T ReadBean<T>(string path, string key)
{
string json = File.ReadAllText(path);
string json = ReadFileText(path);
JObject jObject = JObject.Parse(json);
if (jObject.ContainsKey(key))
@@ -40,7 +94,7 @@ namespace AibisDream.Utility
/// <returns></returns>
public static T ReadBean<T>(string path)
{
string json = File.ReadAllText(path);
string json = ReadFileText(path);
return JsonConvert.DeserializeObject<T>(json);
}
@@ -61,7 +115,7 @@ namespace AibisDream.Utility
/// <returns>目标Bean</returns>
public static T[] ReadBeanArray<T>(string path)
{
string json = File.ReadAllText(path);
string json = ReadFileText(path);
return JsonConvert.DeserializeObject<T[]>(json);
}
@@ -73,7 +127,7 @@ namespace AibisDream.Utility
/// <returns>目标Bean</returns>
public static Dictionary<string, T> ReadBeanDict<T>(string path)
{
string json = File.ReadAllText(path);
string json = ReadFileText(path);
return JsonConvert.DeserializeObject<Dictionary<string, T>>(json);
}
@@ -84,7 +138,7 @@ namespace AibisDream.Utility
/// <returns>key列表</returns>
public static string[] ReadKeys(string path)
{
string json = File.ReadAllText(path);
string json = ReadFileText(path);
JObject jObject = JObject.Parse(json);
return jObject.Properties().Select(jProp => jProp.Name).ToArray();
@@ -92,7 +146,7 @@ namespace AibisDream.Utility
public static JObject ReadJObject(string path)
{
string json = File.ReadAllText(FormatAsJsonPath(path), System.Text.Encoding.UTF8);
string json = ReadFileText(FormatAsJsonPath(path));
return JObject.Parse(json);
}
@@ -105,18 +159,21 @@ namespace AibisDream.Utility
public static void SaveBean<T>(T bean, string path)
{
string json = JsonConvert.SerializeObject(bean);
Directory.CreateDirectory(Path.GetDirectoryName(path));
File.WriteAllText(path, json);
}
public static void SaveJObject(JObject jObject, string path)
{
string json = jObject.ToString();
Directory.CreateDirectory(Path.GetDirectoryName(path));
File.WriteAllText(FormatAsJsonPath(path), json);
}
public static void SaveArray<T>(T[] array, string path)
{
string json = JsonConvert.SerializeObject(array);
Directory.CreateDirectory(Path.GetDirectoryName(path));
File.WriteAllText(FormatAsJsonPath(path), json);
}