SceneKit框架详细解析(四) —— 基于SceneKit的简单游戏示例的实现(三)

版本记录

版本号 时间
V1.0 2018.10.20 星期六

前言

SceneKit使用高级场景描述创建3D游戏并将3D内容添加到应用程序。 轻松添加动画,物理模拟,粒子效果和逼真的基于物理性的渲染。接下来这几篇我们就详细的解析一下这个框架。感兴趣的看下面几篇文章。
1. SceneKit框架详细解析(一) —— 基本概览(一)
2. SceneKit框架详细解析(二) —— 基于SceneKit的简单游戏示例的实现(一)
3. SceneKit框架详细解析(三) —— 基于SceneKit的简单游戏示例的实现(二)

开始

在这部分中,您将学习如何通过Scene Kit物理的强大功能使几何体移动。

我们开始吧!

在本教程中,您将使用SceneKit的物理引擎为您的游戏添加物理。

SceneKit的物理引擎功能强大,易于使用。 您只需告诉SceneKit您想要应用物理的对象,引擎将从该点接管,模拟重力和碰撞等事物。

在深入将物理学集成到游戏中之前,您首先需要为项目添加一些game utilities


Introducing the Game Utilities - 介绍游戏工具

game utilities是专门为您创建的。 它们包括辅助方法,可以处理游戏中的复杂位。 这让你专注于游戏玩法,而不是那些讨厌的比特。

在这里加了一些游戏相关的工具,就不细说了,后面用到会详细说明。

1. Adding the Game Utilities - 添加游戏工具

要添加游戏实用程序,只需将GameUtils文件夹拖放到GeometryFighter组文件夹下的项目中:

将所有设置保留为默认值,然后单击Finish

这会将整个GameUtils文件夹作为一个组导入到您的项目中。 展开此组文件夹,快速查看一些帮助程序方法。 如果某些代码对您没有意义,请不要太担心。


Physics - 物理

是时候快速状态检查游戏的当前状态了。构建并运行游戏;一个很酷的随机几何物体像某种黑暗魔法一样在空气中产生。这可能现在看起来不太多,但很快就会有所改善!

刚刚产生的物体只是挂在空旷的空间里并没有做太多。当然,你可以围绕它旋转相机并放大和缩小,但也就是只能这样。这不是一个有趣的游戏。为了提高兴奋程度,如果物体至少移动一点,那就太好了。

现在,你可以走很长的路,并随着时间的推移操纵对象的位置和旋转,以便旋转和移动。您很快就会意识到虽然可以以这种方式为对象设置动画,但它需要大量的编码工作 - 尤其是当您添加其他功能(如真实碰撞和对象之间的交互)时。

值得庆幸的是,Apple的开发人员已经考虑过这一点;为此,他们将一个非常强大的3D物理引擎集成到SceneKit中。要使用这个内置的物理引擎,您只需要让引擎知道您的对象。

以将几何信息附加到节点的方式相同,可以将physics body附加到节点。物理主体描述了节点的所有物理属性,包括形状,质量,摩擦,阻尼和恢复等内容。物理引擎在模拟对象的真实物理交互时会考虑所有这些信息。这包括重力,摩擦和物理世界中其他物体碰撞等事物。

下一节将详细介绍物理机构的一些重要特征。

1. Physics Body Types - 物理体类型

创建物理主体时必须指定的关键属性之一是其类型(type)。物理体类型定义了物体如何与模拟中的力和其他物体相互作用。

SceneKit中使用了三种类型:

  • 静态(Static)物体不会移动:当其他物体可能与这些物体碰撞时,静态物体本身不受模拟中任何力和碰撞的影响。您可以将此类型用于墙壁和巨大的固定巨石等物体。
  • 动态(Dynamic)物体由物理引擎自动移动以响应力和碰撞。您可以将此类型用于可移动椅子,桌子和杯子等物品。
  • 物理引擎不会自动移动运动(Kinematic)物体以响应力和碰撞。换句话说,如果运动物体与动态(dynamic)物体碰撞,动态物体将会移动,但运动物体不会移动。但是,您可以在代码中手动移动运动体。您可以将此类型用于手动控制的内容,例如移动电梯或可以打开和关闭的门。

2. Physics Shapes - 物理形状

除了物体的类型之外,在创建物理主体时必须指定的另一个导入属性是其形状(shape)。 物理形状定义物理引擎在碰撞检测期间使用的3D形状。 虽然几何定义了节点的视觉效果,但物理主体定义了节点如何与物理模拟中的其他对象进行交互。

您可以使形状(shape)与视觉几何形状完全相同,但这通常比您需要的计算成本更高(因此导致您的游戏运行速度变慢)。 相反,您通常应该使用几何体的简化版本,例如简单的边界框,球体或其中一个提供的原始形状,大致匹配节点的可见外观,如下所示:

3. Adding Physics - 添加物理

现在你已经学会了物理背后的理论,现在是时候开始使用这些概念来改变游戏中的事物了。

在SceneKit中,所有物理实体都是SCNPhysicsBody对象。 创建物理主体后,可以将其分配给SCNNode实例的physicsBody属性。 一旦将物理主体分配给适当的节点,物理引擎就可以为您模拟物理。 就这么简单!

打开GameViewController.swift并在spawnShape()中创建geometryNode的代码行之后添加以下内容:

geometryNode.physicsBody =
  SCNPhysicsBody(type: .dynamic, shape: nil)

这行代码创建了SCNPhysicsBody的新实例,并将其分配给geometryNodephysicsBody属性。 创建物理实体时,可以指定实体的类型和形状。 如果为物理形状传递nilSceneKit将根据节点的可视几何体自动生成形状。

如果要向物理形状添加更多细节,可以创建SCNPhysicsShape并将其用于形状而不是传入nil

构建并运行您的游戏; 一个随机的形状产生进入场景,然后以死鸟的所有优雅的方式从空中掉落,掉出视线:

您甚至可以平移相机以观察物体。 你在这里看到的是重力作用于物体的影响。 SceneKit中的场景默认情况下重力打开。 现在生成的对象具有物理主体,物理模拟将模拟力(例如重力)应用于对象。


Forces - 力

想一想现实生活中的物体:做一些移动的东西 - 比如桌子上的勺子 - 你必须对它施加某种类型的物理力。

SceneKit物理引擎在模拟真实物理方面做得相当不错,所以就像你在现实生活中使用力来移动物体一样,你需要在你的物理体上施加一个力来移动物体。

当你将力施加到一个物理体,你用applyForce(direction: at: asImpulse:)并传递一个SCNVector3实例。可以获得你要施加力时候的力和位置,您施加的力会影响物理体的线性加速度和角加速度。

冲击(impulse)仅将力施加到物理体上,例如当你踢球时。物理模拟中的每一步都应用非冲击力。 SceneKit将在对象上添加所有施加的力,并根据这些力的最终结果加速物理体。这可以模拟类似于助推火箭的东西,其中力是连续的。

之前,您了解到力是具有x,y和z分量的向量。但是,这是什么意思?看看下图:

力具有大小和方向,因此矢量确定每个轴的力的大小。 在上面的示例中,应用具有(x:0,y:10,z:0)向量的力可以使用垂直力向上移动主体。

要应用水平力,您只能使用(x:10,y:0,z:0)的向量指定x轴上的力的大小。 要向左移动而不是向右移动,您将在x轴上施加负的力大小。 当您将各种矢量组合在一起时(x:10,y:10,z:0),您可以准确控制身体的移动方式 - 在这种情况下,对角线。

力也可以应用于物理体的特定位置以产生不同的运动:

同样,它有助于思考现实生活中的例子。 如果你前面有一个挡块并推动它,挡块会根据你施加推动的位置而有所不同。 将相同的力施加到身体质心的左侧或右侧,例如,在(x:1,y:0,z:0)处将使其旋转。在(x:0,y:0,z:0)处直接施加与质心一致的力将不会产生旋转。

1. Applying Force - 施力

卷起你的袖子 - 是时候施加一些力量了!

spawnShape()中为geometryNode创建物理体的行之后添加以下代码:

// 1
let randomX = Float.random(min: -2, max: 2)
let randomY = Float.random(min: 10, max: 18)
// 2
let force = SCNVector3(x: randomX, y: randomY , z: 0)
// 3
let position = SCNVector3(x: 0.05, y: 0.05, z: 0.05)
// 4
geometryNode.physicsBody?.applyForce(force,
  at: position, asImpulse: true)

下面进行详细说明:

  • 1) 这将创建两个随机浮点值,表示力的x和y分量。 它使用您在本教程前面添加的实用程序的Float扩展。
  • 2) 接下来,使用这些随机组件创建一个向量来表示此力。
  • 3) 这将创建另一个向量,表示力将应用到的位置。 该位置稍微偏离中心,以便在物体上产生旋转。
  • 4) 最后,使用所有这些组件,使用applyForce(direction:at:asImpulse :)将力应用于geometryNode的物理体。

构建并运行;当物体凭空产生时,一些神奇的力量将它踢向空中,而不是像死鸟一样掉落:

当重力作用时,物体最终会落下。


Torque - 扭力

扭矩是另一种可以使用applyTorque(torque: asImpulse:)应用于物体的旋转力。 扭矩仅影响物理体的角动量(自旋),而不影响线性动量(x,y,z)。 施加扭矩导致物体围绕其质心旋转。

要了解扭矩如何影响物理机构,请查看下图:

应用扭矩力时,使用SCNVector4指定四分量矢量,而不是像使用力一样使用三分量矢量。 x,y和z分量确定旋转轴,而w分量确定旋转角度,即扭矩的大小。
就像使用applyForce(direction:at:asImpulse :)一样,您可以选择是否将扭矩应用为冲击,这会影响物理引擎处理矢量的方式。

如果扭矩是冲击,则方向矢量被视为角动量的瞬时变化。想想用手指旋转篮球;为了保持球的旋转,你必须用你的手快速挥动球的一侧,每次轻弹都会产生一个冲击,瞬间增加球的角动量。

当扭矩不作为冲击施加时,它在每个物理模拟步骤之后应用。 SceneKit将对所有施加的力和扭矩求和,并根据这些力的净效应加速物理体的角力。可以把它想象成一个围绕自己的轴以恒定速度旋转的行星。

注意:SceneKit物理模拟使用国际单位系统(SI)进行测量:质量单位的公斤数,力单位的牛顿,脉冲(impulse)单位的牛顿秒和扭矩单位的牛顿米。


Adding Flair - 添加Flair

既然你已经移动了几何物体,你可能已经注意到它在屏幕中间的空气中产生,这看起来有点尴尬。 为了解决这个问题,你可以将相机在y轴上移动一点,这样物体就会在屏幕外产生。

1. Positioning the Camera - 定位相机

要向上移动摄像机位置,请使用以下内容替换在setupCamera()中设置摄像机位置的行:

cameraNode.position = SCNVector3(x: 0, y: 5, z: 10)

构建并运行,您将看到该对象似乎在屏幕外生成!

2. Adding some Color - 添加一些颜色

最后,您可以为随机生成的形状添加一些变化。

spawnShape()中添加以下几行,在您随机创建geometry的位置之后,但在创建geometryNode之前:

geometry.materials.first?.diffuse.contents = UIColor.random()

要为随机对象着色,可以修改geometry上的materials;此行获取几何体的第一个可用材质,并将diffuse属性的内容设置为随机UIColor。 UIColor上的random()方法是另一个被定义为game utilities内部扩展的助手。

注意:这里需要注意的是,您可以为漫反射(diffuse )属性的内容指定UIColor,以便更改对象的颜色。

最后,构建并运行游戏以查看颜色漂亮的对象:

后记

本篇主要讲述了基于SceneKit的简单游戏示例的实现,感兴趣的给个赞或者关注~~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容