使用Unity3D Physics来工作

来源:互联网 发布:ea凝胶骗局知乎 编辑:程序博客网 时间:2024/06/07 00:19

这个教程将教你如何用Unity3D构建一个小球击倒柴火堆的游戏!在这个过程中,你将了解到关于使用物理引擎的重要性和你这么做后可以减少无数小时的手工动画的时间。继续阅读!


有什么完整的现代游戏引擎会缺少物理引擎呢?每一个当前的游戏引擎,不管它是3D的还是2D的,都有一个某种类型的物理库,Unity也不例外。想要在你的游戏里,用实时的物理来模拟复杂对象之间的交互是很理想的。一个物理引擎可以减少大量手工编码和动画来达到逼真的行动,能轻易的进行碰撞检测,并且能快速的引进一系列新的游戏机制到你的游戏里。

在本教程中,我们将使用Unity的物理引擎来构建一个3D的类似BoomBlox和愤怒小鸟一样类型的击倒类游戏。我们将学习到如何给对象不同的物理属性,使它们能够互相碰撞,并且甚至当碰撞过于猛烈的时候允许他们被摧毁。




什么是物理引擎?

一个物理引擎的工作是模拟当有外力作用到对象上时他们间相互反应。这些外力可以是常数,像重力或者一辆车的动力,也可以是其他短暂并且强大的,像爆炸。一个物理模拟有时被称作“SendBox(沙盒)”,因为仅仅只有在模拟之中的对象才受到挤压。事实上,不是所有的对象在你的游戏里都需要一部分的模拟。这很重要,因为玩家的动作常常不切实际却还要反应现实的碰撞。

项目设置
-点击文件>新项目
-浏览到一个合适的文件夹并且命名项目为CannonBowl
-点击创建
-点击gameobjects>创建其他>方向光源
-点击文件>保存场景
-命名场景为Main
-点击保存

Colliders(碰撞器)

碰撞器是物理引擎用来执行碰撞检测的。与网格对象不同,当他们互相接触的时候他们自己知道。他们是简单形状,像方块、球形或者胶囊形,分配你的gameobjects并且跟随他们周围。你可以将它们想象成类似“力场”的东东。

方便的是,每当一个gameobjects被创建,它会自动分配一个合适的碰撞器。一个立方体会得到一个BoxCollider(立方体碰撞器),一个球体会得到一个SphereCollider(球体碰撞器),一个圆筒会得到一个CapsuleCollider(柱体碰撞器),等等。




最后,我们将需要一些积木去被击倒:

-点击gameobjects>创建其他>立方体
-重命名立方体为WoodBlock
-设置积木的位置为 0,0,0。这将会把积木放置在世界的中心
-下载Wood.jpg
-拖动Wood.jpg进入你的项目面板去将它变为纹理
-拖动木头纹理到场景中的积木上,这将为我们自动生成木头材料并且应用到积木上
-从层级面板上拖动积木到项目面板将其转化为预制件(应该就是组件吧)

如果我们按下运行,积木啥事都不会干。虽然它有一个碰撞器,但是它缺乏一个刚体,所以它不受任何物理力的效果。

Rigidbodies(刚体)

在一个物理引擎中,刚体是最关键的元素。它在物理模拟中附加在任意一个gameobjects上。

-在项目面板上选择积木组件
-点击组件>物理>刚体




默认情况下,一个刚体受到重力和空气阻力的影响,也是众所周知的阻力。如果我们按下播放,积木将开始掉落,加速,并且当重力和阻力平衡后达到最终速度。

Build a Structure(构建一个结构)

我们将需要创建更多元素为了来构建一个适当的水平。首先,当我们增加一些让积木能放在地面上的土地。

-点击gameobjects>创建其他>平面
-重命名片面为Ground
-设置Ground的位置为0,0,0
-下载Grass.jpg
-拖动Grass.jpg进入你的项目面板制造一个纹理
-将草地纹理拖入到场景上地面上

地面将自动被给定一个网格碰撞器,这将阻止任何的刚体穿过它。按下播放,积木就该掉下来,并且停在地面上。



现在,我们需要一个结构去击倒(囧啊,这句翻译的真坑爹)。选择积木并且按下Ctrl+d(在windows下)或者Cmd+d(在osx上),复制积木几次。使用缩放和移动工具,拉伸并且放置积木在如下图所示的地方。




注意:使用精确的数字来转换是一个好主意。积木应该互相依靠在一起,但是没有重叠。重叠将导致物理引擎崩溃并且做出不可预料的事情来。

Camera Controls(摄像机控制器)

现在,我们已经创建了我们的美丽的结构,让我们来写一段脚本,它将允许我们移动摄像机,让我们能像上帝一样从任意角度欣赏赞美咱自己创建的的东东(同样囧,这翻译的...)

-点击资源>创建>C#脚本
-重命名脚本为Cannon(因为最后我们的摄像机将做些事)
-拖动脚本到主摄像机上
-双击脚本编辑它

接下来的脚本将使得摄像机绕着世界中心盘旋,而且在这过程中还不断的上上下下。


public class Cannon : MonoBehaviour {
  void LateUpdate() {
    float x = Input.GetAxis("Mouse X") * 2;
    float y = -Input.GetAxis("Mouse Y");

    // vertical tilting
    float yClamped = transform.eulerAngles.x + y;
    transform.rotation = Quaternion.Euler(yClamped, transform.eulerAngles.y, transform.eulerAngles.z);

    // horizontal orbiting
    transform.RotateAround(new Vector3(0, 3, 0), Vector3.up, x);
  }
}


在最后阶段,让我们做一个十字准星到我们的摄像机上,这样可以更简单的对准目标:
-点击gameobjects>创建>平面
-重命名平面为Crosshair
-设置Crosshair的位置到0,0,0
-下载Crosshair.png
-拖动Crosshair.png进入项目面板
-拖动Crosshair纹理到场景面板中的Crosshair平面上
-在检测中,右键点击网格碰撞器组件并且移除它以便它在场景中不再影响到其他物理对象




Shooting Cannonballs(发射加农炮)

应该能看到我们的结构已经好了,但是这是假定在物理上!我们需要一种方法击倒它来看看物理效果。我们需要发射!


【此处本来有个swf,但是这个swf好像链接不到。。。】

-点击gameobjects>创建其他>球体
-重命名球体为Cannonball
-设置Cannonball的位置为0,0,0
-当选中Cannonball,点击组件>物理>刚体
-将Cannonball从层次面板中拖到项目面板,把它变成一个预制组件


public class Cannon : MonoBehaviour {
  public GameObject projectilePrefab;



因为我们要从摄像机上直接发射炮弹,我们能编辑我们已经存在的Cannon脚本。首先我们增加一些公共属性在我们预制好了的类的顶部。


void FixedUpdate () {
  if (Input.GetButtonDown("Fire1")) {
    GameObject projectile = Instantiate(projectilePrefab, transform.position, transform.rotation) as GameObject;
    projectile.rigidbody.AddRelativeForce(new Vector3(0, 0, 2000));
  }
}



Boundaries(边界)

你可能已经注意到,如果一个炮弹被发射的足够远,它会从地面的边缘掉落下去。这个炮弹将继续存在,只要游戏继续运行并且它的物理状态将继续被计算,最终将一切都拖慢。我们需要创建一个边界,并且销毁一切离开这个边界的任何gameobjects。

-点击gameobjects>创建空
-重命名它为Boundary
-设置Boundary的x,y和z的位置为0
-当Boundary被选中,点击组件>物理>盒子碰撞器
-在检测中,确保是触发的。
-设置盒子碰撞器的中心为0,25,0
-设置盒子碰撞器的大小为50,50,50




现在,我们需要创建脚本来销毁那些离开边界的对象了。

-点击资源>创建>C#脚本
-重命名脚本为Boundary
-将脚本拖动到层级面板中的Boundary对象上
-编辑脚本并且增加以下代码


public class Boundary : MonoBehaviour {
  void OnTriggerExit(Collider other) {
    Destroy(other.gameObject);
  }
}



Causing Destruction(造成破坏)

我们需要一种方法来赢得当前关卡,如果我们的积木受到足够的冲击,它们将被摧毁。

-点击资源>创建>C#脚本
-重命名脚本为Block
-拖动脚本到项目面板中的Block组件上
-双击项目面板中的脚本来编辑它

在这个脚本中,我们给组件一个公共生命属性让它可以在编辑器中被调整。这允许不同的积木有不同数额的生命。


public class Block : MonoBehaviour {
  public float health = 20;



当碰撞被检测到,冲击的数值将被算出。更大的撞击将造成更大的伤害。任何超过轻轻一击的碰撞都要减去积木的生命值。如果积木的生命值降到了0以下,那么这个积木就会被销毁。然后检测看看有多少个其他的积木留在场景中。如果仅仅只有一个积木被销毁(这句很奇怪,看代码应该是全部的积木都被销毁才对),那么游戏结束,并且它将被重新加载到场景上,重玩一次。


void OnCollisionEnter(Collision collision) {
  // apply collision damage
  if (collision.relativeVelocity.magnitude > 0.5) {
    health -= collision.relativeVelocity.magnitude;
  }

  // destroy if health is too low
  if (health <= 0) {
    Destroy(gameObject);

    // restart the scene if this was the last box
    GameObject[] boxes = GameObject.FindGameObjectsWithTag("Box");
    if (boxes.Length <= 1) {
        Application.LoadLevel("Main");
    }
  }
}



Concrete Blocks(混凝土砖)

到现在为止,我们只是用了木头积木。他们轻并且相对较弱,使得结构很容易被破坏并且显而易见的它将会被怎么被移动。我们需要创建另一种积木,一种既沉重并且强壮的积木。

-在项目面板中,复制木头积木组件(Ctrl+d在windows中,Cmd+d在Osx中)
-重命名复制的积木为ConcreteBlock
-下载Concrete.jpg
-拖动Concrete.jpg进入项目面板
-拖动混凝土纹理到项目面板中的ConcreteBlock组件上
-当组件被选中,使用检测器更新它的生命值到50
-在刚体组件中,增加Mass到5使得它更重
-拖动混凝土积木组件进场景

尝试用混凝土积木重新摆放一些交叉的积木。混凝土积木将更难的被撞击击倒、掉落,并且更难被炮弹摧毁。




Finished Game(完成游戏)

下面是运行在Web播放器中的完成的游戏。使用鼠标对摄像机轨道上的物体按下Ctrl或者鼠标左键射击。


[u3d=600,400]http://tuts-authors.s3.amazonaws.com/mobile.tutsplus.com/Ian Zamojc/2012/08/07/WebPlayer.unity3d[/u3d]

总结

本教程仅仅只是粘到了U3D物理引擎能做的一点点边。恒力,爆炸力,物理材料,铰链,弹簧,布偶等。虽然这看起来可能很可怕,Unity物理引擎的元素都组合在一起,使它容易理解并容易在你的游戏中实现物理效果。