Программирование игр и обработчики событий - PullRequest
12 голосов
/ 15 сентября 2008

Я не программировал игры около 10 лет (моим последним опытом был DJGPP + Allegro), но я решил проверить XNA на выходных, чтобы посмотреть, как он складывается.

Я впечатлен, однако, поскольку я продолжаю собирать игровой движок, у меня есть (вероятно) основной вопрос.

Сколько вы должны полагаться на делегатов и события C # для управления игрой? Как программист приложения, я интенсивно использую делегаты и события, но я не знаю, есть ли значительные издержки для этого.

В моем игровом движке я разработал «чейз-кулачок», который можно прикрепить к объекту, а затем пересчитать его положение относительно объекта. Когда объект движется, есть два способа обновить чейз-камеру.

  • Иметь метод UpdateCameras () в главном игровом цикле.
  • Используйте обработчик событий, и чейз-кам подписывается на object.OnMoved.

Я использую последнее, потому что оно позволяет мне связывать события вместе и красиво автоматизировать большие части двигателя. Внезапно, то, что было бы огромным и сложным, было разбросано до нескольких обработчиков событий из 3-5 строк ... Это прекрасно.

Однако, если обработчики событий, запускаемые каждую наносекунду, оказываются серьезным замедлением, я уберу их и продолжу циклический подход.

Идеи

Ответы [ 7 ]

10 голосов
/ 15 сентября 2008

Если вы думаете о событии как о списке подписчиков, в вашем коде все, что вы делаете, это регистрируете подписчика. Количество инструкций, необходимых для достижения этого, вероятно, будет минимальным на уровне CLR.

Если вы хотите, чтобы ваш код был универсальным или динамическим, вам необходимо проверить, подписано ли что-либо до вызова события. Механизм событий / делегатов C # и .NET предоставляет это вам при очень небольших затратах (с точки зрения ЦП).

Если вы действительно обеспокоены каждым тактом, вы никогда не будете писать общую / динамическую игровую логику. Это компромисс между поддерживаемым / настраиваемым кодом и полной скоростью.

Написано хорошо, я бы предпочел события / делегатов, пока не смогу доказать, что это проблема.

Единственный способ, которым вы по-настоящему узнаете, является ли это проблемой для вас, - это профилирование вашего кода - что вы должны делать в любом случае при разработке любой игры!

4 голосов
/ 15 сентября 2008

Важно понимать, что события в C # не являются асинхронными событиями в очереди (как, например, очередь сообщений Windows). По сути, это список указателей функций. Таким образом, создание события не имеет худших последствий для производительности, чем перебор списка указателей функций и вызов каждого из них.

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

2 голосов
/ 17 сентября 2008

Основной вопрос здесь, кажется, таков: «Какие издержки связаны с использованием делегатов и событий C #?»

События имеют незначительные накладные расходы по сравнению с обычным вызовом функции.

Использование Делегатов может создавать скрытый и, следовательно, скрытый мусор. Мусор может быть основной причиной проблем с производительностью, особенно на XBox360.

Следующий код генерирует около 2000 байт мусора в секунду (при 60 кадрах в секунду) в форме объектов EntityVisitor:

    private delegate void SpacialItemVisitor(ISpacialItem item);

    protected override void Update(GameTime gameTime)
    {
        m_quadTree.Visit(ref explosionCircle, ApplyExplosionEffects);
    }

    private void ApplyExplosionEffects(ISpacialItem item)
    {
    }

Пока вы избегаете генерации мусора, делегаты достаточно быстры для большинства целей. Из-за скрытых опасностей я предпочитаю избегать их и вместо этого использовать интерфейсы.

1 голос
/ 29 мая 2012

Прежде чем вдаваться в подробности влияния события на производительность, вы должны сначала оценить, действительно ли оно необходимо.

Предполагая, что вы действительно пытаетесь постоянно обновлять чейз-камеру, и это не просто пример, то, что вы ищете, не является событием (хотя события могут также помочь), если вы следите за вероятностью аватара. он будет двигаться большую часть времени.

Один из подходов, который я нашел чрезвычайно эффективным, заключается в использовании иерархических преобразований. Если вы реализуете это эффективно, камера не будет единственным объектом, получающим выгоду от такой системы, цель будет заключаться в том, чтобы держать камеру в координатном пространстве объект отслеживания.

Этот подход не самый лучший, если вы хотите применить некоторую эластичность к скорости и способам, которыми камера отслеживает объект, для этого лучше всего использовать вызов обновления, эталон и некоторое базовое ускорение и физика сопротивления.

События более полезны для вещей, которые происходят только время от времени или которые влияют на многие различные аспекты приложения, такие как смерть персонажа, вероятно, многие различные системы хотели бы знать о таком событии, убивать статистику, контролировать ИИ и т. Д., В таком случае, отслеживание всех объектов, которые должны будут постоянно проверять, произошло ли это, гораздо менее эффективно, чем создание события, и уведомление всех заинтересованных объектов только тогда, когда это происходит.

1 голос
/ 16 сентября 2008

Кроме того, вам может быть интересно узнать, что Шон Харгривз , оригинальный разработчик Allegro , является одним из основных разработчиков в команде XNA: -)

1 голос
/ 15 сентября 2008

В свободное от работы время я тоже изучаю XNA.

ИМХО (или не так скромно, если вы спросите моих коллег), что накладные расходы на обработчики событий будут перегружены другими элементами в игре, такими как рендеринг. Учитывая интенсивное использование событий в обычном программировании на .Net, я был бы базовым кодом, хорошо оптимизированным.

Если честно, я думаю, что использование метода UpdateCameras может быть преждевременной оптимизацией. Система событий, вероятно, имеет больше применений, кроме камеры.

1 голос
/ 15 сентября 2008

XNA поощряет использование интерфейсов, событий и делегатов для управления тем, что написано с ним. Посмотрите на классы, связанные с GameComponent, которые настроили это для вас.

Ответ таков: «Столько, сколько вам удобно».

Чтобы немного уточнить, если, например, вы берете и наследуете класс gamecomponent в класс cameracontroller и добавляете его в коллекцию Game.Component. Затем вы можете создать свои классы камеры и добавить их в свой контроллер камеры.

В результате этого будет регулярно вызываться контроллер камеры, и вы сможете выбрать и активировать подходящую камеру или несколько камер, если вы этого хотите.

Вот пример этого (все его уроки превосходны): ReoCode

...