Created
August 1, 2021 13:55
-
-
Save simonwittber/655745b311e0ac67f1c65f20ac5d65e4 to your computer and use it in GitHub Desktop.
Component Systems using Jobs and Burst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using Unity.Jobs; | |
using UnityEngine; | |
static internal class ComponentBatch<T, U, V> | |
where T : MonoBehaviourComponent<T, U, V> where U : MonoBehaviourSystem<T, U, V> | |
where V: struct, IJobParallelFor | |
{ | |
internal static Queue<T> components = new Queue<T>(); | |
internal static Queue<T> newComponents = new Queue<T>(); | |
internal static U system = null; | |
internal static void Setup(T component) | |
{ | |
if (system == null) | |
{ | |
var systems = Resources.FindObjectsOfTypeAll<U>(); | |
if (systems.Length > 0) | |
system = systems[0]; | |
else | |
{ | |
system = new GameObject($"System:{typeof(T)}").AddComponent<U>(); | |
} | |
} | |
if (!system.enabled) | |
system.enabled = true; | |
newComponents.Enqueue(component); | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
public class CullableComponent : MonoBehaviourComponent<CullableComponent, CullableSystem, CullableJob> | |
{ | |
public bool wasVisible; | |
public bool isVisible; | |
public Bounds bounds; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using Unity.Burst; | |
using Unity.Collections; | |
using Unity.Jobs; | |
using Unity.Mathematics; | |
using UnityEngine; | |
[BurstCompile] | |
public struct CullableJob : IJobParallelFor | |
{ | |
public NativeArray<bool> wasVisible, isVisible; | |
public NativeArray<float3> centers, extents; | |
public NativeArray<float4> frustum; | |
public void Execute(int index) | |
{ | |
isVisible[index] = TestPlanesAABB(centers[index], extents[index]); | |
} | |
bool TestPlanesAABB(float3 center, float3 extent) | |
{ | |
for (var i = 0; i < 6; i++) | |
{ | |
var p = frustum[i]; | |
float3 normal = p.xyz; | |
var dist = math.dot(normal, center) + p.w; | |
var radius = math.dot(extent, math.abs(normal)); | |
if (dist + radius < 0) | |
return false; | |
} | |
return true; | |
} | |
} | |
public class CullableSystem : MonoBehaviourSystem<CullableComponent, CullableSystem, CullableJob> | |
{ | |
public override CullableJob CreateJob(Queue<CullableComponent> components) | |
{ | |
var job = new CullableJob(); | |
var camera = Camera.main; //yeah yeah | |
job.frustum = new NativeArray<float4>(6, Allocator.TempJob); | |
var planes = GeometryUtility.CalculateFrustumPlanes(camera); | |
for (var i = 0; i < 6; i++) | |
{ | |
var plane = (Vector4)planes[i].normal; | |
plane.w = planes[i].distance; | |
job.frustum[i] = plane; | |
} | |
var size = components.Count; | |
var wasVisible = job.wasVisible = new NativeArray<bool>(size, Allocator.TempJob); | |
var isVisible = job.isVisible = new NativeArray<bool>(size, Allocator.TempJob); | |
var centers = job.centers = new NativeArray<float3>(size, Allocator.TempJob); | |
var extents = job.extents = new NativeArray<float3>(size, Allocator.TempJob); | |
for (int i = 0, count = components.Count; i < count; i++) | |
{ | |
var cullable = components.Dequeue(); | |
components.Enqueue(cullable); | |
cullable.wasVisible = cullable.isVisible; | |
centers[i] = cullable.transform.position; | |
extents[i] = cullable.bounds.size; | |
} | |
return job; | |
} | |
public override void OnJobComplete(Queue<CullableComponent> components, CullableJob job) | |
{ | |
for (int i = 0, count = components.Count; i < count; i++) | |
{ | |
var cullable = components.Dequeue(); | |
components.Enqueue(cullable); | |
cullable.isVisible = job.isVisible[i]; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Unity.Jobs; | |
using UnityEngine; | |
public abstract class MonoBehaviourComponent<T, U, V> : MonoBehaviour | |
where T : MonoBehaviourComponent<T, U, V> | |
where U : MonoBehaviourSystem<T, U, V> | |
where V: struct, IJobParallelFor | |
{ | |
protected virtual void OnEnable() | |
{ | |
ComponentBatch<T, U, V>.Setup((T)this); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using Unity.Jobs; | |
using UnityEngine; | |
public abstract class MonoBehaviourSystem<T, U, V> : MonoBehaviour | |
where T : MonoBehaviourComponent<T,U,V> where U : MonoBehaviourSystem<T, U,V> | |
where V: struct, IJobParallelFor | |
{ | |
private JobHandle handle; | |
private V job; | |
public abstract V CreateJob(Queue<T> components); | |
public abstract void OnJobComplete(Queue<T> components, V job); | |
public virtual void InitComponent(T component) | |
{ | |
} | |
private void Update() | |
{ | |
while (ComponentBatch<T, U, V>.newComponents.Count > 0) | |
{ | |
var component = ComponentBatch<T, U, V>.newComponents.Dequeue(); | |
InitComponent(component); | |
ComponentBatch<T, U, V>.components.Enqueue(component); | |
} | |
var components = ComponentBatch<T, U, V>.components; | |
job = CreateJob(components); | |
handle = job.Schedule(components.Count, 24); | |
} | |
private void LateUpdate() | |
{ | |
handle.Complete(); | |
OnJobComplete(ComponentBatch<T, U, V>.components, job); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment