Reuse HashSets for actors entered/exited in CellTrigger & ProximityTrigger.
Actors involved in the trigger are determined as actors move around near the trigger - and can be expensive in some maps. This allows us to avoid allocating new sets and the CPU hit required to set it up each time.
This commit is contained in:
committed by
Paul Chote
parent
11b44963da
commit
986025ca76
@@ -48,8 +48,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
readonly Action<Actor> onActorEntered;
|
readonly Action<Actor> onActorEntered;
|
||||||
readonly Action<Actor> onActorExited;
|
readonly Action<Actor> onActorExited;
|
||||||
|
readonly HashSet<Actor> oldActors = new HashSet<Actor>();
|
||||||
IEnumerable<Actor> currentActors = Enumerable.Empty<Actor>();
|
readonly HashSet<Actor> currentActors = new HashSet<Actor>();
|
||||||
|
|
||||||
public CellTrigger(CPos[] footprint, Action<Actor> onActorEntered, Action<Actor> onActorExited)
|
public CellTrigger(CPos[] footprint, Action<Actor> onActorEntered, Action<Actor> onActorExited)
|
||||||
{
|
{
|
||||||
@@ -67,18 +67,21 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (!Dirty)
|
if (!Dirty)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var oldActors = currentActors;
|
// PERF: Reuse collection to avoid allocations.
|
||||||
currentActors = Footprint.SelectMany(actorMap.GetActorsAt).ToList();
|
oldActors.Clear();
|
||||||
|
oldActors.UnionWith(currentActors);
|
||||||
|
|
||||||
var entered = currentActors.Except(oldActors);
|
currentActors.Clear();
|
||||||
var exited = oldActors.Except(currentActors);
|
currentActors.UnionWith(Footprint.SelectMany(actorMap.GetActorsAt));
|
||||||
|
|
||||||
if (onActorEntered != null)
|
if (onActorEntered != null)
|
||||||
foreach (var a in entered)
|
foreach (var a in currentActors)
|
||||||
|
if (!oldActors.Contains(a))
|
||||||
onActorEntered(a);
|
onActorEntered(a);
|
||||||
|
|
||||||
if (onActorExited != null)
|
if (onActorExited != null)
|
||||||
foreach (var a in exited)
|
foreach (var a in oldActors)
|
||||||
|
if (!currentActors.Contains(a))
|
||||||
onActorExited(a);
|
onActorExited(a);
|
||||||
|
|
||||||
Dirty = false;
|
Dirty = false;
|
||||||
@@ -94,13 +97,13 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
readonly Action<Actor> onActorEntered;
|
readonly Action<Actor> onActorEntered;
|
||||||
readonly Action<Actor> onActorExited;
|
readonly Action<Actor> onActorExited;
|
||||||
|
readonly HashSet<Actor> oldActors = new HashSet<Actor>();
|
||||||
|
readonly HashSet<Actor> currentActors = new HashSet<Actor>();
|
||||||
|
|
||||||
WPos position;
|
WPos position;
|
||||||
WDist range;
|
WDist range;
|
||||||
WDist vRange;
|
WDist vRange;
|
||||||
|
|
||||||
IEnumerable<Actor> currentActors = Enumerable.Empty<Actor>();
|
|
||||||
|
|
||||||
public ProximityTrigger(WPos pos, WDist range, WDist vRange, Action<Actor> onActorEntered, Action<Actor> onActorExited)
|
public ProximityTrigger(WPos pos, WDist range, WDist vRange, Action<Actor> onActorEntered, Action<Actor> onActorExited)
|
||||||
{
|
{
|
||||||
this.onActorEntered = onActorEntered;
|
this.onActorEntered = onActorEntered;
|
||||||
@@ -128,22 +131,25 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (!Dirty)
|
if (!Dirty)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var oldActors = currentActors;
|
// PERF: Reuse collection to avoid allocations.
|
||||||
var delta = new WVec(range, range, WDist.Zero);
|
oldActors.Clear();
|
||||||
currentActors = am.ActorsInBox(position - delta, position + delta)
|
oldActors.UnionWith(currentActors);
|
||||||
.Where(a => (a.CenterPosition - position).HorizontalLengthSquared < range.LengthSquared
|
|
||||||
&& (vRange.Length == 0 || (a.World.Map.DistanceAboveTerrain(a.CenterPosition).LengthSquared <= vRange.LengthSquared)))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var entered = currentActors.Except(oldActors);
|
var delta = new WVec(range, range, WDist.Zero);
|
||||||
var exited = oldActors.Except(currentActors);
|
currentActors.Clear();
|
||||||
|
currentActors.UnionWith(
|
||||||
|
am.ActorsInBox(position - delta, position + delta)
|
||||||
|
.Where(a => (a.CenterPosition - position).HorizontalLengthSquared < range.LengthSquared
|
||||||
|
&& (vRange.Length == 0 || (a.World.Map.DistanceAboveTerrain(a.CenterPosition).LengthSquared <= vRange.LengthSquared))));
|
||||||
|
|
||||||
if (onActorEntered != null)
|
if (onActorEntered != null)
|
||||||
foreach (var a in entered)
|
foreach (var a in currentActors)
|
||||||
|
if (!oldActors.Contains(a))
|
||||||
onActorEntered(a);
|
onActorEntered(a);
|
||||||
|
|
||||||
if (onActorExited != null)
|
if (onActorExited != null)
|
||||||
foreach (var a in exited)
|
foreach (var a in oldActors)
|
||||||
|
if (!currentActors.Contains(a))
|
||||||
onActorExited(a);
|
onActorExited(a);
|
||||||
|
|
||||||
Dirty = false;
|
Dirty = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user