Files
2026-07-10 10:24:29 +08:00

312 lines
14 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.UI;
namespace XGame
{
class Game : MonoBehaviour
{
static public Game Instance;
static public AssetBundle m_shaderBundleLoader;
static public XWebSocket m_WebSocket = null;
private static readonly Dictionary<string, Shader> s_RuntimeShaders = new Dictionary<string, Shader>();
private static readonly Color RuntimeAmbientSky = new Color(0.82f, 0.88f, 0.95f, 1f);
private static readonly Color RuntimeAmbientEquator = new Color(0.62f, 0.68f, 0.76f, 1f);
private static readonly Color RuntimeAmbientGround = new Color(0.34f, 0.32f, 0.28f, 1f);
private static readonly Color RuntimeSunColor = new Color(1f, 0.95686275f, 0.8392157f, 1f);
private const float RuntimeAmbientIntensity = 1.65f;
private const float RuntimeSunIntensity = 2.2f;
private const string RuntimeSunName = "RuntimeDirectionalLight";
private static readonly int RuntimeAmbientEnabledId = Shader.PropertyToID("_XRuntimeAmbientEnabled");
private static readonly int RuntimeAmbientSkyId = Shader.PropertyToID("_XRuntimeAmbientSky");
private static readonly int RuntimeAmbientEquatorId = Shader.PropertyToID("_XRuntimeAmbientEquator");
private static readonly int RuntimeAmbientGroundId = Shader.PropertyToID("_XRuntimeAmbientGround");
private void Awake()
{
//加载(添加)一个loading场景作为永久使用,(Test)
//XResLoader.AddScene("res/scene/loading/loading", (UnityEngine.GameObject[] objs) => {
// if (objs == null || objs[0] == null)
// {
// //Debug.Log("Loading Scene Load Failed!");
// }
// else
// {
// //Test
// foreach (var obj in objs)
// {
// (obj as UnityEngine.GameObject).SetActive(false);
// }
// }
// //添加场景后续可以通过场景名操作
// //XResLoader.AddScene("res/scene/s001/scene001", (UnityEngine.GameObject[] objs) =>
// //{
// // if (objs == null || objs[0] == null)
// // {
// // //Debug.Log("Loading Scene Load Failed!");
// // }
// // else
// // {
// // }
// //});
//});
}
public IEnumerator Init()
{
/*string url;
//test Dynamic RenderPipeline (ok)
XResLoader.LoadRes("res/RenderAsset/XRendePipline1.asset", typeof(RenderPipelineAsset), objs =>
{
if (objs == null || objs[0] == null)
{
Debug.Log($"res/RenderAsset/XRendePipline1.asset");
}
else
{
//GameObject obj = GameObject.Instantiate(objs[0], gameObject.transform) as GameObject;
RenderPipelineAsset rpasset = objs[0] as RenderPipelineAsset;
UniversalRenderPipelineAsset urpAsset = rpasset as UniversalRenderPipelineAsset;
QualitySettings.renderPipeline = rpasset;
GraphicsSettings.renderPipelineAsset = rpasset;
Debug.Log($"res/RenderAsset/XRendePipline1.asset : {rpasset.name} msaa : {urpAsset.msaaSampleCount}");
}
}, null);//*/
#if !UNITY_WEBGL
string sUpdatePath = Application.persistentDataPath;
#else
string sUpdatePath = Application.streamingAssetsPath;
#endif
// 加载 shader 变体集合(ShaderVariantCollection)并 WarmUp。
// 真机从 AssetBundle 加载的预设(如 Main)所用 shader,其光照变体在构建时可能被剔除,
// 导致平行光等不起效。把变体打进 game_shader.unity3d 并在此 WarmUp,可避免被剔除/运行时卡顿。
// 变体集合通过菜单 Tools/Shader 生成到 Assets/Game/Shader/Game.shadervariants(活跃流程会打进 game_shader.unity3d)。
DateTime swStart = DateTime.Now;
m_shaderBundleLoader = null;
s_RuntimeShaders.Clear();
Debug.Log($"###shader bundle md5 XWorld={XResLoader.GetFileMd5("XWorld", "game_shader.unity3d")}");
yield return XResLoader.coLoadAB("game_shader.unity3d", (ab) =>
{
m_shaderBundleLoader = ab;
if (ab == null) return;
Shader[] shaders = ab.LoadAllAssets<Shader>();
foreach (Shader shader in shaders)
{
if (shader == null)
{
continue;
}
s_RuntimeShaders[shader.name] = shader;
}
Shader xTexShader = GetRuntimeShader("Test/XTex");
Debug.Log($"###load Shader Count = {shaders.Length}, Test/XTex={(xTexShader != null ? xTexShader.name : "null")} supported={(xTexShader != null && xTexShader.isSupported)}");
ShaderVariantCollection[] svcs = ab.LoadAllAssets<ShaderVariantCollection>();
Debug.Log($"###load SVC Count = {svcs.Length}");
int i = 0;
foreach (var svc in svcs)
{
Debug.Log($"WarmUp{++i} : {svc.name} (variants={svc.variantCount})");
svc.WarmUp();
}
Debug.Log($"Shader WarmUp Finish! {(DateTime.Now - swStart).TotalMilliseconds} ms");
});
/*
// coLoadAB 在包缺失时不会回调 action,这里兜底提示(非致命,跳过 WarmUp 即可)
if (m_shaderBundleLoader == null)
Debug.LogWarning("未找到 shader 变体包 game_shader.unity3d,已跳过 WarmUp。" +
"若真机光照异常,请先用菜单 Tools/Shader 生成变体集合到 Assets/Game/Shader,并重打更新包发布。");
// 重建基于天空盒的环境光探针(SH)。场景环境光为 Skybox 模式且未烘焙时,
// 构建里不会自动生成该探针(编辑器会自动算,所以编辑器看着正常),真机会丢失基础环境光、整体偏暗。
// 调一次 DynamicGI.UpdateEnvironment() 即可在运行时从当前天空盒重新生成,恢复环境光。
ApplyRuntimeLighting("init");
*/
if (m_shaderBundleLoader == null)
Debug.LogWarning("Shader bundle game_shader.unity3d was not found; skipped WarmUp.");
ApplyRuntimeLighting("init");
StartCoroutine(CoReapplyRuntimeLighting());
/*/test 加载些东西 此场景可以
yield return XResLoader.coLoadRes("Assets/Arts/ScenePrefab/s001.prefab", typeof(GameObject), obj =>
{
if (obj == null )
{
Debug.Log($"Load Assets/Arts/ScenePrefab/s001 Failed");
}
else
{
GameObject objInst = GameObject.Instantiate(obj, gameObject.transform) as GameObject;
}
});
//
GameObject obj = GameObject.Find("Scene_21010100_Stone_005");
if (obj != null)
{
Debug.Log("Scene_21010100_Stone_005 ok");
}//*/
//Assets\Arts\Role\CharaterPrefab
//yield return XResLoader.coLoadRes("Assets/Arts/Role/CharaterPrefab/11501100_l.prefab", typeof(GameObject), obj =>
//{
// if (obj == null)
// {
// Debug.Log($"Load Assets/Arts/Role/CharaterPrefab/11501100_l Failed");
// }
// else
// {
// GameObject objInst = GameObject.Instantiate(obj, gameObject.transform) as GameObject;
// }
//});
/*/test net
string addr = "wss://192.168.10.186:4009";//"wss://app.xworld.link:16888";//"wss://app.xworld.link:16887";//"ws://192.168.10.186:2009";// "ws://127.0.0.1:16888";// 192.168.51.105
int port = 0;
lsocket.connect(addr, port, (GYWebSocket sock, string err) =>
{//连接结果
m_WebSocket = sock;
if (sock == null)
{
Debug.LogError($"connect {addr} Failed!");
}
else
{
//发送信息
byte[] byteArray;
//string abc = "123_test_msg_string";
//byteArray = System.Text.Encoding.ASCII.GetBytes(abc);
byteArray = new byte[] { 0x00 ,0x0B, 0x30, 0x15, 0x03, 0x16, 0x01, 0x51, 0x06, 0x02, 0x07, 0x01, 0x02 };
m_WebSocket.send(byteArray, (int nData, string str) =>
{
Debug.Log($"Send {nData} Bytes ");
}, ref err );
}
});//*/
yield break;
}
public static Shader GetRuntimeShader(string shaderName)
{
if (string.IsNullOrEmpty(shaderName))
{
return null;
}
Shader shader;
s_RuntimeShaders.TryGetValue(shaderName, out shader);
return shader;
}
private static IEnumerator CoReapplyRuntimeLighting()
{
yield return null;
ApplyRuntimeLighting("next-frame");
yield return new WaitForEndOfFrame();
ApplyRuntimeLighting("end-of-frame");
yield return new WaitForSeconds(0.5f);
ApplyRuntimeLighting("delay-0.5");
yield return new WaitForSeconds(1.5f);
ApplyRuntimeLighting("delay-2.0");
}
private static void ApplyRuntimeLighting(string reason)
{
RenderSettings.ambientMode = AmbientMode.Trilight;
RenderSettings.ambientSkyColor = RuntimeAmbientSky;
RenderSettings.ambientEquatorColor = RuntimeAmbientEquator;
RenderSettings.ambientGroundColor = RuntimeAmbientGround;
RenderSettings.ambientIntensity = RuntimeAmbientIntensity;
RenderSettings.reflectionIntensity = Mathf.Max(RenderSettings.reflectionIntensity, 0.8f);
Shader.SetGlobalFloat(RuntimeAmbientEnabledId, 1f);
Shader.SetGlobalColor(RuntimeAmbientSkyId, RuntimeAmbientSky * RuntimeAmbientIntensity);
Shader.SetGlobalColor(RuntimeAmbientEquatorId, RuntimeAmbientEquator * RuntimeAmbientIntensity);
Shader.SetGlobalColor(RuntimeAmbientGroundId, RuntimeAmbientGround * RuntimeAmbientIntensity);
// The runtime ambient probe is authored here. DynamicGI.UpdateEnvironment can
// rebuild it from the skybox later on some platforms and overwrite these values.
RenderSettings.ambientProbe = BuildRuntimeAmbientProbe();
SphericalHarmonicsL2 probe = RenderSettings.ambientProbe;
Light sun = EnsureRuntimeDirectionalLight();
Debug.Log($"[Game] Runtime lighting applied({reason}). ambientMode={RenderSettings.ambientMode}, " +
$"intensity={RenderSettings.ambientIntensity}, sky={RenderSettings.ambientSkyColor}, " +
$"sun={(sun != null ? sun.name : "null")} enabled={(sun != null && sun.enabled)} " +
$"sunIntensity={(sun != null ? sun.intensity : 0f)} skybox={(RenderSettings.skybox != null ? RenderSettings.skybox.name : "null")} " +
$"probeL00=({probe[0, 0]:F3},{probe[1, 0]:F3},{probe[2, 0]:F3})");
}
private static SphericalHarmonicsL2 BuildRuntimeAmbientProbe()
{
SphericalHarmonicsL2 probe = new SphericalHarmonicsL2();
probe.AddAmbientLight(RuntimeAmbientEquator * RuntimeAmbientIntensity);
probe.AddDirectionalLight(new Vector3(0.15f, 1f, 0.25f).normalized, RuntimeAmbientSky, 0.85f);
probe.AddDirectionalLight(new Vector3(-0.25f, -1f, -0.1f).normalized, RuntimeAmbientGround, 0.28f);
return probe;
}
private static Light EnsureRuntimeDirectionalLight()
{
Light sun = RenderSettings.sun;
if (!IsDirectionalLight(sun))
{
GameObject sunObj = GameObject.Find("DirectionalLight") ?? GameObject.Find(RuntimeSunName);
sun = sunObj != null ? sunObj.GetComponent<Light>() : null;
}
if (!IsDirectionalLight(sun))
{
foreach (Light light in FindObjectsOfType<Light>())
{
if (IsDirectionalLight(light))
{
sun = light;
break;
}
}
}
if (sun == null)
{
GameObject sunObj = new GameObject(RuntimeSunName);
sun = sunObj.AddComponent<Light>();
}
sun.gameObject.SetActive(true);
sun.enabled = true;
sun.type = LightType.Directional;
sun.color = RuntimeSunColor;
sun.intensity = Mathf.Max(sun.intensity, RuntimeSunIntensity);
sun.shadows = LightShadows.None;
sun.transform.rotation = Quaternion.Euler(50f, -30f, 0f);
RenderSettings.sun = sun;
return sun;
}
private static bool IsDirectionalLight(Light light)
{
return light != null && light.type == LightType.Directional;
}
private void Update()
{
//获得消息
if (Input.GetKey(KeyCode.H))
{
Camera camera = UnityEngine.Camera.main;
var forward = camera.transform.forward;
Debug.Log($"H Key Up {forward.x},{forward.y},{forward.z}");
}
}
}
}