Improve performance of FrozenActorLayer.Tick
By adding a UpdateVisibilityNextTick flag against every FrozenActor to track when a visibility update is required, we can remove the dirtyFrozenActorIds set in FrozenActorLayer. In the Tick method we can now avoid a set lookup. Also, don't create the frozenActorsToRemove list until we need one to avoid an allocation.
This commit is contained in:
@@ -69,6 +69,7 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
public bool Shrouded { get; private set; }
|
public bool Shrouded { get; private set; }
|
||||||
public bool NeedRenderables { get; set; }
|
public bool NeedRenderables { get; set; }
|
||||||
|
public bool UpdateVisibilityNextTick { get; set; }
|
||||||
public IRenderable[] Renderables = NoRenderables;
|
public IRenderable[] Renderables = NoRenderables;
|
||||||
public Rectangle[] ScreenBounds = NoBounds;
|
public Rectangle[] ScreenBounds = NoBounds;
|
||||||
|
|
||||||
@@ -154,10 +155,15 @@ namespace OpenRA.Traits
|
|||||||
{
|
{
|
||||||
if (flashTicks > 0)
|
if (flashTicks > 0)
|
||||||
flashTicks--;
|
flashTicks--;
|
||||||
|
|
||||||
|
if (UpdateVisibilityNextTick)
|
||||||
|
UpdateVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateVisibility()
|
void UpdateVisibility()
|
||||||
{
|
{
|
||||||
|
UpdateVisibilityNextTick = false;
|
||||||
|
|
||||||
var wasVisible = Visible;
|
var wasVisible = Visible;
|
||||||
Shrouded = true;
|
Shrouded = true;
|
||||||
Visible = true;
|
Visible = true;
|
||||||
@@ -248,8 +254,7 @@ namespace OpenRA.Traits
|
|||||||
readonly World world;
|
readonly World world;
|
||||||
readonly Player owner;
|
readonly Player owner;
|
||||||
readonly Dictionary<uint, FrozenActor> frozenActorsById;
|
readonly Dictionary<uint, FrozenActor> frozenActorsById;
|
||||||
readonly SpatiallyPartitioned<uint> partitionedFrozenActorIds;
|
readonly SpatiallyPartitioned<FrozenActor> partitionedFrozenActors;
|
||||||
readonly HashSet<uint> dirtyFrozenActorIds = new();
|
|
||||||
|
|
||||||
public FrozenActorLayer(Actor self, FrozenActorLayerInfo info)
|
public FrozenActorLayer(Actor self, FrozenActorLayerInfo info)
|
||||||
{
|
{
|
||||||
@@ -258,22 +263,26 @@ namespace OpenRA.Traits
|
|||||||
owner = self.Owner;
|
owner = self.Owner;
|
||||||
frozenActorsById = new Dictionary<uint, FrozenActor>();
|
frozenActorsById = new Dictionary<uint, FrozenActor>();
|
||||||
|
|
||||||
partitionedFrozenActorIds = new SpatiallyPartitioned<uint>(
|
partitionedFrozenActors = new SpatiallyPartitioned<FrozenActor>(
|
||||||
world.Map.MapSize.X, world.Map.MapSize.Y, binSize);
|
world.Map.MapSize.X, world.Map.MapSize.Y, binSize);
|
||||||
|
|
||||||
self.Trait<Shroud>().OnShroudChanged += uv => dirtyFrozenActorIds.UnionWith(partitionedFrozenActorIds.At(new int2(uv.U, uv.V)));
|
self.Trait<Shroud>().OnShroudChanged += uv =>
|
||||||
|
{
|
||||||
|
foreach (var fa in partitionedFrozenActors.At(new int2(uv.U, uv.V)))
|
||||||
|
fa.UpdateVisibilityNextTick = true;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(FrozenActor fa)
|
public void Add(FrozenActor fa)
|
||||||
{
|
{
|
||||||
frozenActorsById.Add(fa.ID, fa);
|
frozenActorsById.Add(fa.ID, fa);
|
||||||
world.ScreenMap.AddOrUpdate(owner, fa);
|
world.ScreenMap.AddOrUpdate(owner, fa);
|
||||||
partitionedFrozenActorIds.Add(fa.ID, FootprintBounds(fa));
|
partitionedFrozenActors.Add(fa, FootprintBounds(fa));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Remove(FrozenActor fa)
|
public void Remove(FrozenActor fa)
|
||||||
{
|
{
|
||||||
partitionedFrozenActorIds.Remove(fa.ID);
|
partitionedFrozenActors.Remove(fa);
|
||||||
world.ScreenMap.Remove(owner, fa);
|
world.ScreenMap.Remove(owner, fa);
|
||||||
frozenActorsById.Remove(fa.ID);
|
frozenActorsById.Remove(fa.ID);
|
||||||
}
|
}
|
||||||
@@ -303,7 +312,7 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
void ITick.Tick(Actor self)
|
void ITick.Tick(Actor self)
|
||||||
{
|
{
|
||||||
var frozenActorsToRemove = new List<FrozenActor>();
|
List<FrozenActor> frozenActorsToRemove = null;
|
||||||
VisibilityHash = 0;
|
VisibilityHash = 0;
|
||||||
FrozenHash = 0;
|
FrozenHash = 0;
|
||||||
|
|
||||||
@@ -315,19 +324,19 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
var frozenActor = kvp.Value;
|
var frozenActor = kvp.Value;
|
||||||
frozenActor.Tick();
|
frozenActor.Tick();
|
||||||
if (dirtyFrozenActorIds.Contains(id))
|
|
||||||
frozenActor.UpdateVisibility();
|
|
||||||
|
|
||||||
if (frozenActor.Visible)
|
if (frozenActor.Visible)
|
||||||
VisibilityHash += hash;
|
VisibilityHash += hash;
|
||||||
else if (frozenActor.Actor == null)
|
else if (frozenActor.Actor == null)
|
||||||
|
{
|
||||||
|
frozenActorsToRemove ??= new List<FrozenActor>();
|
||||||
frozenActorsToRemove.Add(frozenActor);
|
frozenActorsToRemove.Add(frozenActor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dirtyFrozenActorIds.Clear();
|
if (frozenActorsToRemove != null)
|
||||||
|
foreach (var fa in frozenActorsToRemove)
|
||||||
foreach (var fa in frozenActorsToRemove)
|
Remove(fa);
|
||||||
Remove(fa);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual IEnumerable<IRenderable> Render(Actor self, WorldRenderer wr)
|
public virtual IEnumerable<IRenderable> Render(Actor self, WorldRenderer wr)
|
||||||
@@ -355,8 +364,7 @@ namespace OpenRA.Traits
|
|||||||
{
|
{
|
||||||
var tl = region.TopLeft;
|
var tl = region.TopLeft;
|
||||||
var br = region.BottomRight;
|
var br = region.BottomRight;
|
||||||
return partitionedFrozenActorIds.InBox(Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y))
|
return partitionedFrozenActors.InBox(Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y))
|
||||||
.Select(FromID)
|
|
||||||
.Where(fa => fa.IsValid && (!onlyVisible || fa.Visible));
|
.Where(fa => fa.IsValid && (!onlyVisible || fa.Visible));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,8 +376,7 @@ namespace OpenRA.Traits
|
|||||||
var br = centerCell + new CVec(cellRange, cellRange);
|
var br = centerCell + new CVec(cellRange, cellRange);
|
||||||
|
|
||||||
// Target ranges are calculated in 2D, so ignore height differences
|
// Target ranges are calculated in 2D, so ignore height differences
|
||||||
return partitionedFrozenActorIds.InBox(Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y))
|
return partitionedFrozenActors.InBox(Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y))
|
||||||
.Select(FromID)
|
|
||||||
.Where(fa => fa.IsValid &&
|
.Where(fa => fa.IsValid &&
|
||||||
(!onlyVisible || fa.Visible) &&
|
(!onlyVisible || fa.Visible) &&
|
||||||
(fa.CenterPosition - origin).HorizontalLengthSquared <= r.LengthSquared);
|
(fa.CenterPosition - origin).HorizontalLengthSquared <= r.LengthSquared);
|
||||||
|
|||||||
Reference in New Issue
Block a user