C# 继承未按预期工作

C# 继承未按预期工作,c#,class,inheritance,typeof,C#,Class,Inheritance,Typeof,类敌人和矿石是实体类的孩子。类小行星是敌人的后代。当我的飞船碰到任何实体时,下面的代码被触发 两句话中的代码是:当船接触到矿石时,将矿石添加到船的库存中,并将矿石从屏幕上移除。当船碰到敌人时,检查它是什么敌人。如果是小行星,将飞船推回,降低其生命值并删除该小行星 if (entities[j] is Ore) { pilots[i].Ship.InventoryAdd(entities[j]); entities.RemoveAt(j--); } if (entities[j] is Enem

敌人
矿石
实体
类的孩子。类
小行星
敌人
的后代。当我的飞船碰到任何实体时,下面的代码被触发

两句话中的代码是:当船接触到矿石时,将矿石添加到船的库存中,并将矿石从屏幕上移除。当船碰到敌人时,检查它是什么敌人。如果是小行星,将飞船推回,降低其生命值并删除该小行星

if (entities[j] is Ore)
{ pilots[i].Ship.InventoryAdd(entities[j]); entities.RemoveAt(j--); }

if (entities[j] is Enemy)
{
    if(entities[j] is Asteroid)
    {
        pilots[i].Ship.AddForce(entities[j].Force * (entities[j] as Enemy).Damage);
        pilots[i].Ship.HP -= (entities[j] as Enemy).Damage;
        entities.RemoveAt(j);
    }
}
注意我看到在一个更新或帧中,两次碰撞都在发生(飞船与小行星和飞船与矿石)时可能会触发的问题,我会解决这个问题。此外,这是整个代码,而不仅仅是所有案例的一部分。现在,我的屏幕上只有矿石和小行星(还有一艘船)

船舶和矿石碰撞的问题正在发生。我的船被推回了。但我只在飞船对小行星的比赛中这么做。这意味着该计划将矿石视为小行星,而事实并非如此。这些东西我都检查了好几次。是的,它们都有相同的父代,但如果我问一个实例是否是小行星,他怎么能说“是的,而且也是矿石”,而事实并非如此

我知道,如果我问一个小行星的例子,如果它是类实体,敌人和小行星,我总是会得到一个答案“是”,但矿石怎么可能是小行星呢


问题是:这背后的逻辑是什么?我如何正确地检查这一点?另外请注意,用于增加力量的线将向所有敌人开火,而不仅仅是小行星,目前的情况就是如此。

您正在处理
实体
阵列中的两个不同元素。因为从数组中删除了条目,所以第二个
if
在不同的元素上工作

如果

if (entities[j] is Ore)
{ 
  pilots[i].Ship.InventoryAdd(entities[j]); entities.RemoveAt(j--); 
}
else if (entities[j] is Enemy)
{
    if(entities[j] is Asteroid)
    {
        pilots[i].Ship.AddForce(entities[j].Force * (entities[j] as Enemy).Damage);
        pilots[i].Ship.HP -= (entities[j] as Enemy).Damage;
        entities.RemoveAt(j);
    }
}

删除索引“j”处的对象,然后重新检查实体[j]。因此,如果8处有矿石,9处有星象,则移除矿石,将星象放在第二个if之前的8处。

您可能需要将第二个if更改为else if。现在发生的情况是,如果你的飞船与矿石发生碰撞,它会将矿石添加到库存中(如预期的那样),然后将实体数组中的索引减少1

在减少之后,您检查当前索引中的实体是否是敌人,因此您基本上看到的是与以前完全不同的实体

将第二个检查更改为

else if (entities[j] is Enemy)
应该防止这种情况

希望这有帮助


弗劳克

好吧,假设您遇到这种情况:

j=8是您正在碰撞的矿石
j=7是一个你没有碰撞到的星号

因为你做了j——在处理一个矿石之后,实体[j]现在将指向一个星号,即使没有与星号发生碰撞。然后HP被减去,等等

您没有继承问题,您有一个“在循环期间弄乱循环变量”的问题

你可以这样做:

if (entities[j] is Ore)
{ 
    pilots[i].Ship.InventoryAdd(entities[j]); 
    entityIndexesToRemove.add(j);
}

if (entities[j] is Enemy)
{
    if(entities[j] is Asteroid)
    {
        pilots[i].Ship.AddForce(entities[j].Force * (entities[j] as Enemy).Damage);
        pilots[i].Ship.HP -= (entities[j] as Enemy).Damage;
        entityIndexesToRemove.add(j);
    }
}
// then rest of that loop on j ...

// then later when loop has finished we do removals....
for (int r=entitiesToRemove.Count; r>0;r--)
    entities.RemoveAt(entitiesToRemove[r]);

这是什么逻辑?逻辑只属于您:-)在
Ore
的情况下,您会更改
实体
,这样索引
j
很可能不会指向
Ore
更长的时间。您为什么会假设继承以某种方式被破坏?你试过调试代码吗?为什么您认为eg
entitiers.RemoveAt
将使
实体[j]
指向同一实例?如果您使用
is
关键字,在大多数情况下,您的代码都有设计问题。如果您在基类上定义一个
Collision
事件,并让每个类型都实现处理程序,那会好得多。@Monset而且正如大家所指出的,您有一个索引问题。这既不是最小的,也不是强制性的。它不会编译。但如果它真的出现了,它就不会出现问题,即使您是对的,并且存在继承错误,我们也无法复制它。PS我没有投反对票,但几乎其他人都投了。或者干脆避免到处使用
实体[j]
。只需将内容分配给一个临时变量即可。此操作非常有效。谢谢请看我写的大屁股便条wrote@Monset请阅读并理解这些评论和建议answers@MonsetMaarten是对的,你需要理解他在说什么检查我批准的答案,你就会看到它是如何在不改变我的方式的情况下解决我的问题的entities@Monset是的Nineberry的回答很好,但是你知道为什么它会起作用,以及最初的问题是什么吗?