Pergunta
Estou escrevendo um jogo XNA em C# usando a porta XNA de Box2D - Box2dx.
Entidades como árvores ou zumbis são representadas como objetos da GameObjects. GameObjectManager
Adiciona e remove -os do mundo do jogo:
/// <summary>
/// Does the work of removing the GameObject.
/// </summary>
/// <param name="controller">The GameObject to be removed.</param>
private void removeGameObjectFromWorld(GameObjectController controller)
{
controllers.Remove(controller);
worldState.Models.Remove(controller.Model);
controller.Model.Body.SetActive(false);
}
public void addGameObjectToWorld(GameObjectController controller)
{
controllers.Add(controller);
worldState.Models.Add(controller.Model);
controller.Model.Body.SetActive(true);
}
controllers
é uma coleção de GameObjectController
instâncias.
worldState.Models
é uma coleção de GameObjectModel
instâncias.
Quando eu removo o GameObjects de Box2D dessa maneira, esse método é chamado:
void IContactListener.EndContact(Contact contact)
{
GameObjectController collider1 = worldQueryUtils.gameObjectOfBody(contact.GetFixtureA().GetBody());
GameObjectController collider2 = worldQueryUtils.gameObjectOfBody(contact.GetFixtureB().GetBody());
collisionRecorder.removeCollision(collider1, collider2);
}
WorldQueryutils:
// this could be cached if we know bodies never change
public GameObjectController gameObjectOfBody(Body body)
{
return worldQueryEngine.GameObjectsForPredicate(x => x.Model.Body == body).Single();
}
Este método lança um erro:
System.InvalidOperationException was unhandled
Message="Sequence contains no elements"
Source="System.Core"
StackTrace:
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
at etc
Por que isso está acontecendo? O que posso fazer para evitar isso? Este método foi chamado muitas vezes antes do body.SetActive()
foi chamado. Eu sinto que isso pode estar bagunçando.
Solução
Algumas coisas. O erro é realmente proveniente do método único, porque assume que haverá pelo menos um item na sequência. Se você deseja um comportamento mais tolerante, use o SingleDefault, que retornará o valor padrão desse tipo (se for uma classe, NULL).
Segundo, o objeto "corporal" ... pode ter o método Equals substituído; nesse caso, você pode obter resultados ímpares ao fazer "==". Se você está literalmente procurando a mesma instância (e é uma classe), você pode usar o object.ReferenceEquals
método.
Terceiro, você deve repensar seu design. Sempre que você precisar percorrer uma coleção para procurar um determinado item (que é o método. Onde o. Você tem a oportunidade de usar um algoritmo melhor