计算机游戏程序设计实验指导书4河北工业大学.docx
《计算机游戏程序设计实验指导书4河北工业大学.docx》由会员分享,可在线阅读,更多相关《计算机游戏程序设计实验指导书4河北工业大学.docx(14页珍藏版)》请在冰豆网上搜索。
![计算机游戏程序设计实验指导书4河北工业大学.docx](https://file1.bdocx.com/fileroot1/2023-1/31/72054a04-e8fe-425d-a06d-ac7a26d61c02/72054a04-e8fe-425d-a06d-ac7a26d61c021.gif)
计算机游戏程序设计实验指导书4河北工业大学
计算机游戏程序设计
实验指导书
河北工业大学
计算机科学与软件学院
实验四应用物理引擎实现游戏
一、实验目的与要求
1.熟悉并掌握刚体及使用方法。
2.熟悉并掌握碰撞器及使用方法。
3.熟悉并掌握射线及使用方法。
4.熟悉并掌握关节及使用方法。
5.熟悉并掌握角色控制器及使用方法
二、实验原理及知识点
物理引擎就是在游戏中模拟真实的物理效果:
比如,场景中有两个立方体对象,一个在空中,一个在地面上,在空中的立方体开始自由下落,然后与地面上的立方体对象发生碰撞,而物理引擎就是用来模拟真实碰撞后的效果。
Unity的物理引擎使用的是NVIDIA(英伟达)的PhysX。
目前,PC上很多游戏发烧友使用的显卡都是英伟达,该显卡是专门为游戏而设计的,它的物理引擎的效果很好,可以完美地在3D世界中模拟任何物理效果。
该引擎完全可适用于次世代游戏开发,它渲染的游戏画面更加逼真,给玩家身临其境的感觉。
如需让模型感应物理引擎的效果,需要将刚体组件或者角色控制器组件添加至该对象当中,刚体组件所受的物理效果是完美虚拟现实中的物理效果,而角色控制器需要受一些限制条件来感应物理效果。
1刚体
刚体是一个非常重要的组件。
新创建的物体默认情况下是不具备物理效果的,而刚体组件可以给物体添加一些常见的物理属性,比如物体质量、摩擦力和碰撞参数等,这些属性可用来真实模拟该物体在3D游戏世界中的一切行为。
刚体可以以游戏组件的形式绑定在物体当中。
如果物体添加了刚体组件,那么它将感应物理引擎中的一切物理效果。
1.1简单使用
要想使用刚体,首先需要将刚体组件添加至游戏对象当中,具体操作方法如下:
在Unity中创建一个需要添加刚体组件的游戏对象,比如立方体对象、球体对象、模型对象等含有网格的对象皆可,接着在Hierarcliy视图中选择刚刚创建的游戏对象,然后在Unity导航菜单栏中选择"Component"、"Pliysics”一“Rigidbody”菜单。
在例子中我们创建三个立方体,分别将其凌空放置在地面上,并且只给其中一个立方体添加刚体组件:
运行游戏后,发现红色立方体正常感应了物理效果,从空中落了下来(因为只给它添加了刚体组件),而剩下的两个立方体依然停留在空中。
在Hierarcliy视图中选择添加过刚体组件的游戏对象,此时在右侧的Inspector视图中可清晰地看到刚体组件包含的属性,下面简要介绍一下其中各个属性的含义。
Mass:
质量,数值越大物体下落得也就越快。
尽量不要让数值其超过10,否则物理效果就不会很真实
Drag:
阻力,数值越大物体速度减慢得就越快。
AngularDrag:
角阻力,数值越大自身旋转的速度减慢得就越快。
UseGravity:
是否使用重力。
IsKinematic:
是否受物理的影响:
Interpolate:
设置图像差值。
CollisionDetection:
碰撞监测。
Constraints:
冻结,停止某个轴向感应物理引擎的效果。
FreezePosition:
冻结x轴方向、Y轴方向和z轴方向。
FreezeRotation:
冻结x轴旋转、y轴旋转和z轴旋转。
1.2力
力在物理学中是一个非常重要的元素,其种类有很多。
刚体组件可以受力的作用,比如给刚体施加一个x轴方向的力,那么该刚体绑定的物体将沿着x轴方向向前移动,这就好比用力将物体扔出去一样,该物体将会以抛物线的形式移动,而不是呆板地做匀速平移。
Unity中力的方式有两种:
第一种为普通力,需要设定力的方向与大小;第二种为目标位置力,需要设定目标点的位置,该物体将朝向这个目标位置施加力。
在例子中,我们共放置两个球体对象,点击“普通力”按钮后,小球将像一脚被踢开似地向前滚动。
点击“位置力”按钮后,小球将被施加一个朝向目标点的力,然后向目标滚动。
使用方法rigidbody.AddForce()添加一个普通力,该方法的参数是施加力的方向,单位是Vector3容器。
使用方法rigidbody.AddForceAtPosition()施加一个目标位置力,该方法的第一个参数为目标点的位置坐标,第二个参数为力的模式。
2碰撞器
游戏对象如果需要感应碰撞,那么必须给其添加碰撞器。
默认情况下,创建游戏对象时,会自动将碰撞器组件添加至其中,而碰撞器组件决定了模型碰撞的方式。
Unity一共为对象提供了5种碰撞器,分别是BoxCollider(盒子碰撞器)、SphereCollider(球体碰撞器)、CapsuleCollider(胶囊碰撞器)、MeshCollider(网格碰撞器)和WheelCollider(车轮碰撞器),其中BoxCollider适用于立方体对象之间的碰撞,SphereCollider适用于球体对象之间的碰撞,CapsuleCollider适用于胶囊体对象之间的碰撞,MeshCollider比较特殊,它的碰撞方式由自定义模型的自身网格决定,适用于自定义网格的碰撞,WheelColhder适用于车轮与地面或其他对象之间的碰撞。
在碰撞器之间可以添加物理材质,用于设定物理碰撞后的效果。
物理材质与碰撞器之间的关系非常紧密,比如两个立方体相撞后,按照物理引擎的效果,它们将开始相互反弹,那么反弹的力度就是由物理材质决定的。
2.1添加碰撞器
添加碰撞器的方式如下:
打开Unity,在Hierarchy视图中选择一个需要添加碰撞器的游戏对象,此时在Unity导航菜单栏中选择“Component"->"Physics”菜单项,然后从中选择碰撞器的种类。
2.2物理材质
物理材质可设定物体的表面材质,不同的表面材质可影响碰撞后的物理效果。
物理材质可以模拟自然界中所有的物理碰撞后的效果,比如木头之间的碰撞或者冰块之间的碰撞。
此外,物理材质可添加在任何碰撞器中,下面我们就在“Material”中添加碰撞器的物理材质。
Unity标准资源包提供了一些物理材质的资源,我们可以将它们添加至当前工程中。
在Project视图中单击鼠标右键,以弹出的快捷菜单中选择“ImportPackage"->"PhysicMaterials”菜单项,此时即可引人物理材质的标准资源包。
标准资源包中提供了‘种常用的物理材质:
弹性材质(Bouncy)、冰材质(Tce、金属材质
(Metal),橡胶材质(Rubber)和木头材质(Wood)。
在Scene视图中选择需要添加物理材质的物体,然后在Project视图中通过拖动将Bouncy赋值给Inspector视图中的”SpliereCollider”即可。
因为Game视图中的小球对象添加了弹性材质,运行游戏后,小球将从空中自然下落,落地后感应弹性材质,然后再次弹回至空中,如此循环下去。
除了可以使用Unity标准资源包中的5款物理材质,也可以自行创建物理材质。
创建新物理材质的方法如下,在Project视图中点击“Create"->"PliysicMaterial”菜单项即可,在右侧的Inspector视图中,我们将看到新创建的物理材质的所有属性,下面简要介绍一下这些属性的含义。
DynamicFriction:
动态摩擦,取值在0到1之间。
0表示最小动态摩擦,1表示最大动态摩擦。
StaticFriction:
静态摩擦,取值在。
到1之间。
0表示最小静态摩擦,1表示最大静态摩擦。
Bounciness:
碰撞反弹系数,取值在0到1之间。
0表示碰撞无反弹,1表示碰撞最大反弹。
FrictionCombine:
普通碰撞后的摩擦模式。
BounceCombine:
反弹碰撞后的摩擦模式。
FrictionDirection2:
摩擦方向,方向分为x轴、y轴和z轴。
DynamicFriction2:
动摩擦系数,它的摩擦方向根据FrictionDirection2设定
StaticFriction2:
静摩擦系数,它的摩擦方向根据FrictionDirection2设定。
3射线
射线是3D世界中一个点一个方向发射的一条无终点的线。
在发射的轨迹中,一旦与其他的模型发生碰撞,它将停止发射。
我们可以判断某条射线是否发设置某游戏对象身上,其应用范围非常的广,如射击类游戏中发射子弹行走路径,并且通过这个路径可以判断子弹是否打中了目标物体。
3.1射线的原理
创建一个射线时,首先需要知道射线的七点和重点在3D世界坐标系中的坐标,本例创建一条从3D世界零点摄像游戏对象本身的射线。
在代码中,Debug.DrawLine()方法只有在Sceme视图中才能看到。
3.2碰撞监测
射线可用于判断与游戏对象的碰撞,如图6-19所示,本例一摄像机的位置为原点向鼠标移动点发射一条射线,好比向靶心打了一枪,这里这条射线用于判断是否打中在靶子上。
使用的Camera.main.ScreenPointToRay(Input.mousePosition)方法来创建一条有摄像机向鼠标党前位置发射的射线,然后使用Physics.Raycast()判断这条射线是否与某游戏对象相交,如果该方法返回ture则表示相交,返回false则表示未相交。
4关节
关节组件一共分为5大类,它们分别是链条的关节、固定关节、弹簧关节、角色关节和可配置关节。
下面先简要介绍一下它们的具体含义。
(1)链条关节(HingeJoint):
将两个物体一链条的形式绑在一起,当力量过大超过链条的固定力矩时,两个物体就会产生相互的拉力。
(2)固定关节(FixedJoint):
将两个物体永远以相对位置固定在一起,及时发生物理改变,它们之间的相对位置也不会发生改变。
(3)弹簧关节(SpringJoint):
将两个物体以弹簧的形式绑定在一起,挤压它们会得到想歪的推力,拉伸它们会得到两边对中间的拉力。
(4)角色关节(CharacterJoint):
它可以模拟角色的骨骼关节,就好比人的手腕一样可以大范围的任意角度旋转。
(5)可配置关节(ConfigurableJoint):
他可以模拟任意关节的效果,包括上面的4中效果,它是最强大的,也是最复杂的。
关节是一个游戏组件,它既可以使用编辑器添加也可以使用代码添加,本节先介绍使用编辑器添加的方法,在导航菜单栏中选择“Component”→“Physics”菜单项,然后从中选择一种关节组件,即可完成关节组件的添加。
5角色控制器
Unity已经帮我们实现了“上”、“下”、“左”、“右”、“跳跃”等这些相对复杂的逻辑操作,并且将它们封装成了角色控制器组件,不用编写任何代码就可以轻松控制第一人称与第三人称主角。
角色控制器组件保存在Unity标准资源包中,它的功能非常强大,可模拟第一人称或第三人称视角。
它不受刚体的限制,非常适用于表现游戏中的主角的运动。
在使用角色控制器时,首先需要将它导人当前工程,具体操作方法为在Project视图中点击鼠标右键,从弹出的快捷菜单中选择“ImportPackage”->“CharacterController”菜单项即可。
5.1第一人称
在第一人称视角游戏中,整个游戏视图好比主角的眼睛,游戏画面中的一切好像是从自己眼睛看到的一样。
第一人称视角的控制原理其实是控制Scene视图中摄像机对象的移动,所以屏幕显示的永远都是主角正前方的画面,比如经典的“cs”游戏就属于第一人称视角游戏。
将角色控制器组件导人工程后,在Project视图中找到该角色控制组件,然后将“FirstPersonController"拖动至Hierarcliy视图中即可,此时它将以一个胶囊体对象的形式出现在Scene视图中,然后使用移动工具编辑一下“胶囊”的位置。
这里值得注意的是,第一人称视角组件y轴一定要高于地面,否则运行游戏后,它将感应物理引擎坠落到地面之下。
确保无误后直接运行游戏,第一人称视角遍映人我们眼帘,在Game视图中通过键盘按键“W”、“S”、“A”、"D",“Space”可以直接控制第一人称视角的移动与跳跃。
在Hierarchy视图中选择“FirstPersonController”对象,在右侧的lnspector视图中可以看到这个对象共绑定了三条脚本。
这3个脚本全部由官方提供,"MouseLook"脚本用来控制第一人称视角如何通过鼠标来移动整个视图,"CharacterMotor”脚本用来监听键盘事件,控制主角“前”、“后”、“左”、“右”的移动,"FPSInputController”脚本用来监听特殊的“Space”按键,实现第一人称视角的跳跃功能。
三个脚本可以直接打开,所以也可在它们的基础上进行拓展,从而达到更好的控制效果。
5.2第三人称
第三人称视角的原理是:
在游戏场景中包含主角对象和摄像机对象,主角移动后,摄像机永远跟着主角移动,所以在Game视图中可以看出主角当前的移动方向。
大多数游戏都采取第三人称的方式,因为第三人称更为清晰地向玩家展示控制角色的效果。
下面将学习如何将第三人称视角添加至工程当中。
如图6-12所示,首先在Project视图中将“3rdPersonController"(第三人称控制器)拖动至Hierarchy视图中,然后在Scene视图中即可看到第三人称所用的模型对象。
在Scene视图中加人地形,并且将角色控制器放在地形之上。
运行游戏后即可看到第三人称视角的效果,用键盘的方向键控制主角移动,空格键用于控制主角跳跃。
控制主角时,摄像机永远跟在主角身后,以第三人称的视角观看着主角的运动。
5.3控制组件
角色控制器组件和刚体组件都具备物理引擎的功能,它们都需要绑定在游戏对象中才能实现物理效果,并且同一个游戏对象中两者只能存在一个。
刚体组件可以非常精确地模拟现实世界中模型的一切物理效果,而角色控制器则没有刚体那么精确,它更多地受控制器的限制,所以它更适合控制游戏对象。
举个简单的例子,给主角对象添加刚体组件作为物理引擎,控制主角向前快速移动,并且以较大力度碰撞在一面墙上。
因为刚体组件会感应完全精确的物理效果,所以力度过大时,主角会被物理引擎施加的弹力反弹回来。
因为主角虽然需要感应物理引擎的效果,但它是一个特殊的游戏对象,需要限制它的物理效果,此时就可以使用角色控制器组件来处理。
添加角色控制器之前,首先要确定是否把角色控制器标准资源包引人工程。
如果未引人,则无法添加角色控制器组件。
确保无误后,首先在Hierarchy视图中选择需要添加角色控制器的游戏对象,具体操作方法是在Unity导航菜单栏中选择“Component->“Physics->CharacterController"菜单项即可。
添加完角色控制器组件后,就需要在脚本中控制角色控制器组件。
首先创建一条游戏脚本,然后在脚本中使用方法GetComponentterController>()获取角色控制器组件对象,
接着通过调用对象的simpleMove()方法(其参数为角色移动的方向,只支持x轴与Y轴方向的移动)来移动该角色。
三、实验内容及步骤
1.熟悉刚体概念,练习使用刚体,并练习给刚体施加力。
2.熟悉碰撞器,练习给游戏对象添加碰撞器组件,并设置属性,设置材质。
在场景中添加立方体和球体:
给摄像机添加代码:
usingUnityEngine;
usingSystem.Collections;
publicclassForce:
MonoBehaviour{
GameObjectobj;
GameObjectobj2;
//Usethisforinitialization
voidStart(){
obj=GameObject.Find("Sphere");
obj2=GameObject.Find("Cube");
}
//Updateiscalledonceperframe
voidUpdate(){
}
voidOnGUI(){
if(GUILayout.Button("普通力",GUILayout.Height(50)))
{
obj.rigidbody.AddForce(10,100,10);
}
if(GUILayout.Button("位置力",GUILayout.Height(50)))
{
Vector3F=obj2.transform.position-obj.transform.position;
obj.rigidbody.AddForceAtPosition(F,obj2.transform.position,ForceMode.Impulse);
}
}
}
给立方体,球体添加刚体组件:
给立方体,球体添加碰撞器:
导入物理材质包,添加物理材质
游戏效果:
3.熟悉射线概念,练习使用射线,并实现射线碰撞。
给摄像机中绑定代码:
usingUnityEngine;
usingSystem.Collections;
publicclassRayTest:
MonoBehaviour{
//Usethisforinitialization
voidStart(){
}
//Updateiscalledonceperframe
voidUpdate()
{
if(Input.GetMouseButton(0))
{
Rayray=Camera.main.ScreenPointToRay(Input.mousePosition);//从摄像机发出到点击坐标的射线
RaycastHithitInfo;
if(Physics.Raycast(ray,outhitInfo))
{
Debug.DrawLine(ray.origin,hitInfo.point);//划出射线,只有在scene视图中才能看到
GameObjectgameObj=hitInfo.collider.gameObject;
Debug.Log("clickobjectnameis"+gameObj.name);
if(gameObj.tag=="cube")//当射线碰撞目标为boot类型的物品,执行拾取操作
{
Debug.Log("pickup!
");
}
}
}
}
}
游戏效果:
4.熟悉关节,并练习使用各种关节。
添加立方体和球体,给球体添加代码:
usingUnityEngine;
usingSystem.Collections;
publicclassjoint:
MonoBehaviour
{
//链接关节游戏对象
GameObjectconnectedObj=null;
//当前链接的关节组件
ComponentjointComponent=null;
voidStart()
{
//获得链接关节的游戏对象
connectedObj=GameObject.Find("Cube");
}
voidOnGUI()
{
if(GUILayout.Button("添加链条关节"))
{
ResetJoint();
jointComponent=gameObject.AddComponent("HingeJoint");
HingeJointhjoint=(HingeJoint)jointComponent;
connectedObj.rigidbody.useGravity=true;
hjoint.connectedBody=connectedObj.rigidbody;
}
if(GUILayout.Button("添加固定关节"))
{
ResetJoint();
jointComponent=gameObject.AddComponent("FixedJoint");
FixedJointfjoint=(FixedJoint)jointComponent;
connectedObj.rigidbody.useGravity=true;
fjoint.connectedBody=connectedObj.rigidbody;
}
if(GUILayout.Button("添加弹簧关节"))
{
ResetJoint();
jointComponent=gameObject.AddComponent("SpringJoint");
SpringJointsjoint=(SpringJoint)jointComponent;
connectedObj.rigidbody.useGravity=true;
sjoint.connectedBody=connectedObj.rigidbody;
}
if(GUILayout.Button("添加角色关节"))
{
ResetJoint();
jointComponent=gameObject.AddComponent("CharacterJoint");
CharacterJointcjoint=(CharacterJoint)jointComponent;
connectedObj.rigidbody.useGravity=true;
cjoint.connectedBody=connectedObj.rigidbody;
}
if(GUILayout.Button("添加可配置关节"))
{
ResetJoint();
jointComponent=gameObject.AddComponent("ConfigurableJoint");
ConfigurableJointcojoint=(ConfigurableJoint)jointComponent;
connectedObj.rigidbody.useGravity=true;
cojoint.connectedBody=connectedObj.rigidbody;
}
}
//重置关节
voidResetJoint(){
//销毁之前添加的关节组件
Destroy(jointComponent);
//重置对象位置
this.transform.position=newVector3(332f,90f,-770f);
connectedObj.gameObject.transform.position=newVector3(335f,82f,-770f);
//不敢应重力
connectedObj.rigidbody.useGravity=false;
}
}
游戏效果:
5.熟悉角色控制器,练习使用第一人称角色控制器,练习使用第三人称角色控制器。
第一人物控制器:
可以通过鼠标调整视角,键盘控制运动
第三人物控制器:
键盘控制运动
四、实验仪器与