版本记录
版本号 | 时间 |
---|---|
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
的新实例,并将其分配给geometryNode
的physicsBody
属性。 创建物理实体时,可以指定实体的类型和形状。 如果为物理形状传递nil
,SceneKit
将根据节点的可视几何体自动生成形状。
如果要向物理形状添加更多细节,可以创建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的简单游戏示例的实现,感兴趣的给个赞或者关注~~~