SceneKit_入門01_旋轉(zhuǎn)人物
SceneKit_入門02_如何創(chuàng)建工程
SceneKit_入門03_節(jié)點(diǎn)
SceneKit_入門04_燈光
SceneKit_入門05_照相機(jī)
SceneKit_入門06_行為動(dòng)畫
SceneKit_入門07_幾何體
SceneKit_入門08_材質(zhì)
SceneKit_入門09_物理身體
SceneKit_入門10_物理世界
SceneKit_入門11_粒子系統(tǒng)
SceneKit_入門12_物理行為
SceneKit_入門13_骨骼動(dòng)畫
SceneKit_中級(jí)01_模型之間的過渡動(dòng)畫
SceneKit_中級(jí)02_SCNView 詳細(xì)講解
SceneKit_中級(jí)03_切換照相機(jī)視角
SceneKit_中級(jí)04_約束的使用
SceneKit_中級(jí)05_力的使用
SceneKit_中級(jí)06_場(chǎng)景的切換
SceneKit_中級(jí)07_動(dòng)態(tài)修改屬性
SceneKit_中級(jí)08_陰影詳解
SceneKit_中級(jí)09_碰撞檢測(cè)
SceneKit_中級(jí)10_濾鏡效果制作
SceneKit_中級(jí)11_動(dòng)畫事件
SceneKit_高級(jí)01_GLSL
SceneKit_高級(jí)02_粒子系統(tǒng)深入研究
SceneKit_高級(jí)03_自定義力
SceneKit_高級(jí)04_自定義場(chǎng)景過渡效果
SceneKit_高級(jí)05 檢測(cè)手勢(shì)點(diǎn)擊到節(jié)點(diǎn)
SceneKit_高級(jí)06_加載頂點(diǎn)驻谆、紋理虹脯、法線坐標(biāo)
SceneKit_高級(jí)07_SCNProgram用法探究
SceneKit_高級(jí)08_天空盒子制作
SceneKit_高級(jí)09_霧效果
SceneKit_大神01_掉落的文字
SceneKit_大神02_彈幕來襲
SceneKit_大神03_navigationbar上的3D文字
先告訴你
我們?cè)谧鰬?yīng)用開發(fā)的時(shí)候,也會(huì)用到約束,應(yīng)用中的約束,就是當(dāng)一個(gè)視圖變化的時(shí)候倔矾,讓和他之間有約束關(guān)系的其他視圖,按照一定的約束規(guī)則變化,那在游戲中,我們的約束是用來干什么的?
官方的解釋:
約束能夠根據(jù)你定義的規(guī)則,自動(dòng)調(diào)整這些變化(位置 旋轉(zhuǎn) 和 比例)
認(rèn)識(shí)新朋友
- SCNConstraint
這個(gè)是游戲中的約束類,是一個(gè)抽象的類,我們不能直接使用,但是它有3個(gè)子類可以供我們使用。
我們看這個(gè)類有哪些屬性
/*
* 作用: 影響因子,決定約束的強(qiáng)度
* 工作原理: 如果設(shè)置為1 那么在游戲每一幀渲染的時(shí)候,系統(tǒng)都會(huì)調(diào)整這個(gè)約束,如果你設(shè)置為0.5 在游戲的某些幀,系統(tǒng)不會(huì)進(jìn)行約束調(diào)整 0 完全忽略約束
* 注意 SCNTransformConstraint 對(duì)這類約束不起作用
*/
var influenceFactor: CGFloat,默認(rèn)值為 1,這是為0 時(shí),則
接下來我們分析三個(gè)子類
- SCNLookAtConstraint
1.作用:
讓一個(gè)節(jié)點(diǎn)的方向,總是指向另外一個(gè)一個(gè)節(jié)點(diǎn)
2.怎么用? 我舉個(gè)簡(jiǎn)單的例子谅海,幫助大家理解它的用法
如果你想要玩第一視角的游戲,這是我們需要讓攝像機(jī)捕捉到人物移動(dòng)時(shí)的位置,這是需要給照相機(jī)節(jié)點(diǎn)添加一個(gè)SCNLookAtConstraint 類型的約束,就能實(shí)現(xiàn)這個(gè)效果。
3.原理:
其實(shí)這個(gè)約束的原理是更改節(jié)點(diǎn)的transform的屬性
4.怎么創(chuàng)建
// target 就是指向的那個(gè)目標(biāo)節(jié)點(diǎn)
+ (instancetype)lookAtConstraintWithTarget:(SCNNode *)target;
5.我們?nèi)绻胍障鄼C(jī)的視野保持在水平面上,也就是說只沿在Y軸轉(zhuǎn)動(dòng)跟隨目標(biāo)節(jié)點(diǎn),我們應(yīng)該怎么做呢?
// 設(shè)置下面的屬性為YES蹦浦,就能實(shí)現(xiàn)上面的效果扭吁,默認(rèn)為NO
var gimbalLockEnabled: Bool
- SCNTransformConstraint
1.作用:
創(chuàng)建一個(gè)轉(zhuǎn)換約束(提供給節(jié)點(diǎn)一個(gè)新的轉(zhuǎn)換的計(jì)算),當(dāng)系統(tǒng)進(jìn)行下一次渲染的時(shí)候,會(huì)重新計(jì)算這個(gè)塊中的約束,然后調(diào)整節(jié)點(diǎn)的狀態(tài)
2.創(chuàng)建方法
/*
* world 設(shè)置為YES 使用世界坐標(biāo)系盲镶,設(shè)置為NO 使用自身坐標(biāo)系
+ (instancetype)transformConstraintInWorldSpace:(BOOL)world withBlock:(SCNMatrix4 (^)(SCNNode *node, SCNMatrix4 transform))block
- SCNIKConstraint(反向運(yùn)動(dòng)約束)
1.作用:
將一個(gè)節(jié)點(diǎn)鏈移動(dòng)到一個(gè)目標(biāo)位置
給張圖理解一下:
2.使用步驟:
1.創(chuàng)建一個(gè)節(jié)點(diǎn)鏈
2.給根節(jié)點(diǎn)添加 SCNIKConstraint 約束對(duì)象(胳膊)
3.添加約束給執(zhí)行器(手)
3.限定鏈?zhǔn)焦?jié)點(diǎn)移動(dòng)的范圍
4.設(shè)置目標(biāo)位置,這個(gè)值可以動(dòng)態(tài)的改變
3.舉個(gè)例子理解一下
比如機(jī)器人的組成身體 上臂 胳膊 和 手,身體是上臂的根節(jié)點(diǎn),上臂是胳膊的根節(jié)點(diǎn),胳膊是手的根節(jié)點(diǎn)侥袜,手是身體的根節(jié)點(diǎn),如果我們要實(shí)現(xiàn)上面的約束的話,需要將約束的根節(jié)點(diǎn)設(shè)置為上臂,那我們把這個(gè)約束應(yīng)該添加到手(執(zhí)行)這個(gè)節(jié)點(diǎn)上去
4.創(chuàng)建反向運(yùn)動(dòng)約束
- (instancetype)initWithChainRootNode:(SCNNode *)chainRoot
+ inverseKinematicsConstraintWithChainRootNode:
5.設(shè)置約束的最大旋轉(zhuǎn)角度
- (void)setMaxAllowedRotationAngle:(CGFloat)angle
forJoint:(SCNNode *)node
6.設(shè)置目標(biāo)位置
var targetPosition: SCNVector3
走進(jìn)代碼的世界
友情提示:
第一種約束和第二種約束都很簡(jiǎn)單,在這里就不寫代碼了,我們重點(diǎn)研究一下,第三種約束的實(shí)現(xiàn)溉贿。
1.創(chuàng)建工程(略)
2.添加模型文件(略)
3.添加框架<SceneKit/SceneKit.h>
4.創(chuàng)建游戲場(chǎng)景
scnView = [[SCNView alloc]initWithFrame:self.view.bounds];
scnView.backgroundColor = [UIColor blackColor];
scnView.allowsCameraControl = true;
scnView.scene = [SCNScene scene];
scnView.scene.physicsWorld.gravity = SCNVector3Make(0, 90, 0);// 添加一個(gè)重力枫吧,我們讓其方向朝上
[self.view addSubview:scnView];
5.添加照相機(jī)
SCNNode *cameraNode = [SCNNode node];
cameraNode.camera = [SCNCamera camera];
cameraNode.camera.automaticallyAdjustsZRange = true;
cameraNode.position = SCNVector3Make(0, 0,1000);
[scnView.scene.rootNode addChildNode:cameraNode];
6.添加機(jī)器手臂并設(shè)置約束
-(void)addArmToScene{
// 創(chuàng)建手掌
SCNNode *handNode = [SCNNode node];
handNode.geometry = [SCNBox boxWithWidth:20 height:20 length:20 chamferRadius:0];
handNode.geometry.firstMaterial.diffuse.contents = [UIColor purpleColor];
handNode.position = SCNVector3Make(0, -50, 0);
// 創(chuàng)建小手臂
SCNNode *lowerArm = [SCNNode node];
lowerArm.geometry = [SCNCylinder cylinderWithRadius:1 height:100];
lowerArm.geometry.firstMaterial.diffuse.contents = [UIColor redColor];
lowerArm.position = SCNVector3Make(0, -50, 0);
lowerArm.pivot = SCNMatrix4MakeTranslation(0, 50, 0); // 連接點(diǎn)
[lowerArm addChildNode:handNode];
// 創(chuàng)建上臂
SCNNode *upperArm = [SCNNode node];
upperArm.geometry = [SCNCylinder cylinderWithRadius:1 height:100];
upperArm.geometry.firstMaterial.diffuse.contents = [UIColor greenColor];
upperArm.pivot = SCNMatrix4MakeTranslation(0, 50, 0);
[upperArm addChildNode:lowerArm];
// 創(chuàng)建控制點(diǎn)
SCNNode *controlNode = [SCNNode node];
controlNode.geometry = [SCNSphere sphereWithRadius:10];
controlNode.geometry.firstMaterial.diffuse.contents = [UIColor blueColor];
[controlNode addChildNode:upperArm];
controlNode.position= SCNVector3Make(0, 100, 0);
// 添加到場(chǎng)景中去
[scnView.scene.rootNode addChildNode:controlNode];
scnView.delegate = self;
// 創(chuàng)建約束
ikContrait =[SCNIKConstraint inverseKinematicsConstraintWithChainRootNode:controlNode];
// 給執(zhí)行器添加約束
handNode.constraints = @[ikContrait];
}
7.添加一個(gè)手,每次點(diǎn)擊屏幕宇色,隨機(jī)增加一個(gè)球
// 添加手勢(shì)
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapHandle)];
[scnView addGestureRecognizer:tap];
-(void)tapHandle{
[self createNodeToScene:scnView.scene andConstraint:ikContrait];
}
-(void)createNodeToScene:(SCNScene*)scene andConstraint:(SCNIKConstraint*)ikConstrait{
SCNNode *node = [SCNNode node];
node.position = SCNVector3Make(arc4random_uniform(100), arc4random_uniform(100), arc4random_uniform(100));
[scene.rootNode addChildNode:node];
node.geometry = [SCNSphere sphereWithRadius:10];
node.geometry.firstMaterial.diffuse.contents = [UIColor colorWithRed:arc4random_uniform(255.0)/255.0 green:arc4random_uniform(255.0)/255.0 blue:arc4random_uniform(255.0)/255.0 alpha:1];
// 創(chuàng)建動(dòng)畫九杂,當(dāng)手掌接觸到小球時(shí),給小球添加一個(gè)動(dòng)態(tài)身體
[SCNTransaction begin];
[SCNTransaction setAnimationDuration:0.5];
ikConstrait.targetPosition = node.position;
[SCNTransaction commit];
node.physicsBody = [SCNPhysicsBody dynamicBody];
}
運(yùn)行一下試試看:
總結(jié)
今天我們使用了反向運(yùn)動(dòng)約束,不知道你學(xué)會(huì)了沒有,其他兩種約束都比較簡(jiǎn)單宣蠕,請(qǐng)自行進(jìn)行學(xué)習(xí)例隆,如有疑問,請(qǐng)聯(lián)系我!
代碼庫,聽說經(jīng)常給人點(diǎn)贊都當(dāng)老板了!