Files
2026-05-26 16:15:54 +08:00

224 lines
7.3 KiB
C#

using asap.core;
using System;
using System.Collections;
using System.IO;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.ResourceLocations;
using UnityEngine.ResourceManagement.ResourceProviders;
namespace game
{
public class RootCtx : GContext
{
#if !UNITY_EDITOR && AGG
private void Start()
{
Debug.Log("InitSDK");
tysdk.TYSdkFacade.Instance.Init();
}
#endif
protected override async Task SetupAsync()
{
container.Register<IStageService, StageService>().AsSingleton();
//container.Register<IDataService, LubanDataService>().AsSingleton();
container.Register<IObjectSerializer, ObjectSerializer>().AsSingleton();
container.Register<IConfig, Config>().AsSingleton();
await Awaiters.NextFrame;
BetterStreamingAssets.Initialize();
// using remote assets locally if exists
Addressables.InternalIdTransformFunc += DoIdTransform;
UnityEngine.Random.InitState((int)System.DateTime.Now.Ticks);
// Initialize DOTween with the preferences set in DOTween's Utility Panel
DG.Tweening.DOTween.Init();
// Set Tweens capacity accordingly based on DOTween warnings
DG.Tweening.DOTween.SetTweensCapacity(200, 125);
Application.lowMemory += OnLowMemory;
//SceneManager.sceneLoaded += OnSceneLoaded;
Screen.sleepTimeout = SleepTimeout.NeverSleep;
}
//void OnSceneLoaded(Scene scene, LoadSceneMode mode)
//{
//GameDebug.Log("[GameEngine]OnSceneLoaded: Name: {0}, Mode: {1}", scene.name, mode);
//SetCamStack();
//}
float _lowMemCleanupTime;
bool _isUnloadingMem;
const float LOW_MEM_CLEANUP_CD = 10f; // in secs
void OnLowMemory()
{
GameDebug.LogWarning("[GameEngine]OnLowMemory: Memory is low!");
// Add a cool-down time to prevent consecutive cleaning up process, which
// will cause a long performance hiccup
if (!_isUnloadingMem &&
Time.realtimeSinceStartup - _lowMemCleanupTime > LOW_MEM_CLEANUP_CD)
{
StartCoroutine(UnloadMemory());
}
}
IEnumerator UnloadMemory(Action back = null)
{
GameDebug.Log("[GameEngine]UnloadMemory: Start cleaning up!");
_isUnloadingMem = true;
System.GC.Collect();
var op = Resources.UnloadUnusedAssets();
while (!op.isDone)
{
yield return null;
}
back?.Invoke();
_lowMemCleanupTime = Time.realtimeSinceStartup;
_isUnloadingMem = false;
GameDebug.Log("[GameEngine]UnloadMemory: Cleaning up is done!");
}
private string customAddressableRemoteURL;
private string originAddressableRemoteURL;
public void ChangeAddressableRemoteUrl(string customUrl, string originUrl)
{
Debug.Log($"[RootCtx::ChangeAddressableRemoteUrl] customUrl: {customUrl}, originUrl: {originUrl}");
customAddressableRemoteURL = customUrl;
originAddressableRemoteURL = originUrl;
Addressables.InternalIdTransformFunc -= DoIdTransform;
Addressables.InternalIdTransformFunc += DoIdTransformUsingCustomURL;
}
private const string Remote_Prefix = "http";
private string DoIdTransformUsingCustomURL(IResourceLocation location)
{
var id = location.InternalId;
if (id.StartsWith(Remote_Prefix))
{
if (location.ResourceType.IsAssignableFrom(typeof(IAssetBundleResource)))
{
var primaryKey = location.PrimaryKey;
if (BetterStreamingAssets.FileExists(primaryKey))
return Path.Combine(Application.streamingAssetsPath, primaryKey);
}
id = id.Replace(originAddressableRemoteURL, customAddressableRemoteURL);
}
return id;
}
private string DoIdTransform(IResourceLocation location)
{
var id = location.InternalId;
if (id.StartsWith(Remote_Prefix))
{
if (location.ResourceType.IsAssignableFrom(typeof(IAssetBundleResource)))
{
var primaryKey = location.PrimaryKey;
if (BetterStreamingAssets.FileExists(primaryKey))
return Path.Combine(Application.streamingAssetsPath, primaryKey);
}
}
return id;
}
public static void ExitGame()
{
PlayerPrefs.Save();
Application.runInBackground = false;
if (Application.platform == RuntimePlatform.Android)
{
// Calling Application.Quit on some devices will cause ANR, so
// directly calling system action instead
try
{
new AndroidJavaClass("java.lang.System").CallStatic("exit", 0);
}
catch (Exception ex)
{
Debug.LogError($"[GameStateMgr]ExitGame: {ex}");
}
}
else
{
Application.Quit();
}
}
public static bool showFPS = false;
public static float fps;
private static float frameCount;
private static float elapse;
private GUIStyle _fpsStyle;
public GUIStyle fpsStyle
{
get
{
if (_fpsStyle == null)
{
int h = Screen.height;
_fpsStyle = new GUIStyle();
_fpsStyle.alignment = TextAnchor.UpperLeft;
_fpsStyle.fontSize = h * 2 / 100;
_fpsStyle.normal.textColor = Color.magenta;
}
return _fpsStyle;
}
}
void OnGUI()
{
frameCount++;
elapse += Time.unscaledDeltaTime;
if (elapse >= 1)
{
fps = frameCount / elapse;
elapse = 0;
frameCount = 0;
}
if (!showFPS) return;
string text = string.Format("FPS: {0:0.}", fps);
int w = Screen.width, h = Screen.height;
Rect rect = new Rect(20, h * 0.4f, w * 0.5f, h * 2 / 100);
GUI.Label(rect, text, fpsStyle);
}
protected override void OnDestroy()
{
Debug.Log("[RootCtx::OnDestroy]");
base.OnDestroy();
Addressables.InternalIdTransformFunc = null;
Application.lowMemory -= OnLowMemory;
root = null;
Ready = false;
IsInited = false;
eventAggregator = new EventAggregator();
container.Dispose();
container = new Container();
}
public static void DestoryRootCtx()
{
if (root != null)
{
GameObject.DestroyImmediate(root.gameObject);
root = null;
}
}
}
}