Initial commit: Client Doc docs Server Tools
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,646 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using XGame;
|
||||
using Unity.Burst;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using Unity.Mathematics;
|
||||
using XWorld;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
/// <summary>
|
||||
/// 游戏启动器
|
||||
/// </summary>
|
||||
public class GameLauncher : MonoBehaviour
|
||||
{
|
||||
private const int AndroidTargetFrameRate = 60;
|
||||
|
||||
class SphereObj
|
||||
{
|
||||
public GameObject obj;
|
||||
public Transform tr;
|
||||
public Vector3 pos;
|
||||
public Vector3 vec;
|
||||
};
|
||||
List<SphereObj> sphereObjs = new List<SphereObj> ();
|
||||
private NativeArray<float3> positions = new NativeArray<float3>();
|
||||
private NativeArray<float3> velocities = new NativeArray<float3>();
|
||||
public int objectCount = 1;
|
||||
public float speed = 1.0f;
|
||||
|
||||
public static GameLauncher Instance;
|
||||
|
||||
string m_sFPS = "FPS";
|
||||
float m_fLastTime = 0;
|
||||
int m_nCount = 0;
|
||||
GUIStyle m_Style = new GUIStyle();
|
||||
|
||||
//系统ui组件
|
||||
GameObject m_PathObj;
|
||||
InputField m_InputField;
|
||||
Button m_LocalButton;
|
||||
Button m_ExitButton;
|
||||
|
||||
static public float m_fSize = 75;
|
||||
|
||||
//内网 DevDiscovery(替代老 Broadcast/UDP9999),StartGame 等其完成后回填 CurNode/CurCDN
|
||||
private XGame.MiniGame.DevServerDiscovery m_LanDiscovery;
|
||||
private const string LocalClientIdKey = "LocalClientId";
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
ConfigureFrameRate();
|
||||
Instance = this;
|
||||
gameObject.name = "Main";//第一时间改为标准名称
|
||||
InitStart();
|
||||
DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
//ud 设置字体
|
||||
m_Style.normal.background = Texture2D.blackTexture;
|
||||
m_Style.normal.textColor = new Color(1, 1, 1);
|
||||
m_Style.fontSize = 24;
|
||||
m_Style.fontStyle = FontStyle.Bold;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化管理器等(原来直接挂在GameManager这个节点下)
|
||||
/// </summary>
|
||||
void InitStart()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName("XNode");
|
||||
|
||||
if (processes.Length ==0)
|
||||
{
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
}
|
||||
#endif
|
||||
//初始化
|
||||
GlobalData.bWX = false;// LoadDll.m_bInWX;
|
||||
#if UNITY_IOS
|
||||
GlobalData.CurPlatform = "ios";
|
||||
#elif UNITY_ANDROID
|
||||
GlobalData.CurPlatform = "android";
|
||||
#elif UNITY_WEBGL
|
||||
GlobalData.CurPlatform = "webgl";
|
||||
#else
|
||||
GlobalData.CurPlatform = "pc";
|
||||
#endif
|
||||
#if UNITY_EDITOR
|
||||
GlobalData.CurPlatform = "pc";
|
||||
#endif
|
||||
|
||||
#if UNITY_WEBGL
|
||||
Debug.Log("WEBGL平台");
|
||||
Shader.EnableKeyword("_PLATFORM_WEBGL");
|
||||
#else
|
||||
Debug.Log("非WEBGL平台");
|
||||
Shader.DisableKeyword("_PLATFORM_WEBGL");
|
||||
#endif
|
||||
|
||||
//XGame.UpdateModule module = gameObject.AddComponent<XGame.UpdateModule>();
|
||||
|
||||
//Debug.Log("GameLauncher : Add UpdateModule");
|
||||
//除了WebGL都要进入更新流程,后再开始游戏
|
||||
|
||||
//
|
||||
//开始流程
|
||||
#if XW_DEVTEST
|
||||
if (gameObject.GetComponent<XGame.MiniGame.DevServerSwitchUI>() == null)
|
||||
{
|
||||
gameObject.AddComponent<XGame.MiniGame.DevServerSwitchUI>();
|
||||
}
|
||||
#endif
|
||||
StartCoroutine(this.StartGame());
|
||||
#if UWA
|
||||
//ud 211112 增加uwa组件
|
||||
GameObject uwa = Instantiate(Resources.Load("UWA_Launcher") as GameObject);
|
||||
if(uwa != null)
|
||||
uwa.transform.SetParent(gameObject.transform);
|
||||
#endif
|
||||
#if UWA_AUTO
|
||||
GameObject uwa = Instantiate(Resources.Load("UWA_LauncherAuto") as GameObject);
|
||||
if(uwa != null)
|
||||
uwa.transform.SetParent(gameObject.transform);
|
||||
#endif
|
||||
}
|
||||
|
||||
IEnumerator StartGame()
|
||||
{
|
||||
SystemUIInit();
|
||||
|
||||
UpdateNodeAddress();
|
||||
|
||||
//内网模式:等 DevDiscovery 完成并回填 CurNode/CurCDN(须在 XResLoader.Init / 全量热更之前)
|
||||
if (GlobalData.bLocal && m_LanDiscovery != null)
|
||||
{
|
||||
float deadline = Time.realtimeSinceStartup + 2.0f;
|
||||
while (m_LanDiscovery.IsRunning && Time.realtimeSinceStartup < deadline)
|
||||
yield return null;
|
||||
var found = m_LanDiscovery.TakeResults();
|
||||
m_LanDiscovery = null;
|
||||
if (found.Count > 0)
|
||||
{
|
||||
var r = found[0];
|
||||
GlobalData.CurNode = WithPid(r.GatewayUrl);
|
||||
GlobalData.CurCDN = r.ResourceBaseUrl; // discovery 下发的是 CDN 根
|
||||
Debug.Log($"[GameLauncher] LAN discovered {GlobalData.CurNode} {GlobalData.CurCDN}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[GameLauncher] LAN discovery found no server");
|
||||
}
|
||||
}
|
||||
else if (GlobalData.CurNode == null)
|
||||
{//等待网络获得节点(外网)
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
}
|
||||
|
||||
//大厅/基础资源(XWorld) base:编辑器走本地 CDN(CurCDN),其它 app 端走生产(与 bLocal 无关)。UpdateModule 内部再 +<platform>/
|
||||
string lobbyRoot = GlobalData.bEditor ? NormalizeCdnUrl(GlobalData.CurCDN) : GlobalData.ProductionResBase;
|
||||
XGame.AppConst.UpdateServer = lobbyRoot + "XWorld/";
|
||||
Debug.Log($"UpdateNodeAddress {GlobalData.CurNode} {GlobalData.CurCDN} update={XGame.AppConst.UpdateServer}");
|
||||
|
||||
//重新启用旧全量热更链路(大厅相关热更):从 <CurCDN>/XWorld/<platform>/ 增量下载
|
||||
#if UNITY_WEBGL
|
||||
{
|
||||
XGame.UpdateModule upd = gameObject.GetComponent<XGame.UpdateModule>();
|
||||
if (upd == null) upd = gameObject.AddComponent<XGame.UpdateModule>();
|
||||
//传非空空回调:UpdateModule.DownLoadAssets 多处无守卫地调 onDownloadComplete(),传 null 会 NRE。我们靠 yield 等待,不依赖回调
|
||||
yield return upd.UpdateResAllWebGL(() => { });
|
||||
}
|
||||
#else
|
||||
{
|
||||
XGame.UpdateModule upd = gameObject.GetComponent<XGame.UpdateModule>();
|
||||
if (upd == null) upd = gameObject.AddComponent<XGame.UpdateModule>();
|
||||
//传非空空回调(同上,避免 DownLoadAssets 内 onDownloadComplete() 为 null 时 NRE)
|
||||
yield return upd.UpdateResAll(() => { });
|
||||
upd.SetAllResHash();
|
||||
}
|
||||
#endif
|
||||
//画质控制
|
||||
//RenderTextureDescriptor descriptor = new RenderTextureDescriptor(Screen.width, Screen.height, RenderTextureFormat.Default);
|
||||
//bool isRenderScaleSupported = SystemInfo.SupportsRenderTextureFormat(descriptor.colorFormat) && SystemInfo.supportedRenderTargetCount > 0;
|
||||
//int TargetWidth = 720;
|
||||
QualitySettings.SetQualityLevel(3);//最高画质VeryHigh 3
|
||||
ConfigureFrameRate();
|
||||
EnforceNativeRenderScale();
|
||||
/*if (UnityEngine.Screen.width > TargetWidth)
|
||||
{
|
||||
if (isRenderScaleSupported)
|
||||
{
|
||||
UniversalRenderPipelineAsset URPAsset = GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
|
||||
URPAsset.renderScale = Math.Min((float)TargetWidth / (float)UnityEngine.Screen.width, 1);
|
||||
URPAsset.upscalingFilter = UpscalingFilterSelection.Linear;
|
||||
Debug.Log($"renderScale {URPAsset.renderScale} {Screen.width}x{Screen.height}");
|
||||
}
|
||||
}//*/
|
||||
gameObject.AddComponent<ConsoleWindow>();
|
||||
//gameObject.AddComponent<TerrainManager>();
|
||||
Component obj = gameObject.GetComponent<ConsoleWindow>();
|
||||
//初始化加载模块(静态)
|
||||
yield return XResLoader.Init();
|
||||
//单例
|
||||
Game game = gameObject.AddComponent<Game>();
|
||||
yield return game.Init();
|
||||
EnforceNativeRenderScale();
|
||||
if (gameObject.GetComponent<CharacterSwitchController>() == null)
|
||||
{
|
||||
gameObject.AddComponent<CharacterSwitchController>();
|
||||
}
|
||||
|
||||
//如果仍然没有,则连接默认节点(内网回退本机 WS 网关;外网走生产 WSS 网关。均不再走已废弃的 tcp 7777)
|
||||
if (GlobalData.CurNode == null || GlobalData.CurNode == "")
|
||||
GlobalData.CurNode = GlobalData.bLocal ? WithPid("ws://127.0.0.1:5005/ws") : GlobalData.ProductionGatewayUrl;
|
||||
yield return CSharpClientApp.Init();
|
||||
//yield return TerrainManager.Init();
|
||||
#if UNITY_EDITOR
|
||||
//ConsoleWindow.ConnectConsoleServer(SystemInfo.deviceName);
|
||||
#endif
|
||||
//加载基础资源lua
|
||||
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
//更新内外网网络连接
|
||||
void UpdateNodeAddress()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (!XData.HasKey("XWorldLocal"))
|
||||
{
|
||||
GlobalData.bLocal = true;
|
||||
XData.SetInt("XWorldLocal", 1);
|
||||
XData.Save();
|
||||
}
|
||||
#endif
|
||||
if (XData.HasKey("XWorldLocal"))
|
||||
{
|
||||
GlobalData.bLocal = XData.GetInt("XWorldLocal") == 1;
|
||||
}
|
||||
#if XW_DEVTEST
|
||||
if (XGame.MiniGame.MiniGameTestOverride.IsActive)
|
||||
{
|
||||
GlobalData.CurNode = AddDevPid(XGame.MiniGame.MiniGameTestOverride.GatewayUrl);
|
||||
GlobalData.CurCDN = NormalizeCdnUrl(XGame.MiniGame.MiniGameTestOverride.CdnBase);
|
||||
Debug.Log($"Using dev test override: {GlobalData.CurNode} {GlobalData.CurCDN}");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (GlobalData.bLocal)
|
||||
{
|
||||
//if (XData.HasKey("CurNode"))
|
||||
//{
|
||||
// string savedNode = XData.GetString("CurNode");
|
||||
// if (!string.IsNullOrWhiteSpace(savedNode) &&
|
||||
// (savedNode.StartsWith("ws://", StringComparison.OrdinalIgnoreCase) ||
|
||||
// savedNode.StartsWith("wss://", StringComparison.OrdinalIgnoreCase)))
|
||||
// {
|
||||
// GlobalData.CurNode = savedNode;
|
||||
// GlobalData.CurCDN = NormalizeCdnUrl(XData.GetString("CurCDN"));
|
||||
// Debug.Log($"Using local Gateway node: {GlobalData.CurNode} {GlobalData.CurCDN}");
|
||||
// return;
|
||||
// }
|
||||
//}
|
||||
|
||||
//内网发现:用已有 DevDiscovery(UDP 48923,二进制+token),结果在 StartGame 里等待回填。
|
||||
//服务端:dotnet run --project Server/Gateway.Runner -- --lan --devToken xw-dev
|
||||
m_LanDiscovery = new XGame.MiniGame.DevServerDiscovery(GlobalData.LanDiscoveryToken);
|
||||
m_LanDiscovery.Begin(1500);
|
||||
Debug.Log("[GameLauncher] LAN discovery started (DevDiscovery, token=" + GlobalData.LanDiscoveryToken + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
//如果有保存当前节点,则直接连接
|
||||
if (XData.HasKey("CurNode"))
|
||||
{
|
||||
GlobalData.CurNode = XData.GetString("CurNode");
|
||||
GlobalData.CurCDN = NormalizeCdnUrl(XData.GetString("CurCDN"));
|
||||
//检查链接是否有效
|
||||
Debug.Log($"Check CurNode {GlobalData.CurNode} {GlobalData.CurCDN}");
|
||||
}
|
||||
else
|
||||
{
|
||||
GlobalData.CurNode = GlobalData.ProductionGatewayUrl;
|
||||
GlobalData.CurCDN = NormalizeCdnUrl(GlobalData.ProductionResBase);
|
||||
Debug.Log($"Using default nodes: {GlobalData.CurNode} {GlobalData.CurCDN}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//内网网关地址补设备级稳定 pid,避免两个端都用 pid=1 被服务端当作同一玩家重连。
|
||||
static string WithPid(string gatewayUrl)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(gatewayUrl)) return gatewayUrl;
|
||||
int pid = GetLocalPlayerId();
|
||||
int queryStart = gatewayUrl.IndexOf('?');
|
||||
if (queryStart < 0)
|
||||
{
|
||||
return gatewayUrl + "?pid=" + pid;
|
||||
}
|
||||
|
||||
string head = gatewayUrl.Substring(0, queryStart);
|
||||
string query = gatewayUrl.Substring(queryStart + 1);
|
||||
string[] parts = query.Split('&');
|
||||
bool replaced = false;
|
||||
for (int i = 0; i < parts.Length; i++)
|
||||
{
|
||||
if (parts[i].StartsWith("pid=", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
parts[i] = "pid=" + pid;
|
||||
replaced = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return head + "?" + (replaced ? string.Join("&", parts) : query + "&pid=" + pid);
|
||||
}
|
||||
|
||||
static int GetLocalPlayerId()
|
||||
{
|
||||
string id = XData.GetString(LocalClientIdKey, string.Empty);
|
||||
if (string.IsNullOrEmpty(id))
|
||||
{
|
||||
id = SystemInfo.deviceUniqueIdentifier;
|
||||
if (string.IsNullOrEmpty(id) || id == "unsupported")
|
||||
{
|
||||
id = Guid.NewGuid().ToString("N");
|
||||
}
|
||||
XData.SetString(LocalClientIdKey, id);
|
||||
XData.Save();
|
||||
}
|
||||
|
||||
unchecked
|
||||
{
|
||||
uint hash = 2166136261u;
|
||||
for (int i = 0; i < id.Length; i++)
|
||||
{
|
||||
hash ^= id[i];
|
||||
hash *= 16777619u;
|
||||
}
|
||||
return (int)(hash % 2000000000u) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static string NormalizeCdnUrl(string cdn)
|
||||
{
|
||||
string url = string.IsNullOrWhiteSpace(cdn) ? "http://127.0.0.1:15081/" : cdn.Trim();
|
||||
if (url.StartsWith("http://file://", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
url = url.Substring("http://".Length);
|
||||
}
|
||||
else if (url.StartsWith("https://file://", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
url = url.Substring("https://".Length);
|
||||
}
|
||||
if (url.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
url = NormalizeFileUrl(url);
|
||||
}
|
||||
if (!url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) &&
|
||||
!url.StartsWith("https://", StringComparison.OrdinalIgnoreCase) &&
|
||||
!url.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
url = "http://" + url;
|
||||
}
|
||||
if (!url.EndsWith("/"))
|
||||
{
|
||||
url += "/";
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
static string NormalizeFileUrl(string url)
|
||||
{
|
||||
string rawPath = url.Substring("file://".Length).Replace('\\', '/');
|
||||
while (rawPath.StartsWith("/") && rawPath.Length > 2 && rawPath[2] == ':')
|
||||
{
|
||||
rawPath = rawPath.Substring(1);
|
||||
}
|
||||
|
||||
string localPath = Uri.UnescapeDataString(rawPath).Replace('/', Path.DirectorySeparatorChar);
|
||||
try
|
||||
{
|
||||
return new Uri(localPath).AbsoluteUri;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "file:///" + rawPath.Replace("#", "%23");
|
||||
}
|
||||
}
|
||||
|
||||
static string NormalizeNodeAddress(string node, int defaultPort)
|
||||
{
|
||||
string address = string.IsNullOrWhiteSpace(node) ? $"127.0.0.1:{defaultPort}" : node.Trim();
|
||||
if (address.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
address = address.Substring("http://".Length);
|
||||
}
|
||||
else if (address.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
address = address.Substring("https://".Length);
|
||||
}
|
||||
int slash = address.IndexOf('/');
|
||||
if (slash >= 0)
|
||||
{
|
||||
address = address.Substring(0, slash);
|
||||
}
|
||||
int colon = address.LastIndexOf(':');
|
||||
string host = colon >= 0 ? address.Substring(0, colon) : address;
|
||||
if (string.IsNullOrWhiteSpace(host))
|
||||
{
|
||||
host = "127.0.0.1";
|
||||
}
|
||||
return $"{host}:{defaultPort}";
|
||||
}
|
||||
|
||||
#if XW_DEVTEST
|
||||
static string AddDevPid(string gatewayUrl)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(gatewayUrl))
|
||||
{
|
||||
return gatewayUrl;
|
||||
}
|
||||
return WithPid(gatewayUrl);
|
||||
}
|
||||
#endif
|
||||
|
||||
private void SystemUIInit()
|
||||
{
|
||||
//用按钮区域
|
||||
Transform objTR = GameObject.Find("Main/Touch/OpenPath").transform;
|
||||
Button button = objTR.GetComponent<Button>();
|
||||
//获取多个系统ui组件
|
||||
//搜索Main下的所有子节点(包括隐藏节点)
|
||||
Transform mainTR = GameObject.Find("Main").transform;
|
||||
foreach (Transform child in mainTR)
|
||||
{
|
||||
if(child.name == "Path")
|
||||
{
|
||||
m_PathObj = child.gameObject;
|
||||
}
|
||||
}
|
||||
foreach (Transform child in m_PathObj.transform)
|
||||
{
|
||||
if(child.name == "InputField")
|
||||
{
|
||||
m_InputField = child.GetComponent<InputField>();
|
||||
}
|
||||
if(child.name == "Local")
|
||||
{
|
||||
m_LocalButton = child.GetComponent<Button>();
|
||||
}
|
||||
if(child.name == "Exit")
|
||||
{
|
||||
m_ExitButton = child.GetComponent<Button>();
|
||||
}
|
||||
}
|
||||
m_LocalButton.onClick.AddListener(()=>{
|
||||
GlobalData.bLocal = !GlobalData.bLocal;
|
||||
XData.SetInt("XWorldLocal", GlobalData.bLocal ? 1 : 0);
|
||||
//根据是否内网,设置按钮文本为Local或Online,并记录到XData里
|
||||
if(GlobalData.bLocal)
|
||||
{
|
||||
m_LocalButton.GetComponentInChildren<TMPro.TMP_Text>(true).text = "Local";
|
||||
XData.SetInt("XWorldLocal", 1);
|
||||
XData.Save();
|
||||
//更新节点地址
|
||||
UpdateNodeAddress();
|
||||
//重启lua
|
||||
CSharpClientApp.RestartCurrent();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_LocalButton.GetComponentInChildren<TMPro.TMP_Text>(true).text = "Online";
|
||||
XData.SetInt("XWorldLocal", 0);
|
||||
XData.Save();
|
||||
//更新节点地址
|
||||
UpdateNodeAddress();
|
||||
//重启lua
|
||||
CSharpClientApp.RestartCurrent();
|
||||
}
|
||||
});
|
||||
button.onClick.AddListener(()=>{
|
||||
//显示Main下的Path节点
|
||||
m_PathObj.SetActive(true);
|
||||
bool bLocal = GlobalData.bLocal;
|
||||
if (bLocal)
|
||||
{
|
||||
m_LocalButton.GetComponentInChildren<TMPro.TMP_Text>(true).text = "Local";
|
||||
}
|
||||
//Path下的Exit按钮,按下则隐藏obj
|
||||
m_ExitButton.onClick.AddListener(()=>{
|
||||
if(m_PathObj != null)
|
||||
m_PathObj.SetActive(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private static void ConfigureFrameRate()
|
||||
{
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
QualitySettings.vSyncCount = 0;
|
||||
//OnDemandRendering.renderFrameInterval = 1;
|
||||
Application.targetFrameRate = AndroidTargetFrameRate;
|
||||
Debug.Log($"[GameLauncher] Frame pacing target={Application.targetFrameRate}, displayRefresh={GetDisplayRefreshRate():0.##}, vSync={QualitySettings.vSyncCount}");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR
|
||||
private static double GetDisplayRefreshRate()
|
||||
{
|
||||
#if UNITY_2022_2_OR_NEWER
|
||||
RefreshRate refreshRate = Screen.currentResolution.refreshRateRatio;
|
||||
if (refreshRate.denominator > 0)
|
||||
{
|
||||
return (double)refreshRate.numerator / refreshRate.denominator;
|
||||
}
|
||||
#endif
|
||||
return Screen.currentResolution.refreshRate;
|
||||
}
|
||||
#endif
|
||||
|
||||
private static void EnforceNativeRenderScale()
|
||||
{
|
||||
UniversalRenderPipelineAsset urpAsset = GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
|
||||
if (urpAsset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Mathf.Abs(urpAsset.renderScale - 1f) > 0.001f)
|
||||
{
|
||||
urpAsset.renderScale = 1f;
|
||||
urpAsset.upscalingFilter = UpscalingFilterSelection.Linear;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
//if (GUI.Button(new Rect(30, Screen.height - 48, 60, 30), "Test"))
|
||||
//{
|
||||
// DateTime currentTime = DateTime.Now;
|
||||
// Debug.Log($"当前时间:{currentTime}");
|
||||
//}
|
||||
GUI.Label(new Rect(100, Screen.height - 40, 300, 300), m_sFPS, m_Style);
|
||||
//if (GUI.Button(new Rect(50, Screen.height - 48, 60, 30), "更新"))
|
||||
//{//运行期热更只能下载更新和使用新的资源,dll那些不能运行期换
|
||||
// Debug.LogWarning("Update更新中");
|
||||
// LoadDll.Instance.StartDownload();
|
||||
//}
|
||||
}
|
||||
[BurstCompile]
|
||||
struct MoveJob : IJobParallelFor
|
||||
{
|
||||
public float deltaTime;
|
||||
public float speed;
|
||||
public NativeArray<float3> positions;
|
||||
public NativeArray<float3> velocities;
|
||||
|
||||
public void Execute(int indexOut)
|
||||
{
|
||||
int index = indexOut;
|
||||
//for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
//int index = indexOut * 10 + i;
|
||||
if (positions[index].x > 75 || positions[index].x < -75)
|
||||
{
|
||||
positions[index] = -velocities[index];
|
||||
}
|
||||
if (positions[index].z > 75 || positions[index].z < -75)
|
||||
{
|
||||
velocities[index] = -velocities[index];
|
||||
}
|
||||
positions[index] += velocities[index] * speed;//deltaTime
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Update()
|
||||
{
|
||||
m_nCount++;
|
||||
|
||||
if (m_fLastTime == 0)
|
||||
{
|
||||
m_fLastTime = Time.realtimeSinceStartup;
|
||||
}
|
||||
else
|
||||
{
|
||||
float CurTime = Time.realtimeSinceStartup;
|
||||
if (CurTime - m_fLastTime > 1.0f)
|
||||
{
|
||||
m_sFPS = $"{m_nCount} | {XResLoader.m_displayProgress}%";
|
||||
m_nCount = 0;
|
||||
m_fLastTime = CurTime;
|
||||
}
|
||||
}
|
||||
/*
|
||||
float deltaTime = Time.deltaTime;
|
||||
var job = new MoveJob
|
||||
{
|
||||
deltaTime = deltaTime,
|
||||
positions = positions,
|
||||
velocities = velocities,
|
||||
speed = speed
|
||||
};
|
||||
JobHandle jobHandle = job.Schedule<MoveJob>(objectCount, 64);
|
||||
jobHandle.Complete();
|
||||
|
||||
for (int i = 0; i < objectCount; ++i)
|
||||
{
|
||||
sphereObjs[i].obj.transform.position = positions[i];
|
||||
|
||||
}//*/
|
||||
foreach (var i in sphereObjs)
|
||||
{
|
||||
i.pos += i.vec * 0.1f;
|
||||
|
||||
if (i.pos.x > m_fSize || i.pos.x < -m_fSize)
|
||||
{
|
||||
i.vec.x = -i.vec.x;
|
||||
}
|
||||
if (i.pos.z > m_fSize || i.pos.z < -m_fSize)
|
||||
{
|
||||
i.vec.z = -i.vec.z;
|
||||
}
|
||||
|
||||
i.tr.position = i.pos;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if(positions.IsCreated)
|
||||
positions.Dispose();
|
||||
if(velocities.IsCreated)
|
||||
velocities.Dispose();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user