294 lines
9.9 KiB
C#
294 lines
9.9 KiB
C#
using HotUpdate.UI;
|
||
using Cysharp.Threading.Tasks;
|
||
using PhxhSDK.AOT;
|
||
using PhxhSDK.AOT.SimpleLoader;
|
||
using PhxhSDK.AOT.VersionUpdate;
|
||
using System;
|
||
using PhxhSDK.AOT.PreConfig;
|
||
using UnityEngine;
|
||
using UnityEngine.SceneManagement;
|
||
using Assets.PhxhSDK.AOT.BI;
|
||
using Obfuz.EncryptionVM;
|
||
|
||
using Obfuz;
|
||
|
||
|
||
|
||
#if PLATFORM_ANDROID || UNITY_EDITOR
|
||
using UnityEngine.Android;
|
||
#endif
|
||
|
||
#if SDK_BILIBILI
|
||
using PhxhSDK.AOT.Bilibili;
|
||
#endif
|
||
|
||
public class GameLauncher : MonoBehaviour
|
||
{
|
||
/// <summary>
|
||
/// 初始化EncryptionService后被混淆的代码才能正常运行,
|
||
/// 因此尽可能地早地初始化它。
|
||
/// </summary>
|
||
[ObfuzIgnore]
|
||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
|
||
private static void SetUpStaticSecretKey()
|
||
{
|
||
Debug.Log("SetUpStaticSecret begin");
|
||
EncryptionService<DefaultStaticEncryptionScope>.Encryptor = new GeneratedEncryptionVirtualMachine(Resources.Load<TextAsset>("us5af47s54fsa1z90sf").bytes);
|
||
Debug.Log("SetUpStaticSecret end");
|
||
}
|
||
|
||
private static void SetUpDynamicSecret(byte[] bytes)
|
||
{
|
||
Debug.Log("SetUpDynamicSecret begin");
|
||
EncryptionService<DefaultDynamicEncryptionScope>.Encryptor = new GeneratedEncryptionVirtualMachine(bytes);
|
||
Debug.Log("SetUpDynamicSecret end");
|
||
}
|
||
|
||
private const string START_SCENE_NAME = "Assets/Scenes/StartScene.unity";
|
||
private const string DYNAMIC_SECRET_PATH = "Assets/Config/Obfuz/defaultDynamicSecretKey.bytes";
|
||
|
||
//最大能容忍的下载卡住时长,一旦超过则重新开始下载
|
||
// private const float DOWNLOAD_STUCK_TIME_MAX = 10;
|
||
|
||
#if USE_HCLR
|
||
private HybridCLRHelper _hybridCLRHelper;
|
||
#endif
|
||
|
||
private VersionUpdateHandle _versionUpdateHandle;
|
||
private ISimpleLoader _simpleLoader;
|
||
private IVersionUpdateUI versionUpdateUI;
|
||
|
||
public bool enableHotUpdate = true;
|
||
|
||
private void Awake()
|
||
{
|
||
#if SDK_BILIBILI
|
||
GameObject goBiliBiliSDK = new()
|
||
{
|
||
name = "BiliBiliSDK"
|
||
};
|
||
|
||
if (!goBiliBiliSDK.TryGetComponent<GSCSdkInterface>(out _))
|
||
goBiliBiliSDK.AddComponent<GSCSdkInterface>();
|
||
|
||
if (!goBiliBiliSDK.TryGetComponent<GSCCallbackListerner>(out _))
|
||
goBiliBiliSDK.AddComponent<GSCCallbackListerner>();
|
||
|
||
DontDestroyOnLoad(goBiliBiliSDK);
|
||
#endif
|
||
}
|
||
|
||
private void Start()
|
||
{
|
||
#if SDK_BILIBILI
|
||
GSCSdkInterface.init();
|
||
#endif
|
||
|
||
#if SDK_ADJUST
|
||
var YourAppToken = "shw96lfwisqo"; // 替换为你的Adjust App Token
|
||
AdjustInitTool.Instance.InitAdjustSDK(YourAppToken);
|
||
#endif
|
||
#if SDK_FIREBASE
|
||
Firebase.Analytics.FirebaseAnalytics.LogEvent("First_open");
|
||
#endif
|
||
|
||
versionUpdateUI = new TempUIHandle();
|
||
|
||
bool agreement = PlayerPrefs.GetInt("PrivacyAgreement", 0) == 1;
|
||
BIToolinAOT.Instance.TrackEventInAOT("app_open", null);
|
||
|
||
if (!agreement) // 弹隐私弹窗
|
||
{
|
||
TempUpdateUI.Instance.PrivacyAgreeCallback = () =>
|
||
{
|
||
TempUpdateUI.Instance.m_ProgressObj.SetActive(true);
|
||
Launch();
|
||
};
|
||
TempUpdateUI.Instance.m_PrivacyDialogObj.SetActive(true);
|
||
}
|
||
else
|
||
{
|
||
TempUpdateUI.Instance.m_ProgressObj.SetActive(true);
|
||
Launch();
|
||
}
|
||
}
|
||
|
||
private async void Launch()
|
||
{
|
||
#if UNITY_EDITOR
|
||
enableHotUpdate = false;
|
||
#endif
|
||
#if PLATFORM_ANDROID && !SDK_BILIBILI //B站在隐私协议之后才申请权限
|
||
if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite))
|
||
{
|
||
Debug.Log("申请权限: " + Permission.ExternalStorageWrite);
|
||
Permission.RequestUserPermission(Permission.ExternalStorageWrite);
|
||
}
|
||
#endif
|
||
versionUpdateUI.UpdateProgress(0f);
|
||
versionUpdateUI.UpdateProgressText(LocalizeMono.Instance.GetLocalizeText("NetworkConnection")); // 尝试网络连接中...
|
||
_versionUpdateHandle = new VersionUpdateHandle(versionUpdateUI);
|
||
VersionUpdateInfo versionUpdateInfo = _versionUpdateHandle.GetVersionInfo();
|
||
PackDataInst.CreateInst();
|
||
|
||
UpdateLocalInfo localInfo = PackDataInst.Inst.localInfo;
|
||
string acquiring = LocalizeMono.Instance.GetLocalizeText("Acquiring"); // 获取中...
|
||
versionUpdateUI.ShowVersion(Application.version, localInfo.workSpace, localInfo.localFullVersion, acquiring, acquiring);
|
||
|
||
|
||
string appID = string.Empty;
|
||
string channel = string.Empty;
|
||
#if SDK_TALKINGDATA
|
||
appID = TalkingDataInitTool.appID;
|
||
channel = TalkingDataInitTool.channel;
|
||
#endif
|
||
BIToolinAOT.Instance.Init(appID, channel);//TalkingData初始化
|
||
|
||
//TalkingData初始化
|
||
#if SDK_TALKINGDATA
|
||
#if PLATFORM_ANDROID
|
||
if (Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite))
|
||
{
|
||
Debug.Log("已申请权限: " + Permission.ExternalStorageWrite);
|
||
BIToolinAOT.Instance.TalkingDataStart();
|
||
}
|
||
#else
|
||
BIToolinAOT.Instance.TalkingDataStart();
|
||
#endif
|
||
|
||
#endif
|
||
PlayerPrefs.SetString("BI_Platform", TalkingDataInitTool.channel);
|
||
#region 更新AppConfig
|
||
bool downloadResult;
|
||
do
|
||
{
|
||
try
|
||
{
|
||
versionUpdateUI.UpdateProgressText(LocalizeMono.Instance.GetLocalizeText("RequestConfiguration")); // 开始请求APPConfig
|
||
BIToolinAOT.Instance.TrackEventInAOT("app_config_request", null);
|
||
|
||
downloadResult = await PreConfig.instance.DownloadConfig();
|
||
|
||
versionUpdateUI.UpdateProgressText(LocalizeMono.Instance.GetLocalizeText("RequestConfigurationComplete")); // 请求APPConfig结束
|
||
versionUpdateUI.ShowVersion(Application.version, localInfo.workSpace, localInfo.localFullVersion, acquiring, PreConfig.instance.ServerName);
|
||
BIToolinAOT.Instance.TrackEventInAOT("app_config_response", new System.Collections.Generic.Dictionary<string, object>(){
|
||
{"result", downloadResult? 0 : 1 }
|
||
});
|
||
}
|
||
catch (Exception)
|
||
{
|
||
downloadResult = false;
|
||
}
|
||
}
|
||
while (!downloadResult && await versionUpdateUI.ShowDialog(LocalizeMono.Instance.GetLocalizeText("Tip"), LocalizeMono.Instance.GetLocalizeText("DownloadConfigErrorRetry"))); // 下载配置文件失败,是否重试?
|
||
|
||
if (!downloadResult)
|
||
TempUpdateUI.Instance.OnClickCancel();
|
||
#endregion
|
||
|
||
if (!PreConfig.instance.isConfigValid)
|
||
{
|
||
// 配置错误,没有读取到ResUrl
|
||
// TODO: 这种情况也应该有个弹出框,提示用户配置文件错误
|
||
Debug.LogError("配置文件错误");
|
||
await versionUpdateUI.ShowDialog(LocalizeMono.Instance.GetLocalizeText("Tip"), LocalizeMono.Instance.GetLocalizeText("ConfigError")); // 配置文件错误
|
||
TempUpdateUI.Instance.OnClickCancel();
|
||
return;
|
||
}
|
||
|
||
#if USE_YOO
|
||
await YooAssetHelper.Init();
|
||
_simpleLoader = new SimpleLoader_YooAsset();
|
||
#else
|
||
_simpleLoader = new SimpleLoader_Addressables();
|
||
#endif
|
||
Debug.Log($"Launch Game! enableHotUpdate:{enableHotUpdate}");
|
||
|
||
bool result = await _versionUpdateHandle.CheckUpdate();//这里会打点资源检测更新事件
|
||
if (!result)
|
||
{
|
||
Debug.LogError("更新失败!,无法进入游戏");
|
||
return;
|
||
}
|
||
|
||
if (enableHotUpdate)
|
||
{
|
||
#if USE_HCLR
|
||
byte[] dynamicSecret = await _simpleLoader.LoadDllBytes(DYNAMIC_SECRET_PATH);
|
||
SetUpDynamicSecret(dynamicSecret);
|
||
await _simpleLoader.UnloadDll(DYNAMIC_SECRET_PATH);
|
||
|
||
Debug.Log("需要热更新,开始加载程序集");
|
||
_hybridCLRHelper = new HybridCLRHelper();
|
||
_hybridCLRHelper.SetDllList(AOTGenericReferences.PatchedAOTAssemblyList);
|
||
_hybridCLRHelper.RegistLoader(_simpleLoader);
|
||
|
||
await _hybridCLRHelper.LoadAssemblies();
|
||
Debug.Log("加载程序集结束!");
|
||
#endif
|
||
}
|
||
|
||
await _simpleLoader.WarmUpShader();
|
||
|
||
await EnterGame();
|
||
}
|
||
|
||
private async UniTask EnterGame()
|
||
{
|
||
Debug.Log("开始加载游戏场景");
|
||
SimulationProgress(versionUpdateUI.GetCurProgress());
|
||
try
|
||
{
|
||
Scene scene = await _simpleLoader.LoadSceneAsync(START_SCENE_NAME, LoadSceneMode.Additive);
|
||
foreach (GameObject go in scene.GetRootGameObjects())
|
||
{
|
||
if ("EventSystem".Equals(go.name))
|
||
{
|
||
Destroy(go);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError(e);
|
||
}
|
||
finally
|
||
{
|
||
await LoadOver();
|
||
Debug.Log("加载游戏场景结束");
|
||
}
|
||
}
|
||
|
||
private async void SimulationProgress(float startProgress)
|
||
{
|
||
versionUpdateUI.UpdateProgressText(LocalizeMono.Instance.GetLocalizeText("InitGaming")); // 初始化游戏...
|
||
versionUpdateUI.UpdateProgress(startProgress);
|
||
|
||
float step = (1f - startProgress) * 0.02f;
|
||
while (startProgress + step <= 0.99f)
|
||
{
|
||
await UniTask.Delay(20);
|
||
startProgress += step;
|
||
versionUpdateUI.UpdateProgress(startProgress);
|
||
}
|
||
}
|
||
|
||
private async UniTask LoadOver()
|
||
{
|
||
while (true)
|
||
{
|
||
await UniTask.Yield();
|
||
// Debug.Log($"校验是否加载完:{IVersionUpdateUI.IsLoadOver}");
|
||
if (StartSceneLoadingManager.IsLoadOver)
|
||
{
|
||
versionUpdateUI.UpdateProgress(1f);
|
||
versionUpdateUI.UpdateProgressText(LocalizeMono.Instance.GetLocalizeText("Complete")); // 完成
|
||
await UniTask.Delay(200);
|
||
versionUpdateUI.CloseAll();
|
||
await SceneManager.UnloadSceneAsync(0);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
} |