Box2d: установить активный и неактивный - PullRequest
0 голосов
/ 07 апреля 2010

Я пишу игру XNA на C #, используя порт XNA Box2d - Box2dx.

Объекты, такие как деревья или зомби, представлены как объекты GameObject. GameObjectManager добавляет и удаляет их из игрового мира:

    /// <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 - это коллекция GameObjectController экземпляров.

worldState.Models представляет собой набор GameObjectModel экземпляров.

Когда я удаляю GameObjects из Box2d, этот метод вызывается:

       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();
    }

Этот метод выдает ошибку:

System.InvalidOperationException was unhandled
  Message="Sequence contains no elements"
  Source="System.Core"
  StackTrace:
       at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
       at etc

Почему это происходит? Что я могу сделать, чтобы избежать этого? Этот метод вызывался много раз, прежде чем был вызван body.SetActive(). Я чувствую, что это может все испортить.

1 Ответ

1 голос
/ 09 апреля 2010

Несколько вещей. Ошибка на самом деле исходит из метода Single, поскольку предполагается, что в последовательности будет хотя бы один элемент. Если вы хотите более терпимого поведения, используйте SingleOrDefault, который будет возвращать значение по умолчанию для этого типа (если это класс, null).

Во-вторых, объект "Body" ... может иметь переопределенный метод equals, и в этом случае вы можете получить странные результаты при выполнении "==". Если вы буквально ищете один и тот же экземпляр (и это класс), вы можете использовать метод object.ReferenceEquals.

В-третьих, вы должны переосмыслить свой дизайн. Каждый раз, когда вам нужно пройтись по коллекции, чтобы найти заданный элемент (и это все, что делает метод .Where), у вас есть возможность использовать лучший алгоритм

...