using UnityEngine;
|
using System.Collections;
|
using System.Collections.Generic;
|
using Cysharp.Threading.Tasks;
|
using System;
|
using UnityEngine.U2D;
|
using LitJson;
|
using System.IO;
|
using UnityEngine.Networking;
|
|
#if UNITY_EDITOR
|
using UnityEditor;
|
#endif
|
|
using LaunchCommon;
|
|
|
// 热更新前的代码
|
|
public class LocalResManager : Singleton<LocalResManager>
|
{
|
//不下载时本地安卓测试路径
|
public string assetBundlesPath = Application.dataPath + "/../AssetBundles/Android/";
|
public static string bytesFolderName = "logicbytes/";
|
public string StreamingAssetPath
|
{
|
get
|
{
|
return ResourcesPath.Instance.StreamingAssetPath;
|
}
|
}
|
public string ExternalStorePath
|
{
|
get
|
{
|
return ResourcesPath.Instance.ExternalStorePath;
|
}
|
}
|
|
//用于editor 下的资源路径
|
public string ResourcesOutPath
|
{
|
get
|
{
|
return ResourcesPath.ResourcesOutPath;
|
}
|
}
|
|
public string CONFIG_FODLER
|
{
|
get
|
{
|
return ResourcesPath.CONFIG_FODLER;
|
}
|
}
|
|
public string ResourcesOutAssetPath
|
{
|
get
|
{
|
return ResourcesPath.ResourcesOutAssetPath;
|
}
|
}
|
|
public bool isPCTestDownLoad = false;
|
|
public static int downLoadCount = 0;
|
|
public static readonly string[] VERSION_URL = new string[] {
|
"http://gamecenter.secondworld.net.cn:11000/center/appversion_new.php/?"};
|
|
public int debugBranch { get; private set; }
|
|
private int urlIndex = 0;
|
|
private string versionUrl;
|
|
public VersionInfo versionInfo { get; private set; }
|
|
private static LoadDllStep m_step;
|
|
public static LoadDllStep step
|
{
|
get { return m_step; }
|
set
|
{
|
m_step = value;
|
Debug.Log("LoadDllStep:" + m_step);
|
}
|
}
|
|
string assetBytesUrl;
|
|
//从网络获取的资源版本信息
|
public Dictionary<string, AssetVersion> assetVersions = new Dictionary<string, AssetVersion>();
|
|
//本地LogicBytes文件和 assetVersions 比较是否需要下载
|
public Dictionary<string, AssetVersion> localAssetVersions = new Dictionary<string, AssetVersion>();
|
|
public static string versionUrlResult { get; private set; }
|
|
/// <summary>
|
/// 语言的ID,用于区分下载资源
|
/// </summary>
|
/// <value></value>
|
public static string Id
|
{
|
get
|
{
|
var config = InitialFunctionConfig.Get("Language").Numerical1;
|
if (string.IsNullOrEmpty(config))
|
return "";
|
return LocalSave.GetString("LANGUAGE_ID1");
|
}
|
set
|
{
|
LocalSave.SetString("LANGUAGE_ID1", value);
|
}
|
}
|
|
//默认路径不附加地址,Id不为空时附加Id
|
public static string fixPath
|
{
|
get
|
{
|
if (string.IsNullOrEmpty(Id))
|
return "";
|
return string.Format("/{0}", Id);
|
}
|
}
|
|
private AssetBundle spriteBundle = null; //需要卸载
|
private AssetBundle prefabBundle = null; //需要卸载
|
private SpriteAtlas spriteAtlas = null;
|
|
public void Init()
|
{
|
if (LocalSave.GetString("#@#BrancH") != string.Empty)
|
{
|
int tmpbranch;
|
int.TryParse(LocalSave.GetString("#@#BrancH").Substring(1), out tmpbranch);
|
if (tmpbranch != 0)
|
debugBranch = tmpbranch;
|
}
|
|
var parentDirectory = Directory.GetParent(Application.persistentDataPath);
|
if (File.Exists(parentDirectory + "/Debug"))
|
{
|
var content = File.ReadAllText(parentDirectory + "/Debug");
|
if (!string.IsNullOrEmpty(content))
|
{
|
var json = JsonMapper.ToObject<DebugBranch>(File.ReadAllText(parentDirectory + "/Debug"));
|
debugBranch = json.branch;
|
}
|
}
|
|
Clock.Init();
|
Debug.Log("LocalResManager.Init");
|
}
|
|
public void Release()
|
{
|
spriteBundle?.Unload(true); //true完全卸载,更新后重新加载
|
prefabBundle?.Unload(true);
|
assetVersions = null;
|
localAssetVersions = null;
|
spriteAtlas = null;
|
Debug.Log("提前ResManager.Release资源");
|
}
|
|
public void RequestVersionCheck()
|
{
|
var versionConfig = VersionConfigEx.Get();
|
var tables = new Dictionary<string, string>();
|
tables["channel"] = versionConfig.appId;
|
tables["versioncode"] = versionConfig.version;
|
if (versionConfig.branch != 0)
|
{
|
tables["branch"] = versionConfig.branch.ToString();
|
}
|
|
tables["game"] = versionConfig.gameId;
|
|
var url = string.Concat(VERSION_URL[urlIndex % VERSION_URL.Length], HttpRequest.HashtablaToString(tables));
|
|
urlIndex++;
|
versionUrl = url;
|
Debug.Log("http地址:versionUrl " + url);
|
HttpRequest.Instance.RequestHttpGet(url, HttpRequest.defaultHttpContentType, 1, OnVersionCheckResult);
|
}
|
|
private void OnVersionCheckResult(bool _ok, string _result)
|
{
|
if (_ok)
|
{
|
versionUrlResult = _result.Replace("{}", "null");
|
versionInfo = JsonMapper.ToObject<VersionInfo>(versionUrlResult);
|
|
if (VersionConfigEx.Get().assetAccess == VersionConfigEx.InstalledAsset.IngoreDownLoad)
|
{
|
assetVersions = localAssetVersions;
|
step = LoadDllStep.ReadBytes;
|
return;
|
}
|
step = LoadDllStep.PrepareDownLoad;
|
}
|
else
|
{
|
Debug.Log("http 数据通讯: VersionUtility:" + versionUrl + " result:" + versionUrlResult);
|
Clock.AlarmAt(DateTime.Now + new TimeSpan(TimeSpan.TicksPerSecond), RequestVersionCheck);
|
}
|
}
|
|
public string GetAssetFilePath(string _assetKey)
|
{
|
var path = Path.Combine(ExternalStorePath, _assetKey);
|
if (!File.Exists(path))
|
{
|
path = Path.Combine(StreamingAssetPath, _assetKey);
|
}
|
|
return path;
|
}
|
|
public Sprite LoadSprite(string name)
|
{
|
Sprite sprite = null;
|
#if UNITY_EDITOR
|
// if (excludePngs.Contains(StringUtility.Contact(name, ".png")))
|
// {
|
// var path = StringUtility.Contact("Assets/ResourcesOut/BuiltIn/Sprites/", name, ".png");
|
// sprite = UnityEditor.AssetDatabase.LoadAssetAtPath<Sprite>(path);
|
// }
|
// else
|
// {
|
var spriteAtlas = UnityEditor.AssetDatabase.LoadAssetAtPath<SpriteAtlas>("Assets/ResourcesOut/BuiltIn/Sprites/sprites.spriteatlasv2");
|
sprite = spriteAtlas.GetSprite(name);
|
// }
|
|
#else
|
if (spriteBundle == null)
|
{
|
string _path = GetAssetFilePath("builtin/sprites");
|
spriteBundle = AssetBundle.LoadFromFile(_path);
|
}
|
|
sprite = spriteBundle.LoadAsset(name, typeof(Sprite)) as Sprite;
|
#endif
|
if (sprite == null)
|
{
|
Debug.LogErrorFormat("LoadSprite() => 加载不到资源: {0}.", name);
|
}
|
|
return sprite;
|
}
|
|
public GameObject LoadBuiltInPrefab(string name)
|
{
|
GameObject prefab = null;
|
#if UNITY_EDITOR
|
var path = string.Concat("Assets/ResourcesOut/BuiltIn/Prefabs/", name, ".prefab");
|
prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(path);
|
#else
|
if (prefabBundle == null)
|
{
|
string _path = GetAssetFilePath("builtin/prefabs");
|
prefabBundle = AssetBundle.LoadFromFile(_path);
|
}
|
prefab = prefabBundle.LoadAsset(name) as GameObject;
|
#endif
|
if (prefab == null)
|
{
|
Debug.LogErrorFormat("LoadBuiltInPrefab() => 加载不到资源: {0}.", name);
|
}
|
|
return prefab;
|
}
|
|
|
static Dictionary<string, string> languageShowDict = new Dictionary<string, string>();//射中显示的多语言版本
|
Dictionary<string, string> languageDict = new Dictionary<string, string>();// unity语言配置对应的约定字符
|
string defaultLanguage = string.Empty;
|
public void InitDefaultLanguage()
|
{
|
if (languageShowDict == null || languageShowDict.Count == 0)
|
{
|
var config = InitialFunctionConfig.Get("Language");
|
Debug.LogFormat("系统语言:{0} {1}", Application.systemLanguage, config.Numerical1);
|
if (string.IsNullOrEmpty(config.Numerical1))
|
return;
|
languageShowDict = JsonMapper.ToObject<Dictionary<string, string>>(config.Numerical1);
|
languageDict = JsonMapper.ToObject<Dictionary<string, string>>(config.Numerical5);
|
defaultLanguage = config.Numerical2;
|
if (!languageShowDict.ContainsKey(defaultLanguage))
|
defaultLanguage = string.Empty;
|
}
|
|
|
var id = LocalSave.GetString("LANGUAGE_ID1");
|
if (!string.IsNullOrEmpty(id))
|
return;
|
|
string languageMark = ((int)Application.systemLanguage).ToString();
|
|
if (languageDict.ContainsKey(languageMark))
|
{
|
id = languageDict[languageMark];
|
}
|
|
Id = languageShowDict.ContainsKey(id) ? id : defaultLanguage;
|
Debug.LogFormat("系统语言:{0} 设置为{1}", Application.systemLanguage, Id);
|
}
|
|
//LogicBytes文件的MD5信息
|
public void RequestLogicBytes()
|
{
|
var remoteURL = string.Concat(versionInfo.GetResourcesURL(VersionConfigEx.Get().branch), fixPath, "/logicbytes.txt");
|
//var localURL = string.Concat(.ExternalStorePath, "/logicbytes.txt");
|
assetBytesUrl = remoteURL;
|
Debug.Log("http地址:logicbytesUrl " + assetBytesUrl);
|
//HttpRequest.Instance.RequestHttpGet(assetBytesUrl, HttpRequest.defaultHttpContentType, 3, OnGetAssetVersionFile);
|
HttpRequest.Instance.UnityWebRequestGet(assetBytesUrl, 5, OnGetAssetVersionFile);
|
}
|
|
private void OnGetAssetVersionFile(bool _ok, string _result)
|
{
|
Debug.LogFormat("RequestLogicBytes文件结果:时间 {0},结果 {1}, 文件大小 {2}", DateTime.Now, _ok, _result.Length);
|
if (_ok)
|
{
|
UpdateAssetVersions(_result);
|
step = LoadDllStep.DownLoad;
|
}
|
else
|
{
|
Debug.Log("http 数据通讯: RequestLogicBytes:" + assetBytesUrl + " result:" + _result);
|
Clock.AlarmAt(DateTime.Now + new TimeSpan(TimeSpan.TicksPerSecond * 3), RequestLogicBytes);
|
}
|
}
|
|
public Dictionary<string, AssetVersion> UpdateAssetVersions(string _assetVersionFile)
|
{
|
var lines = _assetVersionFile.Split(new string[] { FileExtersion.lineSplit }, StringSplitOptions.RemoveEmptyEntries);
|
assetVersions.Clear();
|
for (int i = 0; i < lines.Length; i++)
|
{
|
var assetVersion = new AssetVersion(lines[i]);
|
assetVersions[assetVersion.relativePath] = assetVersion;
|
}
|
return assetVersions;
|
}
|
|
//读表 使用UnityWebRequest 考虑安卓环境
|
private async UniTask ReadText(string table, Action<bool, string> OnComplete = null, string filePath = "")
|
{
|
var path = string.Empty;
|
string content = string.Empty;
|
bool result = false;
|
if (filePath != "")
|
{
|
path = Path.Combine(filePath + $"{table}.txt");
|
}
|
else
|
{
|
#if UNITY_EDITOR
|
path = CONFIG_FODLER + $"/{table}.txt";
|
#else
|
path = GetAssetFilePath($"config/{table}.txt");
|
#endif
|
}
|
if (!path.Contains("file:"))
|
{
|
//ExternalStorePath 路径需要添加
|
path = "file://" + path;
|
}
|
Debug.LogFormat("ReadText() => path: {0}", path);
|
UnityWebRequest www = UnityWebRequest.Get(path);
|
await www.SendWebRequest();
|
|
#if UNITY_2020_1_OR_NEWER
|
if (www.result != UnityWebRequest.Result.Success)
|
{
|
Debug.Log(www.error);
|
OnComplete(result, content);
|
}
|
#else
|
if (www.isHttpError || www.isNetworkError)
|
{
|
Debug.Log(www.error);
|
OnComplete(result, content);
|
}
|
#endif
|
else
|
{
|
content = www.downloadHandler.text;
|
Debug.Log($"table:{table} size:{content.Length}");
|
result = true;
|
OnComplete(result, content);
|
}
|
|
}
|
|
public async void InitTable(Action OnComplete = null)
|
{
|
await ReadText("InitialFunction", (isOK, value) =>
|
{
|
if (isOK)
|
{
|
InitialFunctionConfig.Init(value);
|
OnComplete();
|
}
|
else
|
{
|
Debug.LogError("InitTable InitialFunctionConfig error");
|
}
|
});
|
if (isPCTestDownLoad || Application.isMobilePlatform)
|
{
|
//读取的一定是StreamingAssetPath路径
|
await ReadText("logicbytes", (isOK, value) =>
|
{
|
if (isOK)
|
InitLocalLogicbytes(value);
|
else
|
Debug.LogWarning("InitTable logicbytes error");
|
}, StreamingAssetPath);
|
}
|
}
|
|
//随包安装的资源不同平台不一定可以获取FileInfo,所以需要下载一个文件来获取资源的MD5信息
|
//该文件在打包时生成 记录随包的所有资源的信息
|
//该文件记录的资源在包中肯定存在,所以不用去取指定的资源文件获得FileInfo 计算MD5
|
//随包LogicBytes文件的MD5信息 用于下载对比
|
void InitLocalLogicbytes(string content)
|
{
|
using (StringReader reader = new StringReader(content))
|
{
|
string line;
|
while ((line = reader.ReadLine()) != null)
|
{
|
try
|
{
|
var assetVersion = new AssetVersion(line);
|
assetVersion.localValid = true;
|
localAssetVersions[assetVersion.relativePath] = assetVersion;
|
}
|
catch (System.Exception ex)
|
{
|
Debug.LogError(ex);
|
}
|
}
|
}
|
|
}
|
|
public class VersionInfo
|
{
|
public JsonData notice_flag;
|
public JsonData resource_url; //这里只用到这个取下载地址
|
public string ResourceAward;
|
public int downAsset = 1;
|
public string downUrl;
|
public int VersionCount;
|
|
|
public string GetResourcesURL(int _branch)
|
{
|
if (resource_url != null)
|
{
|
return resource_url[_branch.ToString()].ToString();
|
}
|
else
|
{
|
return string.Empty;
|
}
|
}
|
|
}
|
|
public class DebugBranch
|
{
|
public int branch = -1;
|
}
|
|
public enum LoadDllStep
|
{
|
None,
|
Wait, //每个阶段的等待时间 比如在下载中就处于等待状态,完成后再进入下一个阶段
|
RequestVersion,
|
PrepareDownLoad,
|
DownLoad,
|
ReadBytes,
|
Completed,
|
}
|
}
|