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 s_RuntimeShaders = new Dictionary(); 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(); 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(); 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() : null; } if (!IsDirectionalLight(sun)) { foreach (Light light in FindObjectsOfType()) { if (IsDirectionalLight(light)) { sun = light; break; } } } if (sun == null) { GameObject sunObj = new GameObject(RuntimeSunName); sun = sunObj.AddComponent(); } 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}"); } } } }