Что нужно знать об обнаружении столкновений в SceneKit:
- он основан на битовых масках, которые вместе образуют таблицу.
- контактный делегат — это то, как вы реагируете на коллизии.
Столкновение объектов
Например, вы можете изложить немного игрового дизайна на простом английском языке следующим образом:
Астероиды сталкиваются друг с другом (и образуют меньшие астероиды). Ракеты должны проходить друг сквозь друга, но уничтожать ракеты и астероиды. Ракеты не должны ничего делать с ракетами (только наоборот), но если одна подойдет слишком близко к другой или к астероиду, у вас будет серьезная проблема, и вы не полетите сегодня в космос.
Первый шаг к пониманию того, что с обнаружением столкновений состоит в том, чтобы систематизировать этот дизайн с точки зрения того, какие пары взаимодействуют. Это можно сделать с помощью таблицы:
| Missile | Rocket | Asteroid
--------------------------------------
Missile | No | Yes | Yes
Rocket | No | Yes | Yes
Asteroid | No | No | Yes
Затем вы можете превратить заголовки таблицы в набор констант категории для использования в вашем коде.
typedef NS_OPTIONS(NSUInteger, CollisionCategory) {
CollisionCategoryMissile = 1 << 0,
CollisionCategoryRocket = 1 << 1,
CollisionCategoryAsteroid = 1 << 2,
};
missile.physicsBody.categoryBitMask = CollisionCategoryMissile;
rocket.physicsBody.categoryBitMask = CollisionCategoryRocket;
asteroid.physicsBody.categoryBitMask = CollisionCategoryAsteroid;
Используйте побитовое ИЛИ для этих констант, чтобы создать collisionBitMask
значений, которые заполняют таблицу.
missile.physicsBody.collisionBitMask =
CollisionCategoryRocket | CollisionCategoryAsteroid;
rocket.physicsBody.collisionBitMask =
CollisionCategoryRocket | CollisionCategoryAsteroid;
asteroid.physicsBody.collisionBitMask = CollisionCategoryAsteroid;
Это все, что вам нужно, чтобы SceneKit разрешал за вас коллизии (то есть отбрасывал объекты друг от друга).
Реакция на столкновения
Если вы также хотите получать уведомления о столкновениях (чтобы ракеты взрывались, а столкновение корабля с астероидом заканчивало игру), вам нужно установить свяжитесь с делегатом в физическом мире вашей сцены и внедрите один или несколько из методы делегата контакта, которые вызываются, когда происходит контакт.
В вашем методе делегирования контакта (скажем, physicsWorld:didBeginContact:
), вам нужно выяснить, какие категории тел участвовали в контакте и какие именно, чтобы вы могли добраться до своего кода, который делает то, что вам нужно. игра делает для столкновения:
- (void)physicsWorld:(SCNPhysicsWorld *)world didBeginContact:(SCNPhysicsContact *)contact
{
CollisionCategory contactMask =
contact.nodeA.physicsBody.categoryBitMask | contact.nodeB.physicsBody.categoryBitMask;
// first, sort out what kind of collision
if (contactMask == (CollisionCategoryMissile | CollisionCategoryRocket)) {
// next, sort out which body is the missile and which is the rocket
// and do something about it
if (contact.nodeA.physicsBody.categoryBitMask == CollisionCategoryMissile) {
[self hitRocket:contact.nodeB withMissile:contact.nodeA];
} else {
[self hitRocket:contact.nodeA withMissile:contact.nodeB];
}
} else if (contactMask == (CollisionCategoryMissile | CollisionCategoryAsteroid)) {
// ... and so on ...
}
}
Поместите этот код в один из ваших классов (возможно, в контроллер представления — везде, где вы сохраняете свою игровую логику) и заставьте этот класс декларировать соответствие SCNPhysicsContactDelegate
.
@interface ViewController: UIViewController <SCNPhysicsContactDelegate>
Затем назначьте этот объект физическому миру вашей сцены в качестве контактного делегата:
// in initial setup, where presumably you already have a reference to your scene
scene.physicsWorld.contactDelegate = self
Узнать больше
Немного о разрешении коллизий есть в SCNPhysicsBody справочная документация. И у Apple есть пример кода, который использует обнаружение столкновений — это часть шведского стола демонстраций на WWDC слайды и demo в примерах приложений и в физика транспортных средств.
Кроме того, модель обработки столкновений в SceneKit почти такая же, как и в SpriteKit, поэтому почти все в Руководство по программированию SpriteKit также полезно для понимания того же самого материала в SceneKit.
person
rickster
schedule
09.12.2014
println
прямо внутриphysicsWorld:didBeginContact:
. Таким образом, вы узнаете, связана ли ваша проблема с тем, что метод не вызывается, или вашаcontactMask
логика работает неправильно. - person rickster   schedule 10.12.2014