SceneKit_中级04_约束的使用

SceneKit_入门01_旋转人物
SceneKit_入门02_如何创建工程
SceneKit_入门03_节点
SceneKit_入门04_灯光
SceneKit_入门05_照相机
SceneKit_入门06_行为动画
SceneKit_入门07_几何体
SceneKit_入门08_材质
SceneKit_入门09_物理身体
SceneKit_入门10_物理世界
SceneKit_入门11_粒子系统
SceneKit_入门12_物理行为
SceneKit_入门13_骨骼动画
SceneKit_中级01_模型之间的过渡动画
SceneKit_中级02_SCNView 详细讲解
SceneKit_中级03_切换照相机视角
SceneKit_中级04_约束的使用
SceneKit_中级05_力的使用
SceneKit_中级06_场景的切换
SceneKit_中级07_动态修改属性
SceneKit_中级08_阴影详解
SceneKit_中级09_碰撞检测
SceneKit_中级10_滤镜效果制作
SceneKit_中级11_动画事件
SceneKit_高级01_GLSL
SceneKit_高级02_粒子系统深入研究
SceneKit_高级03_自定义力
SceneKit_高级04_自定义场景过渡效果
SceneKit_高级05 检测手势点击到节点
SceneKit_高级06_加载顶点、纹理、法线坐标
SceneKit_高级07_SCNProgram用法探究
SceneKit_高级08_天空盒子制作
SceneKit_高级09_雾效果
SceneKit_大神01_掉落的文字
SceneKit_大神02_弹幕来袭
SceneKit_大神03_navigationbar上的3D文字

1594482-ed6554e21af4cbc5.PNG
让学习成为一种习惯
先告诉你

我们在做应用开发的时候,也会用到约束,应用中的约束,就是当一个视图变化的时候,让和他之间有约束关系的其他视图,按照一定的约束规则变化,那在游戏中,我们的约束是用来干什么的?
官方的解释:

约束能够根据你定义的规则,自动调整这些变化(位置 旋转 和 比例)

认识新朋友
  • SCNConstraint

这个是游戏中的约束类,是一个抽象的类,我们不能直接使用,但是它有3个子类可以供我们使用。

我们看这个类有哪些属性

 /* 
  * 作用: 影响因子,决定约束的强度
  * 工作原理: 如果设置为1 那么在游戏每一帧渲染的时候,系统都会调整这个约束,如果你设置为0.5 在游戏的某些帧,系统不会进行约束调整 0 完全忽略约束
  * 注意 SCNTransformConstraint  对这类约束不起作用
  */
 var influenceFactor: CGFloat,默认值为 1,这是为0 时,则

接下来我们分析三个子类

  • SCNLookAtConstraint

1.作用:

让一个节点的方向,总是指向另外一个一个节点

2.怎么用? 我举个简单的例子,帮助大家理解它的用法

如果你想要玩第一视角的游戏,这是我们需要让摄像机捕捉到人物移动时的位置,这是需要给照相机节点添加一个SCNLookAtConstraint 类型的约束,就能实现这个效果。

3.原理:

其实这个约束的原理是更改节点的transform的属性

4.怎么创建

 // target 就是指向的那个目标节点 
+ (instancetype)lookAtConstraintWithTarget:(SCNNode *)target;

5.我们如果想要照相机的视野保持在水平面上,也就是说只沿在Y轴转动跟随目标节点,我们应该怎么做呢?

// 设置下面的属性为YES,就能实现上面的效果,默认为NO
var gimbalLockEnabled: Bool
  • SCNTransformConstraint

1.作用:

创建一个转换约束(提供给节点一个新的转换的计算),当系统进行下一次渲染的时候,会重新计算这个块中的约束,然后调整节点的状态

2.创建方法

 /*
  * world 设置为YES 使用世界坐标系,设置为NO 使用自身坐标系 
+ (instancetype)transformConstraintInWorldSpace:(BOOL)world  withBlock:(SCNMatrix4 (^)(SCNNode *node,  SCNMatrix4 transform))block
  • SCNIKConstraint(反向运动约束)

1.作用:

将一个节点链移动到一个目标位置

给张图理解一下:

1594482-9d513f1985cd7ebf.png
让学习成为一种习惯

2.使用步骤:

1.创建一个节点链
2.给根节点添加 SCNIKConstraint 约束对象(胳膊)
3.添加约束給执行器(手)
3.限定链式节点移动的范围
4.设置目标位置,这个值可以动态的改变

3.举个例子理解一下

比如机器人的组成身体 上臂 胳膊 和 手,身体是上臂的根节点,上臂是胳膊的根节点,胳膊是手的根节点,手是身体的根节点,如果我们要实现上面的约束的话,需要将约束的根节点设置为上臂,那我们把这个约束应该添加到手(执行)这个节点上去

4.创建反向运动约束

- (instancetype)initWithChainRootNode:(SCNNode *)chainRoot  
+ inverseKinematicsConstraintWithChainRootNode:

5.设置约束的最大旋转角度

- (void)setMaxAllowedRotationAngle:(CGFloat)angle
                      forJoint:(SCNNode *)node

6.设置目标位置

var targetPosition: SCNVector3
走进代码的世界

友情提示:

第一种约束和第二种约束都很简单,在这里就不写代码了,我们重点研究一下,第三种约束的实现。

1594482-576b02027764a980.png
制作一个机器手模型

1.创建工程(略)
2.添加模型文件(略)
3.添加框架<SceneKit/SceneKit.h>
4.创建游戏场景

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);// 添加一个重力,我们让其方向朝上
[self.view addSubview:scnView];

5.添加照相机

 SCNNode *cameraNode = [SCNNode node];
cameraNode.camera = [SCNCamera camera];
cameraNode.camera.automaticallyAdjustsZRange = true;
cameraNode.position = SCNVector3Make(0, 0,1000);
[scnView.scene.rootNode addChildNode:cameraNode];

6.添加机器手臂并设置约束

-(void)addArmToScene{

// 创建手掌
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);

// 创建小手臂
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); // 连接点
[lowerArm addChildNode:handNode];

// 创建上臂
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];

// 创建控制点
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);

// 添加到场景中去
[scnView.scene.rootNode addChildNode:controlNode];
scnView.delegate = self;

// 创建约束
 ikContrait =[SCNIKConstraint inverseKinematicsConstraintWithChainRootNode:controlNode];

// 给执行器添加约束
handNode.constraints = @[ikContrait];
}

7.添加一个手,每次点击屏幕,随机增加一个球

// 添加手势
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];
// 创建动画,当手掌接触到小球时,给小球添加一个动态身体
[SCNTransaction begin];
[SCNTransaction setAnimationDuration:0.5];
ikConstrait.targetPosition = node.position;
[SCNTransaction commit];
node.physicsBody = [SCNPhysicsBody dynamicBody];  
}

运行一下试试看:

1594482-05b0f998c8bdfdbb.gif
让学习成为一种习惯
总结

今天我们使用了反向运动约束,不知道你学会了没有,其他两种约束都比较简单,请自行进行学习,如有疑问,请联系我!


代码库,听说经常给人点赞都当老板了!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值