本节任务
SCNNode的clone方法你要知道怎么用?
Swift原型
clone() -> Self
从这个方法的名字我们知道它就是在克隆对象,什么是克隆?就是复制一个一模一样的东西出来,计算机中的克隆,其实是创建一个新的内存空间,将一对象占用的内存数据全部复制一份到另一个内存空间里
下面讲解一下SCNNode的clone方法都干了什么事情?
1.克隆的节点是自动管理内存的
2.克隆节点的时候,子节点也会被克隆
3.源节点和克隆的节点共享的对象有light, geometry, camera等
4.如果你想要独立的改变副本的某些共享对象,就必须分别复制节点的共享对象,或者为它创新创建这些对象
我们举一个简单的例子
这里有一个模型文件包含了骨骼动画,先把它导入到工程中去(记得使用右击导入文件的方式)
然后我们加载文件模型
let url = Bundle.main.url(forResource: "boss", withExtension: "dae")
let scene = try! SCNScene(url: url!, options: nil)
let scene = SCNScene()
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
cameraNode.camera?.automaticallyAdjustsZRange = true
let scnView = self.view as! SCNView
scnView.scene = scene
我们注意到模型的大小为
width:348.292
height:649
depth:368.192
此时运行发现 什么都看不到,原因很简单,是由于我们的模型太大了
有三种方法可以让我看的到模型
1.将相机沿着+z轴的方向移动
2.将模型沿着-z轴的方向移动
3.改变模型的比例值
第一种 方式
cameraNode.position = SCNVector3(x: 0, y: 0, z: 1000)
运行结果如上
第二种 方式
let boss = scene.rootNode.childNode(withName: "bossGroup", recursively: true)
boss?.position = SCNVector3(x: 0, y: 0, z: -1000)
运行结果如上
第三种 方式
let boss = scene.rootNode.childNode(withName: "bossGroup", recursively: true)
boss?.scale = SCNVector3Make(0.01, 0.01, 0.01)
发现是可以的
如果我们要将多个模型加载到一个场景下应该怎么办呢?
接下来,我们来演示一下过程
1.首先创建一个空的场景
let scene = SCNScene()
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
cameraNode.camera?.automaticallyAdjustsZRange = true
// place the camera
cameraNode.position = SCNVector3(x: 0, y: 0, z: 0)
let scnView = self.view as! SCNView
scnView.scene = scene
2.将模型文件中的模型加载到场景中去
let url = Bundle.main.url(forResource: "boss", withExtension: "dae")
let bossScene = try! SCNScene(url: url!, options: nil)
let boss = bossScene.rootNode.childNode(withName: "bossGroup", recursively: true)
boss?.position = SCNVector3Make(0, 0, -3000)
scene.rootNode.addChildNode(boss!)
运行结果如下
这个时候,我们想要创建很多个怪兽,最优化的办法就是使用clone方法
for i in 0...20 {
var bossCopy = boss?.clone()
bossCopy!.position = SCNVector3Make(0, Float(i * 100), -3000)
scene.rootNode.addChildNode(bossCopy!)
}
有时候你会发现 你直接加载的场景文件中的模型 不能调节位置属性,这个时候你只需要clone一下模型 然后在添加到场景的rootNode 节点上即可
下面还有一种情况 必须使用clone
如果你想要将boss.dea文件的包含多个模型,你需要一次性将他们全部加入场景中,你可能会像下面一样
let url = Bundle.main.url(forResource: "boss", withExtension: "dae")
let bossScene = try! SCNScene(url: url!, options: nil)
let boss = bossScene.rootNode
boss.position = SCNVector3Make(0, 0, -3000)
scene.rootNode.addChildNode(boss)
这个时候会报一个错误
Error: removing the root node of a scene from its scene is not allowed
iOS 11 之后,遇到这个程序直接崩溃,所以我们遇到这种情况需要像下面这样做
let url = Bundle.main.url(forResource: "boss", withExtension: "dae")
let bossScene = try! SCNScene(url: url!, options: nil)
let boss = bossScene.rootNode
boss.position = SCNVector3Make(0, 0, -3000)
scene.rootNode.addChildNode(boss.clone())