如何使用SCNNodeRendererDelegate?

时间:2015-01-07 19:07:17

标签: swift scenekit

我是Swift和SceneKit的新手,并试图了解如何使用SCNNodeRendererDelegate。

我已声明委托如下

class MyRender: NSObject, SCNNodeRendererDelegate {

  func renderNode(node: SCNNode, renderer: SCNRenderer, arguments: [NSObject : AnyObject]) {
    node.rendererDelegate!.renderNode!(node, renderer: renderer, arguments: arguments)
  }
}

并尝试使用它

class GameViewController: NSViewController {

  @IBOutlet weak var gameView: GameView!

  override func awakeFromNib(){
    // ... some code ....
    let boxNode = SCNNode()
    boxNode.geometry = SCNBox(width: 5, height: 5, length: 5, chamferRadius: 0.1)
    boxNode.geometry?.firstMaterial?.diffuse.contents = NSColor.blueColor()
    boxNode.rendererDelegate = MyRender()
    scene.rootNode.addChildNode(boxNode)
    // ... some code ....

启动后失败,出现EXC_BAD_ACCESS(代码= 1,地址= 0x0) 请帮助我理解,我做错了什么。

2 个答案:

答案 0 :(得分:3)

我可以看到三个问题:

  1. 不保留委托,因此您必须通过将MyRender实例分配给某个强变量(例如实例变量)来保持rendererDelegate实例的活动

  2. assign被声明为weak而不是nil,因此当代理被解除分配时,它不会自动设置为nil(这是SceneKit中的弱点) )所以你必须明确地将它设置为MyRender。在释放boxNode实例时,SceneKit仍然认为{{1}}有一个委托,而消息是一个解除分配的对象(EXC_BAD_ACCESS崩溃)

  3. 似乎你最终会陷入无限循环。您的委托方法正在调用自己。

答案 1 :(得分:-1)

请试一试,首先必须定义你的课程

 @interface YourClass : SCNView <SCNPhysicsContactDelegate, SCNSceneRendererDelegate>
 {

 }
 @end

完成后,您的班级已准备好参与渲染和物理联系,但您仍然必须告诉您的主要SCNView和SCNScene YOURClass将接管。 你这样做:

 [Myview setDelegate:self];
 [[Myscene physicsWorld] setContactDelegate:self];

你可以在初始化课程时这样做,我个人将Myscene和MYview作为一个单身人士。

完成所有操作后,您需要在实现文件中添加下一行:

pragma mark PhysicsDelegate

-(void)physicsWorld:(SCNPhysicsWorld *)world didBeginContact:(SCNPhysicsContact *)contact{}

-(void)physicsWorld:(SCNPhysicsWorld *)world didEndContact:(SCNPhysicsContact *)contact{}

-(void)physicsWorld:(SCNPhysicsWorld *)world didUpdateContact:(SCNPhysicsContact *)contact{}

pragma mark RenderDelegate

-(void)renderer:(id<SCNSceneRenderer>)aRenderer updateAtTime:(NSTimeInterval)time{}
-(void)renderer:(id<SCNSceneRenderer>)aRenderer didApplyAnimationsAtTime:(NSTimeInterval)time{}
-(void)renderer:(id<SCNSceneRenderer>)aRenderer didRenderScene:(SCNScene *)scene atTime:(NSTimeInterval)time{}
-(void)renderer:(id<SCNSceneRenderer>)aRenderer didSimulatePhysicsAtTime:(NSTimeInterval)time{}
-(void)renderer:(id<SCNSceneRenderer>)aRenderer willRenderScene:(SCNScene *)scene atTime:(NSTimeInterval)time{}

现在您可以参与渲染和物理代理。

当然,没有必要使用Pragma标记。 希望这有帮助