647 lines
22 KiB
C#
647 lines
22 KiB
C#
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();
|
||
}
|
||
}
|