Как настроить обнаружение столкновения SceneKit

Привет, я налил документацию и не могу понять, как настроить обнаружение столкновения в наборе сюжетов. Может кто-нибудь, пожалуйста, покажет пример. Пожалуйста, помогите, я очень отчаянна, чтобы понять это. Спасибо!

Редактировать: Привет Большое спасибо, мне жаль, что я забыл упомянуть, что мой проект идет быстро. Ничего страшного я могу перевести сам по большей части.

У меня есть BitMasks, которые работают правильно, когда объекты сталкиваются и отскакивают друг от друга. Однако я не могу заставить функцию работать

func physicsWorld(world: SCNPhysicsWorld, didBeginContact contact: SCNPhysicsContact){ let contactMask = contact.nodeA.physicsBody!.categoryBitMask | contact.nodeB.physicsBody!.categoryBitMask if (contactMask == (CollisionBallCategory | CollisionTerminatorCategory)) { println("Collided") } } 

Глядя на документацию, мне кажется, мне нужно каким-то образом присвоить делегату мира физики сцены этот метод. Я не уверен, как это сделать.

Основные сведения о обнаружении столкновений в 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 ... } } 

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

 @interface ViewController: UIViewController  

Затем назначьте этот объект физическому миру вашей сцены в качестве делегата-контакта:

 // in initial setup, where presumably you already have a reference to your scene scene.physicsWorld.contactDelegate = self 

Узнать больше

Немного о разрешении конфликтов в справочной документации SCNPhysicsBody . И у Apple есть пример кода, который использует обнаружение конфликтов - это часть smorgasbord демонстраций в слайдах и демонстрационных примерах WWDC, а также в демо- версии автомобильной физики .

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

Давайте будем гением компьютера.