2014-10-27 5 views
2

Я делаю игру Space Shooter на Scene Kit, и я хочу, чтобы астероиды взорвались, когда корабль контактирует с ними, я не хочу, чтобы они сталкивались, я просто хочу знать, когда они контактируют друг с другом.SceneKit: Как обнаружить контакт без столкновения iOS

Проблема в том, что я не знаю, как реализовать обнаружение столкновения, когда корабль пересекает астероид. Например, я хочу, чтобы Xcode записывал «COLLIDED», когда они фактически общались друг с другом.

Я уже добавил categoryBitMask и collisionBitMask для обоих объектов. Итак, как я мог добиться этого? Кстати, я делаю все на Swift.

+0

ли вы на самом деле с помощью SpriteKit (2D) или SceneKit (3D)? 'SCNPhysicsBody' не имеет' contactTestBitMask'. – rickster

+0

Я использую SceneKit, мой плохой, я неправильно изменил 'categoryBitMask' для' contactTestBitMask', я изменю его прямо сейчас. –

ответ

2

В SceneKit нет возможности отделить обнаружение контактов от разрешения столкновения для динамических тел. (Если одно из ваших тел является кинематическим телом, оно не будет иметь столкновений, разрешенных против него, но оно не будет перемещаться по физике.) File a feature request?

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


Чтобы сделать что-то, когда происходит столкновение, необходимо установить contact delegate на вашем scene's physics world. В любом классе, который служит вашим делегатом-контактом, применяйте метод didBeginContact для уведомления о возникновении столкновения.

В этом методе вы должны посмотреть nodeA и nodeB, чтобы узнать, какие категории тел столкнулись (а какие есть). После того, как вы знаете, что, например, nodeA является кораблем и nodeB астероида (или наоборот), вы можете убить астероид, обновите ваш счет и т.д.

+1

Я понимаю, что когда астероид попадает в контакт с космическим кораблем, астероид будет заменен на VFX или что-то в этом роде, дело в том, что как мне заставить Xcode рассказать мне, когда астероид связывается с космическим кораблем? Я хочу знать, когда это происходит, а не что делать, когда это происходит. –

+0

А, неправильно сформулируйте вопрос. См. Отредактированный ответ. – rickster

-2

В конце концов я понял, как решить эту проблему.

Сначала я добавил categoryBitMask и collisionBitMask для обоих объектов, космического корабля и астероидов.

ship.physicsBody?.categoryBitMask = 2 
asteroid.physicsBody?.categoryBitMask = 4 

ship.physicsBody?.collisionBitMask = 4 
ball.physicsBody?.collisionBitMask = 2 

Тогда я дал dynamicBody() для них обоих.

ship.physicsBody = SCNPhysicsBody.dynamicBody() 
asteroid.physicsBody = SCNPhysicsBody.dynamicBody() 

Затем я добавил NSTimer, чтобы помочь мне с обнаружением контактов, чтобы обновить каждые 0,1 секунды, чтобы увидеть, если есть контакт.

override func viewDidLoad() 
    { 
     NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "checkContact", userInfo: nil, repeats: true) 
    } 

func checkContact() 
{ 
    if (self.scene.physicsWorld.contactTestBetweenBody(ship.physicsBody, andBody: asteroid.physicsBody, options: nil) != nil) 
    { 
     println("CONTACT!") 
    } 
} 

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

И все!

ПРИМЕЧАНИЕ: Важно добавить dynamicBody() или staticBody() к нашим 3D-объектам, иначе он не будет иметь контакта. И важно добавить dynamicBody() или staticBody() к нашим 3D-объектам, прежде чем мы добавим их в качестве ребенка на нашу сцену.

Надеюсь, это поможет кому-то!

+2

Не делайте этого. Вы выполняете повторную работу, которую SceneKit уже делает для вас, оценивая производительность. Во-первых, планирование «NSTimer» является излишним - SceneKit уже вызывает ваш метод renderer (_: updateAtTime:) 'каждый кадр, если он у вас есть. Во-вторых, SceneKit уже проверяет наличие столкновений в каждом кадре, поэтому вы повторяете эту проверку. – rickster

+0

Если вы устанавливаете 'ship.physicsBody ?.categoryBitMask' перед назначением' ship.physicsBody = SCNPhysicsBody.dynamicBody() ', то первый ничего не делает -' PhysicsBody' равен нулю, пока вы не установите его, поэтому присвоение одной из своих свойства через необязательную цепочку ничего не делают. – rickster

+0

Затем, где SceneKit проверяет наличие столкновений в каждом кадре? –

0

Я получил это, чтобы работать с гораздо более простым ответом.

На узле вы хотите вещи, чтобы провалиться, установить массу физики в очень небольшом количестве:

ship.physicsBody.mass = 0.00000000000001; 
+1

И что это должно делать? –

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