(Monogame)更新方法导致极度滞后

(Monogame) Update method causes extreme lag

我目前正在用单人游戏制作 2d 平台游戏。 我创建了一个块,当被玩家击中时,它开始消失。当它消失时,我在它周围画了一个矩形。每个相同类型的 Tile (BrittleTile) 也开始消失,直到整个连接的 BrittleTiles 生物消失。

问题是对于每个被销毁的 BrittleTile,我的游戏运行速度明显变慢,直到在 10 个左右的 BrittleTiles 被销毁后它变成幻灯片。我不知道是什么原因造成的,我一直在尝试简化 class 的更新方法,但似乎无济于事。

知道是什么原因造成的吗?

    class BrittleTile: Tile, IIncludeSound 
{
    public Rectangle DestroyedCheckRectangle;
    private BrittleTile brittle;
    private bool _isPlayed;
    private bool _hasBroken;
    private SoundEffect _sfxBreak;
    private SoundEffectInstance _sfxiBreak;
    private TimeSpan _breakTimer = new TimeSpan();
    public Rectangle BrokenViewRectangle { get; set; }
    private bool _isBreaking = false;
    public BrittleTile(Texture2D texture, Rectangle baseViewRectangle, Rectangle brokenViewRectangle):base(texture, baseViewRectangle, true )
    {
        this.BrokenViewRectangle = brokenViewRectangle;
        this.ViewRectangle = baseViewRectangle;
    }

    public void Update(GameTime gameTime, Hero hero, Entity[,] grid)
    {
        if (!this._hasBroken)
        {
            if (!this._isBreaking && !this._hasBroken && this.hasCollision)
                _checkCollision(hero, grid);
            if (this._isBreaking)
            {
                if (!this._isPlayed)
                    _sfxiBreak.Play();
                this._isPlayed = true;
                this._breakTimer += gameTime.ElapsedGameTime;
                if (this._breakTimer.TotalMilliseconds < 250)
                    this.GhostMode(gameTime);
                else
                {
                    this._isBreaking = false;
                    this.hasCollision = false;
                    this._breakTimer -= this._breakTimer;
                }
            }
            else
            {
                if (!this.hasCollision && this.DestroyedCheckRectangle.Width == 0)
                {
                    this.DestroyedCheckRectangle.X = this.DestinationRectangle.X - 10;
                    this.DestroyedCheckRectangle.Y = this.DestinationRectangle.Y - 10;
                    this.DestroyedCheckRectangle.Height = this.DestinationRectangle.Height + 20;
                    this.DestroyedCheckRectangle.Width = this.DestinationRectangle.Width + 20;
                    this._hasBroken = true;
                }
            }
        }
    }
    public override void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(this.Texture, this.DestinationRectangle, this.BrokenViewRectangle, Color.White);
        if (this.hasCollision)
            spriteBatch.Draw(this.Texture, this.DestinationRectangle, this.ViewRectangle, Color.White * this.GhostDraw * 0.9f);
        spriteBatch.Draw(this.Texture, DestroyedCheckRectangle, new Rectangle(1, 1, 1, 1), Color.Yellow);
        Console.WriteLine(this.DestroyedCheckRectangle.X + ", " + this.DestroyedCheckRectangle.Y + ", " + this.DestroyedCheckRectangle.Width + ", " + this.DestroyedCheckRectangle.Height);
    }
    private void _checkCollision(Hero hero, Entity[,] grid)
    {
        if (this.DestinationRectangle.Intersects(hero.AttackHitBox))
        {
            this._isBreaking = true;
        }
        foreach (Shuriken star in hero.Stars)
        {
            if (this.DestinationRectangle.Intersects(star.DestinationRectangle))
                this._isBreaking = true;
        }
        foreach (Entity entityObject in grid)
        {
            if (hasCollision && entityObject.GetType() == typeof(BrittleTile)){
                brittle = entityObject.DeepCopy() as BrittleTile;
                if (this.DestinationRectangle.Intersects(brittle.DestroyedCheckRectangle))
                    this._isBreaking = true;
            }
        }
    }
    override public void LoadSounds(ContentManager content)
    {
        this._sfxBreak = content.Load<SoundEffect>("SFX/brittleBreak");
        _sfxiBreak = _sfxBreak.CreateInstance();
        _sfxiBreak.Volume = 0.2f;
    }
}

首先,这一行:

if (!this._isBreaking && !this._hasBroken && this.hasCollision)

!this._hasBroken 是多余的。

我的第一个警告标志是这一行:

brittle = entityObject.DeepCopy() as BrittleTile;

我假设 DeepCopy() 创建了对象的新版本,并复制了它的所有属性,对吗?查看其中的代码可能有助于确定它,但基于该假设...

对于每个 Tile,您循环遍历网格中的每个对象,并且完全复制该对象作为 BrittleTile,为什么?

我的第一个更改是修改 foreach 以将其包含在其中:

var brittle = entityObject as BrittleTile
if (brittle != null && hasCollision){
    if (this.DestinationRectangle.Intersects(brittle.DestroyedCheckRectangle))
        this._isBreaking = true;
    }
}

不确定这是速度变慢的主要原因,但这绝对是一个问题。如果您正在克隆一个对象然后立即丢弃一个对象,那么您几乎可以肯定做错了什么。如果您正在克隆一个对象而您根本没有编辑该副本的属性(并使用这些编辑),那么您肯定做错了什么。在使用这样的方法之前我会很小心,除非你真的确定那是你想要的。