using System.Threading; using TMPro; using UnityEngine; public class ThreadedWaveSimulation : MonoBehaviour { public GameObject spherePrefab; [Range(250, 90000)] public int totalSpheres = 40000; public float waveSpeed = 1f; public float waveHeight = 0.5f; public TMP_Text fpsText; private GameObject[,] spheres; private int rows; private int columns; private float deltaTime = 0.0f; void Start() { CalculateRowsAndColumns(); SpawnSpheres(); } void Update() { CalculateFPS(); AnimateSpheresThreaded(); } void CalculateFPS() { deltaTime += (Time.unscaledDeltaTime - deltaTime) * 0.1f; float fps = 1.0f / deltaTime; fpsText.text = $"FPS: {Mathf.Ceil(fps)}"; } void CalculateRowsAndColumns() { float ratio = Mathf.Sqrt(totalSpheres / 400.0f); // assuming 400 spheres initially rows = Mathf.Max(Mathf.RoundToInt(20 * ratio), 5); columns = Mathf.Max(Mathf.RoundToInt(20 * ratio), 5); Debug.Log($"Rows: {rows}, Columns: {columns}"); } void SpawnSpheres() { spheres = new GameObject[rows, columns]; for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { GameObject sphere = Instantiate(spherePrefab, new Vector3(i, 0, j), Quaternion.identity); spheres[i, j] = sphere; } } } void AnimateSpheresThreaded() { float time = Time.time; Thread[] threads = new Thread[Mathf.Min(rows, System.Environment.ProcessorCount)]; for (int i = 0; i < threads.Length; i++) { int startIndex = i * (rows / threads.Length); int endIndex = (i + 1) * (rows / threads.Length); threads[i] = new Thread(() => AnimateSpheresChunk(time, startIndex, endIndex)); threads[i].Start(); } // Wait for all threads to finish foreach (Thread thread in threads) { thread.Join(); } } void AnimateSpheresChunk(float time, int startIndex, int endIndex) { for (int i = startIndex; i < endIndex; i++) { for (int j = 0; j < columns; j++) { float perlinValue = Mathf.PerlinNoise(i * 0.1f, j * 0.1f); float waveOffset = Mathf.Sin(perlinValue * 2 * Mathf.PI + time * waveSpeed) * waveHeight; // Access the corresponding GameObject based on the index GameObject sphere = spheres[i, j]; if (sphere != null) { // Update the GameObject's position sphere.transform.position = new Vector3(i, waveOffset, j); } } } } }