Примеры кода
Основы Entity Component System (ECS)
Создание сущностей, компонентов и систем для высокопроизводительной архитектуры.
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
// Компонент для движения
public struct MovementComponent : IComponentData
{
public float3 velocity;
public float speed;
}
// Система движения
[UpdateInGroup(typeof(SimulationSystemGroup))]
public partial class MovementSystem : SystemBase
{
protected override void OnUpdate()
{
float deltaTime = Time.DeltaTime;
Entities
.WithAll<MovementComponent>()
.ForEach((ref Translation translation, in MovementComponent movement) =>
{
translation.Value += movement.velocity * movement.speed * deltaTime;
// Ограничение области движения
if (math.abs(translation.Value.x) > 50f)
translation.Value.x = -translation.Value.x;
if (math.abs(translation.Value.z) > 50f)
translation.Value.z = -translation.Value.z;
}).ScheduleParallel();
}
}
// MonoBehaviour для создания сущностей
public class EntitySpawner : MonoBehaviour
{
public GameObject prefab;
public int spawnCount = 1000;
void Start()
{
var entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
var settings = GameObjectConversionSettings.FromWorld(
World.DefaultGameObjectInjectionWorld, null);
var prefabEntity = GameObjectConversionUtility.ConvertGameObjectHierarchy(
prefab, settings);
Debug.Log($"Создание {spawnCount} сущностей с ECS");
for (int i = 0; i < spawnCount; i++)
{
var entity = entityManager.Instantiate(prefabEntity);
entityManager.AddComponentData(entity, new MovementComponent
{
velocity = new float3(
UnityEngine.Random.Range(-1f, 1f),
0,
UnityEngine.Random.Range(-1f, 1f)
),
speed = UnityEngine.Random.Range(5f, 15f)
});
}
Debug.Log("ECS сущности созданы успешно");
}
}
Jobs System для параллельных вычислений
Использование Jobs System для эффективной обработки больших объемов данных.
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
// Job для обработки позиций частиц
public struct ParticleUpdateJob : IJobParallelFor
{
public NativeArray<float3> positions;
public NativeArray<float3> velocities;
[ReadOnly] public float deltaTime;
[ReadOnly] public float3 gravity;
public void Execute(int index)
{
velocities[index] += gravity * deltaTime;
positions[index] += velocities[index] * deltaTime;
// Отскок от земли
if (positions[index].y < 0)
{
positions[index] = new float3(positions[index].x, 0, positions[index].z);
velocities[index] = new float3(
velocities[index].x * 0.8f,
-velocities[index].y * 0.8f,
velocities[index].z * 0.8f
);
}
}
}
// Менеджер системы частиц
public class ParticleSystemManager : MonoBehaviour
{
public int particleCount = 10000;
public GameObject particlePrefab;
private NativeArray<float3> positions;
private NativeArray<float3> velocities;
private Transform[] particleTransforms;
private JobHandle jobHandle;
void Start()
{
InitializeParticles();
Debug.Log($"Инициализирована система частиц с {particleCount} частицами");
}
void InitializeParticles()
{
positions = new NativeArray<float3>(particleCount, Allocator.Persistent);
velocities = new NativeArray<float3>(particleCount, Allocator.Persistent);
particleTransforms = new Transform[particleCount];
for (int i = 0; i < particleCount; i++)
{
var particle = Instantiate(particlePrefab);
particleTransforms[i] = particle.transform;
positions[i] = new float3(
UnityEngine.Random.Range(-25f, 25f),
UnityEngine.Random.Range(10f, 50f),
UnityEngine.Random.Range(-25f, 25f)
);
velocities[i] = new float3(
UnityEngine.Random.Range(-10f, 10f),
0,
UnityEngine.Random.Range(-10f, 10f)
);
}
}
void Update()
{
jobHandle.Complete();
var particleJob = new ParticleUpdateJob
{
positions = positions,
velocities = velocities,
deltaTime = Time.deltaTime,
gravity = new float3(0, -9.81f, 0)
};
jobHandle = particleJob.Schedule(particleCount, 64);
jobHandle.Complete();
// Обновление Transform компонентов
for (int i = 0; i < particleCount; i++)
{
if (particleTransforms[i] != null)
{
particleTransforms[i].position = positions[i];
}
}
}
void OnDestroy()
{
jobHandle.Complete();
if (positions.IsCreated) positions.Dispose();
if (velocities.IsCreated) velocities.Dispose();
}
}
Burst Compiler для максимальной производительности
Использование Burst Compiler для компиляции высокопроизводительного кода.
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
// Burst-компилированный job
[BurstCompile]
public struct MathIntensiveJob : IJobParallelFor
{
[ReadOnly] public NativeArray<float3> inputPositions;
public NativeArray<float3> outputPositions;
[ReadOnly] public float time;
[ReadOnly] public float frequency;
[ReadOnly] public float amplitude;
public void Execute(int index)
{
float3 pos = inputPositions[index];
// Сложные математические вычисления
float wave1 = math.sin(pos.x * frequency + time) * amplitude;
float wave2 = math.cos(pos.z * frequency + time) * amplitude;
float height = wave1 + wave2;
outputPositions[index] = new float3(pos.x, height, pos.z);
}
}
// Менеджер с Burst-оптимизацией
public class BurstOptimizedManager : MonoBehaviour
{
public int objectCount = 50000;
public GameObject objectPrefab;
public float waveFrequency = 0.5f;
public float waveAmplitude = 5f;
private NativeArray<float3> originalPositions;
private NativeArray<float3> currentPositions;
private Transform[] objectTransforms;
private JobHandle jobHandle;
void Start()
{
InitializeSimulation();
Debug.Log($"Burst-оптимизированная симуляция с {objectCount} объектами");
}
void InitializeSimulation()
{
originalPositions = new NativeArray<float3>(objectCount, Allocator.Persistent);
currentPositions = new NativeArray<float3>(objectCount, Allocator.Persistent);
objectTransforms = new Transform[objectCount];
int gridSize = Mathf.CeilToInt(Mathf.Sqrt(objectCount));
for (int i = 0; i < objectCount; i++)
{
int x = i % gridSize;
int z = i / gridSize;
float3 position = new float3(x * 2f - gridSize, 0, z * 2f - gridSize);
originalPositions[i] = position;
var obj = Instantiate(objectPrefab);
objectTransforms[i] = obj.transform;
}
}
void Update()
{
jobHandle.Complete();
var mathJob = new MathIntensiveJob
{
inputPositions = originalPositions,
outputPositions = currentPositions,
time = Time.time,
frequency = waveFrequency,
amplitude = waveAmplitude
};
jobHandle = mathJob.Schedule(objectCount, 128);
jobHandle.Complete();
// Обновление Transform компонентов
for (int i = 0; i < objectCount; i++)
{
if (objectTransforms[i] != null)
{
objectTransforms[i].position = currentPositions[i];
}
}
}
void OnDestroy()
{
jobHandle.Complete();
if (originalPositions.IsCreated) originalPositions.Dispose();
if (currentPositions.IsCreated) currentPositions.Dispose();
}
}
Оптимизация производительности
Продвинутые техники оптимизации для максимальной производительности.
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
// Компонент для LOD системы
public struct LODComponent : IComponentData
{
public float distance;
public int lodLevel;
public bool isVisible;
}
// Система LOD
[UpdateInGroup(typeof(SimulationSystemGroup))]
public partial class LODSystem : SystemBase
{
protected override void OnUpdate()
{
float3 cameraPosition = Camera.main.transform.position;
Entities
.WithAll<LODComponent>()
.ForEach((ref LODComponent lod, in Translation translation) =>
{
float distance = math.distance(translation.Value, cameraPosition);
lod.distance = distance;
if (distance < 10f)
{
lod.lodLevel = 0; // Высокая детализация
lod.isVisible = true;
}
else if (distance < 50f)
{
lod.lodLevel = 1; // Средняя детализация
lod.isVisible = true;
}
else
{
lod.isVisible = false; // Не отображать
}
}).ScheduleParallel();
}
}
// Менеджер производительности
public class PerformanceManager : MonoBehaviour
{
public int targetFPS = 60;
public float cullingDistance = 200f;
private float frameTime;
void Update()
{
frameTime = Time.deltaTime;
float currentFPS = 1f / frameTime;
// Адаптивная оптимизация
if (currentFPS < targetFPS * 0.8f)
{
ReduceQuality();
}
else if (currentFPS > targetFPS * 1.2f)
{
IncreaseQuality();
}
if (Time.frameCount % 60 == 0)
{
Debug.Log($"FPS: {currentFPS:F1}");
}
}
void ReduceQuality()
{
cullingDistance = math.max(50f, cullingDistance * 0.9f);
Debug.Log("Качество снижено для улучшения производительности");
}
void IncreaseQuality()
{
cullingDistance = math.min(200f, cullingDistance * 1.05f);
Debug.Log("Качество повышено");
}
}
Массовая симуляция с тысячами объектов
Создание масштабируемых симуляций с большим количеством объектов.
using Unity.Entities;
using Unity.Collections;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
// Компонент для роя
public struct SwarmComponent : IComponentData
{
public float3 target;
public float speed;
public float separationRadius;
}
// Система роя (Boids)
[UpdateInGroup(typeof(SimulationSystemGroup))]
public partial class SwarmSystem : SystemBase
{
protected override void OnUpdate()
{
float deltaTime = Time.DeltaTime;
Entities
.ForEach((ref Translation translation, in SwarmComponent swarm) =>
{
// Движение к цели
float3 toTarget = math.normalize(swarm.target - translation.Value);
translation.Value += toTarget * swarm.speed * deltaTime;
}).ScheduleParallel();
}
}
// Массовый симулятор
public class MassiveSimulation : MonoBehaviour
{
public GameObject entityPrefab;
public int entityCount = 50000;
public float spawnRadius = 100f;
private EntityManager entityManager;
void Start()
{
InitializeMassiveSimulation();
Debug.Log($"Массовая симуляция с {entityCount} объектами");
}
void InitializeMassiveSimulation()
{
entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
var settings = GameObjectConversionSettings.FromWorld(
World.DefaultGameObjectInjectionWorld, null);
var prefabEntity = GameObjectConversionUtility.ConvertGameObjectHierarchy(
entityPrefab, settings);
var entities = new NativeArray<Entity>(entityCount, Allocator.Temp);
entityManager.Instantiate(prefabEntity, entities);
for (int i = 0; i < entityCount; i++)
{
var entity = entities[i];
float3 randomPos = UnityEngine.Random.insideUnitSphere * spawnRadius;
randomPos.y = math.abs(randomPos.y);
entityManager.SetComponentData(entity, new Translation
{
Value = randomPos
});
entityManager.AddComponentData(entity, new SwarmComponent
{
target = float3.zero,
speed = UnityEngine.Random.Range(5f, 15f),
separationRadius = 2f
});
}
entities.Dispose();
}
void Update()
{
// Обновление цели на основе позиции мыши
if (Input.GetMouseButton(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit))
{
UpdateSwarmTarget(hit.point);
}
}
}
void UpdateSwarmTarget(float3 newTarget)
{
Entities
.WithAll<SwarmComponent>()
.ForEach((ref SwarmComponent swarm) =>
{
swarm.target = newTarget;
}).Run();
}
}