225 lines
7.9 KiB
C#
225 lines
7.9 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.SceneManagement;
|
|
|
|
[DisallowMultipleComponent]
|
|
public sealed class RuntimeBootProbe : MonoBehaviour
|
|
{
|
|
[Header("Optional References")]
|
|
[SerializeField] private GameObject hudRoot;
|
|
[SerializeField] private GeoTileAddressablesLoader geoTileLoader;
|
|
[SerializeField] private Transform expectedPlayer;
|
|
|
|
[Header("Probe Settings")]
|
|
[SerializeField] private bool logOnAwake = true;
|
|
[SerializeField] private bool logOnStart = true;
|
|
[SerializeField] private bool logAfterDelay = true;
|
|
[SerializeField] private float delayedLogSeconds = 2.0f;
|
|
|
|
private void Awake()
|
|
{
|
|
if (logOnAwake)
|
|
Dump("Awake");
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
if (logOnStart)
|
|
Dump("Start");
|
|
|
|
if (logAfterDelay && delayedLogSeconds > 0.0f)
|
|
Invoke(nameof(DumpDelayed), delayedLogSeconds);
|
|
}
|
|
|
|
private void DumpDelayed()
|
|
{
|
|
Dump("Delayed");
|
|
}
|
|
|
|
private void Dump(string phase)
|
|
{
|
|
var sb = new StringBuilder(1024);
|
|
sb.Append("[RuntimeBootProbe] ").Append(phase).Append(" ");
|
|
sb.Append("activeScene=").Append(SceneManager.GetActiveScene().name).Append(" ");
|
|
sb.Append("loadedScenes=").Append(SceneManager.sceneCount).Append(" ");
|
|
sb.Append("persistentDataPath=").Append(Application.persistentDataPath).Append(" ");
|
|
|
|
if (hudRoot == null)
|
|
{
|
|
sb.Append("hudRoot=null ");
|
|
}
|
|
else
|
|
{
|
|
sb.Append("hudRoot.activeInHierarchy=").Append(hudRoot.activeInHierarchy).Append(" ");
|
|
sb.Append("hudRoot.activeSelf=").Append(hudRoot.activeSelf).Append(" ");
|
|
}
|
|
|
|
if (expectedPlayer == null)
|
|
{
|
|
sb.Append("expectedPlayer=null ");
|
|
}
|
|
else
|
|
{
|
|
Vector3 p = expectedPlayer.position;
|
|
sb.Append("expectedPlayer.pos=(")
|
|
.Append(p.x.ToString("F2")).Append(",")
|
|
.Append(p.y.ToString("F2")).Append(",")
|
|
.Append(p.z.ToString("F2")).Append(") ");
|
|
}
|
|
|
|
if (geoTileLoader == null)
|
|
{
|
|
sb.Append("geoTileLoader=null ");
|
|
AppendRenderState(sb);
|
|
Debug.Log(sb.ToString());
|
|
return;
|
|
}
|
|
|
|
bool loaderEnabled = geoTileLoader.enabled && geoTileLoader.gameObject.activeInHierarchy;
|
|
sb.Append("geoTileLoader.enabled=").Append(loaderEnabled).Append(" ");
|
|
|
|
string tileBundleFolderName = ReadPrivateField(geoTileLoader, "tileBundleFolderName", "TileBundles");
|
|
string manifestFileName = ReadPrivateField(geoTileLoader, "manifestFileName", "TileManifest.json");
|
|
string buildingManifestFileName = ReadPrivateField(geoTileLoader, "buildingManifestFileName", "TileBuildingsManifest.json");
|
|
string buildTargetFolderOverride = ReadPrivateField(geoTileLoader, "buildTargetFolderOverride", "");
|
|
|
|
string buildTargetFolder = string.IsNullOrWhiteSpace(buildTargetFolderOverride)
|
|
? GetBuildTargetFolderName()
|
|
: buildTargetFolderOverride;
|
|
|
|
string basePath = Path.Combine(Application.persistentDataPath, tileBundleFolderName, buildTargetFolder);
|
|
string manifestPath = Path.Combine(basePath, manifestFileName);
|
|
string buildingsManifestPath = Path.Combine(basePath, buildingManifestFileName);
|
|
string catalogPath = ResolveCatalogPath(manifestPath);
|
|
|
|
sb.Append("basePath=").Append(basePath).Append(" ");
|
|
sb.Append("manifestExists=").Append(File.Exists(manifestPath)).Append(" ");
|
|
sb.Append("buildingsManifestExists=").Append(File.Exists(buildingsManifestPath)).Append(" ");
|
|
|
|
if (!string.IsNullOrWhiteSpace(catalogPath))
|
|
sb.Append("catalogExists=").Append(File.Exists(catalogPath)).Append(" ");
|
|
else
|
|
sb.Append("catalogExists=unknown ");
|
|
|
|
AppendRenderState(sb);
|
|
Debug.Log(sb.ToString());
|
|
}
|
|
|
|
private static void AppendRenderState(StringBuilder sb)
|
|
{
|
|
var rp = GraphicsSettings.currentRenderPipeline;
|
|
string rpName = rp != null ? $"{rp.name} ({rp.GetType().Name})" : "BuiltInRenderPipeline";
|
|
int qualityIndex = QualitySettings.GetQualityLevel();
|
|
string qualityName = qualityIndex >= 0 && qualityIndex < QualitySettings.names.Length
|
|
? QualitySettings.names[qualityIndex]
|
|
: "<unknown>";
|
|
|
|
sb.Append("quality=").Append(qualityIndex).Append(":").Append(qualityName).Append(" ");
|
|
sb.Append("renderPipeline=").Append(rpName).Append(" ");
|
|
|
|
var cam = Camera.main;
|
|
if (cam == null)
|
|
{
|
|
sb.Append("mainCamera=<none> ");
|
|
}
|
|
else
|
|
{
|
|
sb.Append("mainCamera=").Append(cam.name).Append(" ");
|
|
sb.Append("mainCamera.farClip=").Append(cam.farClipPlane.ToString("F1")).Append(" ");
|
|
sb.Append("mainCamera.nearClip=").Append(cam.nearClipPlane.ToString("F3")).Append(" ");
|
|
sb.Append("mainCamera.cullingMask=0x").Append(cam.cullingMask.ToString("X")).Append(" ");
|
|
}
|
|
|
|
AppendXrState(sb);
|
|
}
|
|
|
|
private static void AppendXrState(StringBuilder sb)
|
|
{
|
|
try
|
|
{
|
|
Type xrSettingsType = Type.GetType("UnityEngine.XR.XRSettings, UnityEngine.XRModule");
|
|
if (xrSettingsType == null)
|
|
{
|
|
sb.Append("xrEnabled=<unavailable> ");
|
|
return;
|
|
}
|
|
|
|
var enabledProp = xrSettingsType.GetProperty("enabled", BindingFlags.Public | BindingFlags.Static);
|
|
bool xrEnabled = enabledProp != null && enabledProp.GetValue(null) is bool enabled && enabled;
|
|
sb.Append("xrEnabled=").Append(xrEnabled).Append(" ");
|
|
|
|
if (!xrEnabled)
|
|
return;
|
|
|
|
var stereoModeProp = xrSettingsType.GetProperty("stereoRenderingMode", BindingFlags.Public | BindingFlags.Static);
|
|
object stereoMode = stereoModeProp?.GetValue(null);
|
|
sb.Append("xrStereoMode=").Append(stereoMode != null ? stereoMode.ToString() : "<unknown>").Append(" ");
|
|
}
|
|
catch
|
|
{
|
|
sb.Append("xrEnabled=<error> ");
|
|
}
|
|
}
|
|
|
|
private static string ReadPrivateField(GeoTileAddressablesLoader loader, string fieldName, string fallback)
|
|
{
|
|
try
|
|
{
|
|
FieldInfo fi = typeof(GeoTileAddressablesLoader).GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
|
|
if (fi == null)
|
|
return fallback;
|
|
|
|
object value = fi.GetValue(loader);
|
|
return value as string ?? fallback;
|
|
}
|
|
catch
|
|
{
|
|
return fallback;
|
|
}
|
|
}
|
|
|
|
private static string ResolveCatalogPath(string manifestPath)
|
|
{
|
|
try
|
|
{
|
|
if (!File.Exists(manifestPath))
|
|
return null;
|
|
|
|
string json = File.ReadAllText(manifestPath);
|
|
TileManifest manifest = JsonUtility.FromJson<TileManifest>(json);
|
|
if (manifest == null || string.IsNullOrWhiteSpace(manifest.catalogFile))
|
|
return null;
|
|
|
|
return Path.Combine(Path.GetDirectoryName(manifestPath) ?? string.Empty, manifest.catalogFile);
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static string GetBuildTargetFolderName()
|
|
{
|
|
switch (Application.platform)
|
|
{
|
|
case RuntimePlatform.Android:
|
|
return "Android";
|
|
case RuntimePlatform.WindowsPlayer:
|
|
case RuntimePlatform.WindowsEditor:
|
|
return "StandaloneWindows64";
|
|
case RuntimePlatform.OSXPlayer:
|
|
case RuntimePlatform.OSXEditor:
|
|
return "StandaloneOSX";
|
|
case RuntimePlatform.LinuxPlayer:
|
|
case RuntimePlatform.LinuxEditor:
|
|
return "StandaloneLinux64";
|
|
default:
|
|
return "Android";
|
|
}
|
|
}
|
|
}
|