2015-07-01 4 views
1

У меня есть игра с 2D-прокруткой. Прямо сейчас, чтобы прыгать, игрок должен касаться земли. Поэтому у меня есть логический, isOnGround, который установлен в YES, когда игрок сталкивается с объектом плитки, и нет, когда игрок прыгает. Это генерирует много вызовов метода didBeginContact, замедляя игру.Оптимизация SKPhysicsBody

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

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

+0

Вы тестируете устройство прямо? –

ответ

1

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

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

Использование физики и столкновений, вероятно, самый простой способ определить состояние вашего игрока в отношении контакта с землей. Чтобы решить проблему с вашей стеной, вы просто делаете контакт стены другой категорией, чем ваша земля. Это предотвратит установку параметра isOnGround равным YES.

+0

> Чтобы решить проблему с вашей стеной, вы просто создаете контакт стены с другой категорией, чем ваша земля. Это предотвратит установку параметра isOnGround равным YES. Ну вот в чем проблема, плитки этой игры динамичны, а значит, игрок может подобрать и установить плитки. –

+0

@ThorCorreia Вам нужно будет определить, является ли плитка стенкой или полом в зависимости от того, где пользователь кладет плиту. –

+0

@ThorCorreia - Я не знаю вашей точной структуры кода, но было бы разумно установить битовую маску категории плитки на основе текущего обстоятельства. Например, сбор напольной плитки и размещение ее на стене изменит битовую маску от пола до стены. – sangony

1

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

Для лучшей производительности, только набор бит в контактах маски для взаимодействий вы заинтересованы в

Так что я нашел лучшее решение для моей игры (который имеет 25+. единичные единицы, которые все требуют обнаружения поверхности). Вместо того, чтобы проходить физический движок, я только что сделал свой собственный расчет поверхности и закрепил результат каждого обновления игры. Что-то вроде этого:

final class func getSurfaceID(nodePosition: CGPoint) -> SurfaceID { 
    //Loop through surface rects and see if position is inside. 
} 

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

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

Выполнение этого изменения уменьшило время процессора, затрачиваемое на обнаружение поверхности, с 20% до 0,1%. Это также позволяет мне проверять, лежит ли какая-либо произвольная точка на поверхности, а не создавать физическое тело (что лишние накладные расходы). Однако это решение, очевидно, не сработает для вас, если вам нужно использовать обнаружение контактов.

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

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

+0

Установив столкновение, как узел может находиться внутри другого? – sangony

+0

@sangony Извините, я не понимаю вопроса. –

+0

@sangony О, я думаю, я понимаю. Поверхностные рамки обозначают область, где разрешено прыгать. Поэтому он должен располагаться над узлом, а не поверх него. Вы можете думать о поверхностном фрейме как о «рисовании» поверхностей вашей игры, используя ряд прямоугольников. В моем случае я использую 3-точечные вращающиеся прямоугольники. Проверить, находится ли положение внутри одного из этих прямоугольников, намного быстрее, чем полагаться на обнаружение контактов комплекта спрайтов или использование свойства allContactedBodies. –

Смежные вопросы