Reorganization and many improvements of rendering

This commit is contained in:
Daniel Lovell
2024-09-12 10:36:45 -07:00
parent 76b6037ce8
commit 742da94fe9
49 changed files with 1434 additions and 64 deletions

View File

@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using UnityEngine;
// The assignment class is an interface for assigning a target to each missile.
public abstract class Assignment
{
// Assignment item type.
// The first element corresponds to the missile index, and the second element
// corresponds to the target index.
public struct AssignmentItem
{
public int MissileIndex;
public int TargetIndex;
public AssignmentItem(int missileIndex, int targetIndex)
{
MissileIndex = missileIndex;
TargetIndex = targetIndex;
}
}
// A list containing the missile-target assignments.
protected LinkedList<AssignmentItem> missileToTargetAssignments = new LinkedList<AssignmentItem>();
// Return the missile-target assignments.
public IEnumerable<AssignmentItem> Assignments => missileToTargetAssignments;
// Assign a target to each missile that has not been assigned a target yet.
public abstract void Assign(List<Agent> missiles, List<Agent> targets);
// Get the list of assignable missile indices.
protected static List<int> GetAssignableMissileIndices(List<Agent> missiles)
{
List<int> assignableMissileIndices = new List<int>();
for (int missileIndex = 0; missileIndex < missiles.Count; missileIndex++)
{
if (missiles[missileIndex].IsAssignable())
{
assignableMissileIndices.Add(missileIndex);
}
}
return assignableMissileIndices;
}
// Get the list of active target indices.
protected static List<int> GetActiveTargetIndices(List<Agent> targets)
{
List<int> activeTargetIndices = new List<int>();
for (int targetIndex = 0; targetIndex < targets.Count; targetIndex++)
{
if (!targets[targetIndex].IsHit())
{
activeTargetIndices.Add(targetIndex);
}
}
return activeTargetIndices;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 95c1ee01149331443bb91460f4d1e3a2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
// The round-robin assignment class assigns missiles to the targets in a
// round-robin order.
public class RoundRobinAssignment : Assignment
{
// Previous target index that was assigned.
private int prevTargetIndex = -1;
// Assign a target to each missile that has not been assigned a target yet.
public override void Assign(List<Agent> missiles, List<Agent> targets)
{
List<int> assignableMissileIndices = GetAssignableMissileIndices(missiles);
if (assignableMissileIndices.Count == 0)
{
return;
}
List<int> activeTargetIndices = GetActiveTargetIndices(targets);
if (activeTargetIndices.Count == 0)
{
return;
}
foreach (int missileIndex in assignableMissileIndices)
{
int nextActiveTargetIndex = activeTargetIndices
.FindIndex(index => index > prevTargetIndex);
if (nextActiveTargetIndex == -1)
{
nextActiveTargetIndex = 0;
}
int nextTargetIndex = activeTargetIndices[nextActiveTargetIndex];
missileToTargetAssignments.AddFirst(new AssignmentItem(missileIndex, nextTargetIndex));
prevTargetIndex = nextTargetIndex;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f668f6d7413495c4093550e492ce36bd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
// The threat assignment class assigns missiles to the targets based
// on the threat level of the targets.
public class ThreatAssignment : Assignment
{
// Assign a target to each missile that has not been assigned a target yet.
public override void Assign(List<Agent> missiles, List<Agent> targets)
{
List<int> assignableMissileIndices = GetAssignableMissileIndices(missiles);
if (assignableMissileIndices.Count == 0)
{
return;
}
List<int> activeTargetIndices = GetActiveTargetIndices(targets);
if (activeTargetIndices.Count == 0)
{
return;
}
Vector3 missilesMeanPosition = CalculateMeanPosition(missiles);
List<ThreatInfo> threatInfos = CalculateThreatLevels(targets, activeTargetIndices, missilesMeanPosition);
foreach (int missileIndex in assignableMissileIndices)
{
if (threatInfos.Count == 0) break;
ThreatInfo highestThreat = threatInfos[0];
missileToTargetAssignments.AddFirst(new AssignmentItem(missileIndex, highestThreat.TargetIndex));
threatInfos.RemoveAt(0);
}
}
private Vector3 CalculateMeanPosition(List<Agent> agents)
{
return agents.Aggregate(Vector3.zero, (sum, agent) => sum + agent.transform.position) / agents.Count;
}
private List<ThreatInfo> CalculateThreatLevels(List<Agent> targets, List<int> activeTargetIndices, Vector3 missilesMeanPosition)
{
List<ThreatInfo> threatInfos = new List<ThreatInfo>();
foreach (int targetIndex in activeTargetIndices)
{
Agent target = targets[targetIndex];
float distanceToMean = Vector3.Distance(target.transform.position, missilesMeanPosition);
float velocityMagnitude = target.GetVelocity().magnitude;
// Calculate threat level based on proximity and velocity
float threatLevel = (1 / distanceToMean) * velocityMagnitude;
threatInfos.Add(new ThreatInfo(targetIndex, threatLevel));
}
// Sort threats in descending order
return threatInfos.OrderByDescending(t => t.ThreatLevel).ToList();
}
private class ThreatInfo
{
public int TargetIndex { get; }
public float ThreatLevel { get; }
public ThreatInfo(int targetIndex, float threatLevel)
{
TargetIndex = targetIndex;
ThreatLevel = threatLevel;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8e9829915a9eb41409ea03fb46910432
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: