我有一个 Minion 对象的 ArrayList,当盾牌与 Minion 碰撞时,我想从 ArrayList 中删除该 Minion。但是,我只能让它以一种方式工作,而不能以另一种方式工作。谁能解释一下为什么?
在所有 3 种情况下,我都使用 Android 的 Renderer 的 onDrawFrame() 方法......所以我无法控制它何时被调用。但这是所有 3 种方式的代码:
方法一:(无效)
public void onDrawFrame(GL10 gl) {
List<Integer> indexesToRemove = new ArrayList<Integer>();
int len = minions.size();
for(int i=0; i<len; i++){
if( OverlapTester.overlapCircleRectangle( (Circle)shield1.bounds, (Rectangle)minions.get(i).bounds) ){ //this tests out to work just fine
indexesToRemove.add(i);
}
}
for(int i=indexesToRemove.size()-1; i>=0; i--){
minions.remove(indexesToRemove.get(i)); //<------ why doesn't this work?
}
}
问题是最后一行minions.remove(indexesToRemove.get(i));
实际上并没有删除奴才。它确实被调用,具有适当的索引。我已经通过调试器,直接运行它,并且 arraylist 根本没有修改。为什么是这样?实际上,在调试器中,该行“minions.remove(indexesToRemove.get(i));” 被称为数十亿次。
方法二:(还是不行)
public void onDrawFrame(GL10 gl) {
synchronized(minions){
List<Integer> indexesToRemove = new ArrayList<Integer>();
int len = minions.size();
for(int i=0; i<len; i++){
if( OverlapTester.overlapCircleRectangle( (Circle)shield1.bounds, (Rectangle)minions.get(i).bounds) ){ //this tests out to work just fine
indexesToRemove.add(i);
}
}
for(int i=indexesToRemove.size()-1; i>=0; i--){
minions.remove(indexesToRemove.get(i)); //<------ why doesn't this work?
}
}
}
在这里,我想......“哦,也许因为它不完全同步,drawFrame有时被调用太多次并且在错误的时间访问arraylist,我需要锁定它。但它仍然不起作用。再次,该行minions.remove(indexesToRemove.get(i));
被正确的索引正确调用,但实际上并没有删除对象.我正在看着我的盾牌在屏幕上猛烈撞击奴才,奴才没有任何反应(它没有从数组列表中删除)
方法#3(这确实有效)
public void onDrawFrame(GL10 gl) {
ArrayList<Minion> colliders = new ArrayList<Minion>(minions);
int len = colliders.size();
for(int i=0; i<len; i++){
GameObject collider = colliders.get(i);
if(OverlapTester.overlapCircleRectangle((Circle)shield1.bounds, (Rectangle)collider.bounds)){
minions.remove(collider); // <---- why does THIS work instead?
}
}
}
此代码完美运行。盾牌击打仆从,仆从倒地死亡。正如您在此处看到的,唯一的区别是我使用的是重载ArrayList.remove(object)
方法而不是按索引删除。如行中minions.remove(collider);
。为什么这行得通?
谁能解释一下?
附带说明一下,除了存储arraylist的另一个实例变量副本之外,还有更好的管理方法ArrayList<Minion> colliders = new ArrayList<Minion>(minions);
吗?
注意:Shield 和 Minion 都是以矩形为边界的常规 Java 对象。所有这些数学检查都很好。我已经在调试器中对其进行了测试,并且碰撞检测是准确的。我也在更新onDrawFrame()
方法中准确的边界/位置。