文件系统安卓适配
This commit is contained in:
@@ -13,7 +13,6 @@ namespace AibisDream.Kit
|
||||
{
|
||||
public class ConfigUtil : SingletonBase<ConfigUtil>
|
||||
{
|
||||
private const string CharacterConfigPath = "/Config/character.csv";
|
||||
private const string SpriteGroupPath = "/Config/sprite_group.json";
|
||||
|
||||
private Dictionary<string, Character> _characters;
|
||||
@@ -42,12 +41,12 @@ namespace AibisDream.Kit
|
||||
public override void OnSingletonInit()
|
||||
{
|
||||
InitCharacterConfig();
|
||||
InitSpriteGroupConfig();
|
||||
// InitSpriteGroupConfig();
|
||||
}
|
||||
|
||||
private void InitCharacterConfig()
|
||||
{
|
||||
var characterList = CsvUtil.ReadAsBean<Character>(Application.streamingAssetsPath + CharacterConfigPath);
|
||||
var characterList = CsvUtil.ReadAsBean<Character>(ConstRef.CharacterConfigPath);
|
||||
_characters = characterList.ToDictionary(item => item.Key, item => item);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AibisDream.Kit
|
||||
@@ -14,7 +15,7 @@ namespace AibisDream.Kit
|
||||
/// <summary>
|
||||
/// 日志文件路径
|
||||
/// </summary>
|
||||
public static string LogPath => Application.streamingAssetsPath + "/LogFile";
|
||||
public static string LogPath => Path.Combine(Application.streamingAssetsPath, "LogFile");
|
||||
|
||||
/// <summary>
|
||||
/// 日志保存最近几天的内容
|
||||
@@ -32,7 +33,7 @@ namespace AibisDream.Kit
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
#if !UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS
|
||||
DontDestroyOnLoad(gameObject);
|
||||
_fileLogger = new FileLogger(LogFileName, LogPath, SaveDays);
|
||||
LogMessage($"Ver.{Application.version}", "", LogType.Log);
|
||||
|
||||
@@ -112,7 +112,9 @@ namespace AibisDream
|
||||
|
||||
public void SaveUnloadChapters()
|
||||
{
|
||||
#if !UNITY_ANDROID || UNITY_EDITOR
|
||||
JsonUtil.SaveArray(unlockedChapterList.ToArray(), ConstRef.ChapterProgressPath);
|
||||
#endif
|
||||
}
|
||||
|
||||
public bool TryGetSaveFilePath(out string saveFilePath)
|
||||
|
||||
@@ -4,6 +4,7 @@ using AibisDream.Framework;
|
||||
using AibisDream.Kit;
|
||||
using AibisDream.UI;
|
||||
using UnityEngine;
|
||||
using System.IO;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
@@ -12,7 +13,7 @@ namespace AibisDream
|
||||
/// </summary>
|
||||
public class SettingLoader
|
||||
{
|
||||
private static readonly string SettingPath = Application.streamingAssetsPath + "/Config/setting.json";
|
||||
private static readonly string SettingPath = Path.Combine(Application.streamingAssetsPath, "Config", "setting.json");
|
||||
|
||||
private readonly ConfigContainer _container;
|
||||
|
||||
|
||||
@@ -23,6 +23,9 @@ namespace AibisDream
|
||||
|
||||
private void InitCursor()
|
||||
{
|
||||
#if UNITY_ANDROID || UNITY_IOS
|
||||
_cursor.gameObject.SetActive(false);
|
||||
#endif
|
||||
Cursor.visible = false;
|
||||
_cursor.sprite = defaultCursor;
|
||||
}
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace AibisDream.UI
|
||||
{
|
||||
public class SavesPanel : MonoBehaviour, IUIPanel
|
||||
{
|
||||
public bool IsOpen => gameObject.activeSelf;
|
||||
public bool IsCloseable => true;
|
||||
|
||||
private static readonly string SaveFilePath = Application.streamingAssetsPath + "/SaveFiles";
|
||||
|
||||
#region 索引
|
||||
public Button buttonPrefab;
|
||||
public Transform buttonParent;
|
||||
#endregion
|
||||
|
||||
#region 打开和关闭
|
||||
|
||||
public void Show()
|
||||
{
|
||||
InitLevelBtn();
|
||||
gameObject.SetActive(true);
|
||||
RegisterButton();
|
||||
}
|
||||
|
||||
public void Hide()
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
UnRegisterButton();
|
||||
}
|
||||
|
||||
private void RegisterButton()
|
||||
{
|
||||
var returnBtn = transform.Find("Return").GetComponent<Button>();
|
||||
returnBtn.onClick.AddListener(() => UIManager.Instance.HidePanel<SavesPanel>());
|
||||
}
|
||||
|
||||
private void UnRegisterButton()
|
||||
{
|
||||
var returnBtn = transform.Find("Return").GetComponent<Button>();
|
||||
returnBtn.onClick.RemoveAllListeners();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void InitLevelBtn()
|
||||
{
|
||||
// 清空旧按钮
|
||||
foreach (Transform child in buttonParent)
|
||||
{
|
||||
Destroy(child.gameObject);
|
||||
}
|
||||
|
||||
// 加载存档文件
|
||||
string[] saveFiles = Directory.GetFiles(SaveFilePath, "*.json");
|
||||
var orderedSaveFiles = saveFiles.OrderByDescending(item => item).ToArray();
|
||||
foreach (var saveFile in orderedSaveFiles)
|
||||
{
|
||||
var button = Instantiate(buttonPrefab, buttonParent);
|
||||
button.GetComponentInChildren<TMP_Text>().text = Path.GetFileNameWithoutExtension(saveFile);
|
||||
button.onClick.AddListener(() => OnSaveFileSelected(saveFile));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSaveFileSelected(string saveFileName)
|
||||
{
|
||||
// 隐藏UI
|
||||
gameObject.SetActive(false);
|
||||
// 开始游戏
|
||||
GameManager.Instance.StartWithSaveFile(saveFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bdd86c19be1449ca9e2783eb714fb8ff
|
||||
timeCreated: 1745572533
|
||||
@@ -1,59 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
public class SaveFileUIController : MonoBehaviour
|
||||
{
|
||||
private static readonly string SaveFilePath = Application.streamingAssetsPath + "/SaveFiles";
|
||||
|
||||
#region 索引
|
||||
public Button buttonPrefab;
|
||||
public Transform buttonParent;
|
||||
public Button returnButton;
|
||||
#endregion
|
||||
|
||||
private void Start()
|
||||
{
|
||||
returnButton.onClick.AddListener(HideSaveFileUI);
|
||||
}
|
||||
|
||||
public void ShowSaveFileUI()
|
||||
{
|
||||
// 清空旧按钮
|
||||
foreach (Transform child in buttonParent)
|
||||
{
|
||||
Destroy(child.gameObject);
|
||||
}
|
||||
|
||||
// 加载存档文件
|
||||
string[] saveFiles = Directory.GetFiles(SaveFilePath, "*.json");
|
||||
var orderedSaveFiles = saveFiles.OrderByDescending(item => item).ToArray();
|
||||
foreach (var saveFile in orderedSaveFiles)
|
||||
{
|
||||
var button = Instantiate(buttonPrefab, buttonParent);
|
||||
button.GetComponentInChildren<TMP_Text>().text = Path.GetFileNameWithoutExtension(saveFile);
|
||||
button.onClick.AddListener(() => OnSaveFileSelected(saveFile));
|
||||
}
|
||||
|
||||
gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
private void OnSaveFileSelected(string saveFileName)
|
||||
{
|
||||
// 隐藏UI
|
||||
gameObject.SetActive(false);
|
||||
// 开始游戏
|
||||
// GameLoopManager.Instance.StartWithSaveFile(saveFileName);
|
||||
}
|
||||
|
||||
private void HideSaveFileUI()
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a351e509c8dd5944f9e6406f59ea5c0b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,4 +1,5 @@
|
||||
using UnityEngine;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AibisDream.Utility
|
||||
{
|
||||
@@ -23,10 +24,12 @@ 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");
|
||||
|
||||
#region 本地化索引
|
||||
|
||||
|
||||
@@ -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无标题");
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user