Files
BABA_YAGA/Assets/Scripts/Optimization/JobsMovementManager.cs
2026-03-26 20:27:19 +07:00

130 lines
4.4 KiB
C#

using UnityEngine;
using Unity.Collections;
using Unity.Jobs;
using UnityEngine.Jobs;
using Unity.Burst;
namespace Elbyss.Optimization
{
/// <summary>
/// Manages 10,000+ objects using C# Job System and Burst Compiler.
/// This avoids the overhead of 10,000 individual Update() calls.
/// </summary>
public class JobsMovementManager : MonoBehaviour
{
[Header("Spawn Settings")]
public GameObject prefab;
public int objectCount = 10000;
public float spacing = 1.5f;
[Header("Movement Settings")]
public float speed = 5f;
private TransformAccessArray transformAccessArray;
private NativeArray<Vector3> directions;
private bool isInitialized = false;
private void Start()
{
// Optional: Start automatically or via Context Menu
// Setup(objectCount);
}
[ContextMenu("Setup 10k Objects")]
public void InitialSetup()
{
Setup(objectCount);
}
public void Setup(int count)
{
if (isInitialized) Cleanup();
objectCount = count;
Transform[] transforms = new Transform[objectCount];
directions = new NativeArray<Vector3>(objectCount, Allocator.Persistent);
int rowSize = Mathf.CeilToInt(Mathf.Sqrt(objectCount));
for (int i = 0; i < objectCount; i++)
{
float x = (i % rowSize) * spacing;
float z = (i / rowSize) * spacing;
Vector3 pos = transform.position + new Vector3(x, 0, z);
GameObject go = Instantiate(prefab, pos, Quaternion.identity, this.transform);
transforms[i] = go.transform;
// Set alternating directions
directions[i] = (i % 2 == 0) ? Vector3.forward : Vector3.back;
// CRITICAL OPTIMIZATION: Disable components that are too heavy for 10k objects
if (go.TryGetComponent<Animator>(out var anim)) anim.enabled = false;
if (go.TryGetComponent<CharacterController>(out var cc)) cc.enabled = false;
// Disable all other custom scripts
MonoBehaviour[] scripts = go.GetComponents<MonoBehaviour>();
foreach (var s in scripts)
{
if (s != this) s.enabled = false;
}
}
transformAccessArray = new TransformAccessArray(transforms);
isInitialized = true;
Debug.Log($"Initialized {objectCount} objects with Job System.");
}
private void Update()
{
if (!isInitialized) return;
// Create the movement job
var job = new MovementJob
{
DeltaTime = Time.deltaTime,
Speed = speed,
Directions = directions
};
// Schedule the job to run in parallel on all available CPU cores
// transformAccessArray allows the job to modify Transform data directly
JobHandle handle = job.Schedule(transformAccessArray);
// This ensures the job is finished before the frame ends
// In a real scenario, you might want to call Complete() in LateUpdate or next frame
// but for simple movement, scheduling and completing in Update is fine.
handle.Complete();
}
private void OnDestroy()
{
Cleanup();
}
private void Cleanup()
{
if (isInitialized)
{
if (transformAccessArray.isCreated) transformAccessArray.Dispose();
if (directions.IsCreated) directions.Dispose();
isInitialized = false;
}
}
[BurstCompile] // This attribute tells the Burst compiler to optimize this job into machine code
struct MovementJob : IJobParallelForTransform
{
public float DeltaTime;
public float Speed;
[ReadOnly] public NativeArray<Vector3> Directions;
public void Execute(int index, TransformAccess transform)
{
// Directly modify the transform position in parallel
transform.position += Directions[index] * Speed * DeltaTime;
}
}
}
}