我是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) 请帮助我理解,我做错了什么。
答案 0 :(得分:3)
我可以看到三个问题:
不保留委托,因此您必须通过将MyRender
实例分配给某个强变量(例如实例变量)来保持rendererDelegate
实例的活动
assign
被声明为weak
而不是nil
,因此当代理被解除分配时,它不会自动设置为nil
(这是SceneKit中的弱点) )所以你必须明确地将它设置为MyRender
。在释放boxNode
实例时,SceneKit仍然认为{{1}}有一个委托,而消息是一个解除分配的对象(EXC_BAD_ACCESS崩溃)
似乎你最终会陷入无限循环。您的委托方法正在调用自己。
答案 1 :(得分:-1)
请试一试,首先必须定义你的课程
@interface YourClass : SCNView <SCNPhysicsContactDelegate, SCNSceneRendererDelegate>
{
}
@end
完成后,您的班级已准备好参与渲染和物理联系,但您仍然必须告诉您的主要SCNView和SCNScene YOURClass将接管。 你这样做:
[Myview setDelegate:self];
[[Myscene physicsWorld] setContactDelegate:self];
你可以在初始化课程时这样做,我个人将Myscene和MYview作为一个单身人士。
完成所有操作后,您需要在实现文件中添加下一行:
-(void)physicsWorld:(SCNPhysicsWorld *)world didBeginContact:(SCNPhysicsContact *)contact{}
-(void)physicsWorld:(SCNPhysicsWorld *)world didEndContact:(SCNPhysicsContact *)contact{}
-(void)physicsWorld:(SCNPhysicsWorld *)world didUpdateContact:(SCNPhysicsContact *)contact{}
-(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标记。 希望这有帮助