xbox性能陷阱

问题描述

| 背景:我有一款游戏一直在(低规格)笔记本电脑上进行过测试。运行正常。在xbox上进行测试时,有一种方法在被调用时似乎会严重影响性能/ fps。在PC上,您不会注意到任何速度下降/跳帧。 我在xbox上进行了分析,平均而言,我每秒获得大约1-2次GC,在游戏运行时需要20-40ms。 运行慢速方法时,我注意到GC速率或持续时间没有变化。 接下来,我尝试在PC上进行性能分析,以确定该方法花费最多的时间。原来它在做
List<T>.Contains()
,所以我创建了自己的类,内部有
List<T>
HashSet<T>
,所以我可以在内部将
HashSet<T>
用作
Contains()
。 我现在已经到了要点,在不更改算法的情况下我真的无法想到还有什么要调整的,而且我认为该算法非常简单。 我知道我无法在xbox上进行配置以获取方法时间/百分比,所以我对下一步尝试感到有些困惑。 我已经包含了下面的代码,该代码用于在基于图块的系统中模拟流水。它在每个水瓦片上运行一次,试图通过其他水瓦片向下移动(通常来说)。 问题:我想知道我是否在这里做任何明显错误的事情(即会严重影响xbox的性能)。打电话给5英镑很慢吗?我可以用
Point
物品在任何地方拳击吗?等等 适用于大量代码的应用程序!切片本身来自对象池,以最大程度地减少GC。导致所有问题的原因是“ 7”方法。
public abstract class TileFlowing : TileMovable
{
    private FastList<Point> TeleportSwapLocations = new FastList<Point>();

    private FastList<Point> PossibleMoveLocations = new FastList<Point>();

    private FastQueue<Point> PositionsToCheck = new FastQueue<Point>();

    private FastList<Point> PositionsChecked = new FastList<Point>();

    private static Comparison<Point> _PossibleMoveComparer;

    public bool Static = false;

    protected abstract Func<Point,int> PossibleMoveLocationOrdering { get; }

    protected abstract Func<Point,Point,bool,bool> MoveSidewaysFunc { get; }

    protected abstract int MaxUnitsWithin { get; }

    protected abstract int Weight { get; }

    public int UnitsWithin;

    public int AvailableToFlowThrough = 0;

    protected virtual bool RecurseTilesUp { get { return true; } }
    protected virtual bool RecurseTilesDown { get { return true; } }
    protected virtual bool RecurseTilesLeft { get { return true; } }
    protected virtual bool RecurseTilesRight { get { return true; } }

    public TileFlowing()
        : base()
    {

    }

    public override void LoadContent(Components.TileGridManagement.GameGrid Owner)
    {
        base.LoadContent(Owner);

        _PossibleMoveComparer = (Point P1,Point P2) =>
        {
            int Result = PossibleMoveLocationOrdering(P1) -
                            PossibleMoveLocationOrdering(P2);
            if (Result == 0)
                Result = (IsSameType(P1) ? (_Owner[P1] as TileFlowing).UnitsWithin : 0) -
                            (IsSameType(P2) ? (_Owner[P2] as TileFlowing).UnitsWithin : 0);

            return Result;
        };
    }

    public override void ResetProperties()
    {
        base.ResetProperties();

        Static = false;
        UnitsWithin = MaxUnitsWithin;
        AvailableToFlowThrough = 0;
    }

    public override void CopyProperties(Tile SourceTile)
    {
        base.CopyProperties(SourceTile);

        Static = (SourceTile as TileFlowing).Static;
        UnitsWithin = (SourceTile as TileFlowing).UnitsWithin;
        AvailableToFlowThrough = (SourceTile as TileFlowing).AvailableToFlowThrough;
    }

    public override void Think()
    {
        base.Think();

        InternalThink(false,false);
    }

    public override void FactoryThink()
    {
        base.FactoryThink();

        InternalThink(true,false);
    }

    public void FlowThink(bool CalledFromFactoryThink)
    {
        InternalThink(CalledFromFactoryThink,true);
    }

    private bool IsSameType(Point Position)
    {
        return IsSameType(Position.X,Position.Y);
    }

    private bool IsSameType(int X,int Y)
    {
        return _Owner[X,Y] != null && _Owner[X,Y].GetType() == GetType();
    }

    private bool IsDifferentFlowingTile(Point Position)
    {
        return IsDifferentFlowingTile(Position.X,Position.Y);
    }

    private bool IsDifferentFlowingTile(int X,int Y)
    {
        return !IsSameType(X,Y) && _Owner[X,Y] is TileFlowing;
    }

    protected void CheckPosition(Point PositionToCheck,Point TilePosition,bool CalledFromFactoryThink,bool CalledFromFlowThink,ref FastList<Point> PossibleMoveLocations,ref FastList<Point> TeleportSwapLocations,ref FastQueue<Point> PositionsToCheck,Func<Point,bool> ClearCheckFunc)
    {
        if (IsSameType(PositionToCheck))
        {
            if (!PositionsToCheck.Contains(PositionToCheck))
                PositionsToCheck.Enqueue(PositionToCheck);
        }
        else if (_Owner[PositionToCheck] is TileFlowing && (ClearCheckFunc == null || ClearCheckFunc(PositionToCheck,TilePosition,CalledFromFactoryThink)))
        {
            // If we weigh more than the other tile,or we\'re called from the factory think (are under pressure)
            if ((_Owner[PositionToCheck] as TileFlowing).Weight < Weight || CalledFromFactoryThink)
            {
                if (!(_Owner[PositionToCheck] as TileFlowing).Static || !CalledFromFlowThink)
                    PossibleMoveLocations.Add(PositionToCheck);
            }
        }
        else if (_Owner.IsClear(PositionToCheck) && (ClearCheckFunc == null || ClearCheckFunc(PositionToCheck,CalledFromFactoryThink)))
        {
            PossibleMoveLocations.Add(PositionToCheck);
        }
    }

    private int PossibleMoveLocationsComparer(Point P1,Point P2)
    {
        return (PossibleMoveLocationOrdering(P1) - PossibleMoveLocationOrdering(P2)) * 1000 +
               ((IsSameType(P1) ? (_Owner[P1] as TileFlowing).UnitsWithin : 0) - (IsSameType(P2) ? (_Owner[P2] as TileFlowing).UnitsWithin : 0)) * 100;
    }

    protected void InternalThink(bool CalledFromFactoryThink,bool CalledFromFlowThink)
    {
        AvailableToFlowThrough = 0;

        TeleportSwapLocations.Clear();

        PossibleMoveLocations.Clear();

        PositionsToCheck.Clear();

        PositionsChecked.Clear();

        PositionsToCheck.Enqueue(Position);

        while (PositionsToCheck.Count != 0)
        {
            Point PositionToCheck = PositionsToCheck.Dequeue();

            if (!PositionsChecked.Contains(PositionToCheck) &&
                ((_Owner[PositionToCheck] as TileFlowing).AvailableToFlowThrough < MaxUnitsWithin || CalledFromFactoryThink))
            {
                if (((_Owner[PositionToCheck] as TileFlowing).Static && !CalledFromFactoryThink))
                    continue;

                if (PositionToCheck != Position)
                {
                    (_Owner[PositionToCheck] as TileFlowing).AvailableToFlowThrough++;
                }

                PositionsChecked.Add(PositionToCheck);

                if ((_Owner[PositionToCheck] as TileFlowing).UnitsWithin < MaxUnitsWithin && PositionToCheck != Position)
                {
                    PossibleMoveLocations.Add(PositionToCheck);

                    if (CalledFromFactoryThink && (_Owner[PositionToCheck] as TileFlowing).UnitsWithin + UnitsWithin <= MaxUnitsWithin)
                        continue;
                }

                // Check below
                Point PosBelow = new Point(PositionToCheck.X + TileDirection.Down.X,PositionToCheck.Y + TileDirection.Down.Y);

                CheckPosition(PosBelow,Position,CalledFromFactoryThink,CalledFromFlowThink,ref PossibleMoveLocations,ref TeleportSwapLocations,ref PositionsToCheck,null);

                // Check one horizontal direction
                Point RandHDir = Randomiser.GetHDirection();

                Point RandHPos = new Point(RandHDir.X + PositionToCheck.X,RandHDir.Y + PositionToCheck.Y);

                CheckPosition(RandHPos,MoveSidewaysFunc);

                // Check the other horizontal direction
                Point OtherHDir = new Point(-RandHDir.X,RandHDir.Y);

                Point OtherHPos = new Point(OtherHDir.X + PositionToCheck.X,OtherHDir.Y + PositionToCheck.Y);

                CheckPosition(OtherHPos,MoveSidewaysFunc);

                // Check above if appropriate
                Point AbovePos = new Point(PositionToCheck.X + TileDirection.Up.X,PositionToCheck.Y + TileDirection.Up.Y);

                if (TileDirection.Below(AbovePos,Position) || CalledFromFactoryThink)
                {
                    CheckPosition(AbovePos,null);
                }
            }
        }

        PossibleMoveLocations.Sort(_PossibleMoveComparer);

        bool Moved = false;

        if (PossibleMoveLocations.Count != 0)
        {
            if (CalledFromFactoryThink)
            {
                while (UnitsWithin != 0 && PossibleMoveLocations.Count != 0)
                {
                    int OldUnitsWithin = UnitsWithin;

                    Moved = IterateTeleport(CalledFromFactoryThink,(P) => !IsDifferentFlowingTile(P),Moved);

                    if (UnitsWithin == OldUnitsWithin)
                    {
                        Moved = IterateTeleport(CalledFromFactoryThink,(P) => IsDifferentFlowingTile(P),Moved);
                    }

                    PossibleMoveLocations.RemoveAll(P => IsSameType(P) && (_Owner[P] as TileFlowing).UnitsWithin == MaxUnitsWithin);
                }
            }
            else
            {
                Moved = Moved || Teleport(PossibleMoveLocations[0]);
            }

            // If we did move and not because we were forced to then mark all mercury tiles above and left or right as not static.
            if (!CalledFromFactoryThink)
            {
                _Owner.RecurseTiles(Position,(P) => RecurseTilesUp && IsSameType(P.X + TileDirection.Up.X,P.Y + TileDirection.Up.Y),(P) => RecurseTilesDown && IsSameType(P.X + TileDirection.Down.X,P.Y + TileDirection.Down.Y),(P) => RecurseTilesLeft && IsSameType(P.X + TileDirection.Left.X,P.Y + TileDirection.Left.Y),(P) => RecurseTilesRight && IsSameType(P.X + TileDirection.Right.X,P.Y + TileDirection.Right.Y),(P) =>
                                    {
                                        if (IsSameType(P))
                                            (_Owner[P] as TileFlowing).Static = false;
                                    });
            }
        }
        else
        {
            // Mark this tile as static if we didn\'t move,no water moved through this tile and we have all the units we can take.
            Static = (AvailableToFlowThrough == 0) && (UnitsWithin == MaxUnitsWithin); // TODO: 9 Fix flowing tiles becoming static and getting stuck
        }

        if (!Moved)
        {
            // If we haven\'t moved
            if (TeleportSwapLocations.Count != 0)
            {
                Moved = TeleportSwap(TeleportSwapLocations[0]);
            }

            if(!Moved)
            {
                // If we didn\'t move,undo checked tiles
                foreach (var CheckedPosition in PositionsChecked)
                {
                    (_Owner[CheckedPosition] as TileFlowing).AvailableToFlowThrough--;
                }
            }
        }
    }

    private bool IterateTeleport(bool CalledFromFactoryThink,ref FastList<Point> SortedPossibleMoveLocations,bool> PossibleMoveLocationsFilter,bool Moved)
    {
        foreach (var PossibleMoveLocation in SortedPossibleMoveLocations)
        {
            if (PossibleMoveLocationsFilter(PossibleMoveLocation))
            {
                if (IsDifferentFlowingTile(PossibleMoveLocation))
                {
                    bool OldStatic = Static;

                    Static = true;
                    (_Owner[PossibleMoveLocation] as TileFlowing).FlowThink(CalledFromFactoryThink);
                    Static = OldStatic;
                }

                bool TeleportResult = Teleport(PossibleMoveLocation);
                Moved = Moved || TeleportResult;

                if (TeleportResult)
                    break;
            }
        }
        return Moved;
    }

    protected bool TeleportSwap(Point NewPosition)
    {
        TileFlowing OurNewTile = (TileFlowing)Tile.GetNewTileFromStore(this);
        OurNewTile.CopyProperties(this);
        OurNewTile.Position = NewPosition;

        TileFlowing ReplacedTile = (TileFlowing)Tile.GetNewTileFromStore(_Owner[NewPosition]);
        ReplacedTile.CopyProperties(_Owner[NewPosition]);
        ReplacedTile.Position = Position;

        _Owner.ClearTile(NewPosition);
        _Owner.AddTileToGrid(OurNewTile);

        _Owner.ClearTile(Position);
        _Owner.AddTileToGrid(ReplacedTile);

        UnitsWithin = 0;

        return true;
    }

    protected bool Teleport(Point NewPosition)
    {
        if (IsDifferentFlowingTile(NewPosition))
        {
            return TeleportSwap(NewPosition);
        }
        else
        {

            TileFlowing NewTile;

            bool RemovedAllUnits = false;

            int NewPositionUnits = IsSameType(NewPosition) ? (_Owner[NewPosition] as TileFlowing).UnitsWithin : 0;

            int UnitsToRemove = Math.Min(UnitsWithin,Math.Max(1,Math.Min(Math.Abs(UnitsWithin - NewPositionUnits) / 2,MaxUnitsWithin - NewPositionUnits)));

            UnitsWithin -= UnitsToRemove;

            if (IsSameType(NewPosition))
            {
                (_Owner[NewPosition] as TileFlowing).UnitsWithin += UnitsToRemove;
            }
            else
            {
                NewTile = (TileFlowing)Tile.GetNewTileFromStore(this);

                NewTile.Position = NewPosition;
                NewTile.UnitsWithin = UnitsToRemove;

                _Owner.AddTileToGrid(NewTile);
            }

            if (UnitsWithin == 0)
            {
                _Owner.ClearTile(Position);
                RemovedAllUnits = true;
            }

            return RemovedAllUnits;
        }
    }
}
    

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)