124 lines
4.1 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Collections;
using Unity.Burst;
using Unity.Jobs;
using Unity.Mathematics;
public class Game : MonoBehaviour
{
[SerializeField] private int numBlues;
[SerializeField] private int numReds;
[SerializeField] private GameObject bluePrefab;
[SerializeField] private GameObject redPrefab;
[SerializeField] private Rect[] areasOfTheMap;
private int maxQuadTreeSize;
private Transform[] blueTransforms;
private Transform[] redTransforms;
private NativeArray<float2> bluePositions;
private NativeArray<float2> redPositions;
private NativeArray<float4> quadTree;
private NativeArray<long> nearestEnemyOfBlueIndex;
private NativeArray<long> nearestEnemyOfRedIndex;
public void Start()
{
blueTransforms = new Transform[numBlues];
redTransforms = new Transform[numReds];
int nearestPowerOf2(int n)
{
int a = (int)(Math.Log(n) / Math.Log(2));
return (int)Math.Pow(2, a) == n
? n
: (int)Math.Pow(2, a + 1);
}
maxQuadTreeSize = nearestPowerOf2(numBlues + numReds);
// This is actually the size of the max subdivisions
int maxSubDivisions = 5;
maxQuadTreeSize = (int)Math.Pow(4, maxSubDivisions);
Debug.Log(maxQuadTreeSize);
void InstantiatePrefabs(int amount, GameObject prefab, Transform[] transforms, Rect area) {
for (int i = 0; i < amount; i++) {
var go = GameObject.Instantiate(prefab);
transforms[i] = go.transform;
float randX = UnityEngine.Random.Range(area.x, area.x + area.width);
float randY = UnityEngine.Random.Range(area.y, area.y + area.height);
go.transform.localPosition = new Vector3(randX, 0, randY);
}
};
InstantiatePrefabs(numBlues, bluePrefab, blueTransforms, areasOfTheMap[0]);
InstantiatePrefabs(numReds, redPrefab, redTransforms, areasOfTheMap[1]);
bluePositions = new NativeArray<float2>(numBlues, Allocator.Persistent);
redPositions = new NativeArray<float2>(numReds, Allocator.Persistent);
quadTree = new NativeArray<float4>(maxQuadTreeSize, Allocator.Persistent);
nearestEnemyOfBlueIndex = new NativeArray<long>(numBlues, Allocator.Persistent);
nearestEnemyOfRedIndex = new NativeArray<long>(numReds, Allocator.Persistent);
}
float2 Vec3ToF2(Vector3 v) => new float2(v.x, v.z);
public void Update()
{
int i = 0;
int min = numBlues > numReds ? numBlues : numReds;
while (i < min)
{
bluePositions[i] = Vec3ToF2(blueTransforms[i].localPosition);
redPositions[i] = Vec3ToF2(redTransforms[i].localPosition);
i++;
}
while (i < numBlues)
{
bluePositions[i] = Vec3ToF2(blueTransforms[i].localPosition);
i++;
}
while (i < numReds)
{
redPositions[i] = Vec3ToF2(redTransforms[i].localPosition);
i++;
}
var constructJob = new ConstructQuadTreeJob
{
positions = bluePositions,
quadTree = quadTree,
};
var constructHandle = constructJob.Schedule(maxQuadTreeSize, 100);
constructHandle.Complete();
var findEnemyJob = new FindNearestEnemyQuadTreeJob
{
bluePositions = bluePositions,
redPositions = redPositions,
quadTree = quadTree,
nearestEnemyOfBlueIndex = nearestEnemyOfBlueIndex,
nearestEnemyOfRedIndex = nearestEnemyOfRedIndex,
};
var findRedsHandle = findEnemyJob.Schedule(numBlues, 100);
// We don't have a dependency on findRedsHandle, but we do have to wait for both
// findReds and findBlues to finish
findRedsHandle.Complete();
var findBluesHandle = findEnemyJob.Schedule(numReds, 100);
findBluesHandle.Complete();
}
public void OnDestroy()
{
bluePositions.Dispose();
redPositions.Dispose();
quadTree.Dispose();
}
}