下面我们通过一个具体的实例来了解如何使用物理引擎,该实例通过第三人称视角控制游戏中的小球对象,游戏通过是否与钻石碰撞来界定是否寻找到钻石并获得积分,获得积分满10分后,赢得游戏,当小球冲出跑道时,游戏失败,并提示是否重新开始游戏。
依次打开文件夹Assets-》object,在object文件夹下找到Runway.fbx文件,拖进场景中,如下图:
选择Runway游戏对象,修改Transform组件的Position(88,48.5,57),Rotation(270,350,0),Scale(1,1,1),然后选择Main Camera对象,修改Transform组件的Position(88,60,45),Rotation(55,0,0),Scale(1,1,1),如下图:
然后下面我们添加一个平行光源,依次打开菜单栏中的GameObject->Create Other->Directional light,修改该对象的Transform组件的Position(87,57,58),Rotation(48,-29,1),Scale(1,1,1),如下图:
然后我们添加一个球体,依次打开菜单栏GameObject->Create Other->Sphere,并命名为Ball,设置它的position(84,50,48),Rotation(0,0,0),Scale(1,1,1),然后打开菜单栏Component->Physics->Rigidbody,给Ball对象添加刚体组件,如下图:
下面给小球添加材质文件,如下图:
现在小球无法移动,所以我们得给小球绑定一个脚本,新建一个文件夹,命名为Scripts,在Scripts文件夹里新建一个C#文件,并命名为BallControl.cs,代码如下:
using UnityEngine; using System.Collections; public class BallControl : MonoBehaviour { //小球运动的速率 public float movementSpeed=6.0f; //小球的水平运动 private Vector3 horizontalMovement; //小球的前后运动 private Vector3 verticalMovement; // Use this for initialization void Start () { } // Update is called once per frame void Update () { //Vector3.right x zhou horizontalMovement=Input.GetAxis("Horizontal")*Vector3.right*movementSpeed; //z zhou verticalMovement=Input.GetAxis("Vertical")*Vector3.forward*movementSpeed; //小球的运动 Vector3 movement=horizontalMovement+verticalMovement; //为小球施加力 rigidbody.AddForce(movement,ForceMode.Force); } }然后绑定到Ball对象上,如下图:
点击Play按钮,我们发现可以用键盘控制小球移动了,如下图:
下面我们添加钻石游戏对象,将Gem.fbx文件拖进场景中,复制10个这样的对象,然后依次命名Gem1--Gem10,依次打开菜单栏创建一个空游戏对象,命名Gems,然后把Gem1-10都拖进Gems对象中,如下图:
依次设置Gem1-Gem10对象的Transform组件属性,Gem1的Position(78,50,55),Rotation(-90,0,0),Scale(0.27,0.27,0.27),并再Mesh Collider组件下勾选Is Trigger,设置tag为Pickup,依次设置剩下的gem对象,设好后如下图:
我们修改下BallControl.cs脚本,当小球与钻石碰撞时,让钻石消失,添加代码如下:
void OnTriggerEnter(Collider other) { //判断小球是否与钻石对象碰撞 if (other.tag == "Pickup") { //销毁对象 Destroy(other.gameObject); } }
勾选Box Collider下的Is Trigger复选框,并取消勾选Mesh Renderer组件,创建一个c#脚本,叫GameOverTrigger.cs,代码如下:
using UnityEngine; using System.Collections; public class GameOverTrigger : MonoBehaviour { void OnTriggerEnter() { Debug.Log("over"); } }
using UnityEngine; using System.Collections; //枚举 public enum CrazyBallState { playing, won, lost }; public class CrazyBallManager : MonoBehaviour { //单例 public static CrazyBallManager CB; //按钮 public GUIStyle buttonStyle; //标签 public GUIStyle labelStyle; //钻石总共的数量 private int totalGems; //找到钻石的数量 private int foundGems; //游戏的状态 private CrazyBallState gameSate; void Awake() { CB = this; foundGems = 0; gameSate = CrazyBallState.playing; totalGems = GameObject.FindGameObjectsWithTag ("Pickup").Length; //开始游戏 Time.timeScale = 1.0; } void OnGUI() { GUI.skin.label = labelStyle; GUI.skin.button = buttonStyle; //显示找到的钻石数量 GUILayout.Label ("Found gems:"+foundGems+"/"+totalGems); if (gameSate == CrazyBallState.lost) { //提示游戏失败 GUILayout.Label("You Lost"); if(GUI.Button(new Rect(Screen.width/2,Screen.height/2,113,84),"Play again")) { //重新加载场景 Application.LoadLevel(Application.loadedLevel); } } else if(gameSate==CrazyBallState.won) { GUILayout.Label("You won"); if(GUI.Button(new Rect(Screen.width/2,Screen.height/2,113,84),"Play again")) { //重新加载场景 Application.LoadLevel(Application.loadedLevel); } } } public void FoundGem() { foundGems++; if(foundGems>=totalGems) { WonGame(); } } public void WonGame() { //暂停游戏 Time.timeScale = 0.0; gameSate = CrazyBallState.won; } public void SetGameOver() { //暂停游戏 Time.timeScale = 0.0; gameSate = CrazyBallState.lost; } }CrayBallManager脚本文件中,每调用一次FoundGem()函数,对FoundGems变量累加一次,所以我们在BallControl.cs中修改如下代码:
{ //判断小球是否与钻石对象碰撞 if (other.tag == "Pickup") { CrazyBallManager.CB.FoundGem(); //销毁对象 Destroy(other.gameObject); } }
GameOverTrigger.cs修改如下:
void OnTriggerEnter() { CrazyBallManager.CB.SetGameOver (); //将CrayBallManager.cs脚本绑定到Main Camera对象上,然后我们单击Main Camera对象,单击ButtonStyle属性,设置Background属性,放入一张图片,设置FontSize为18,Alignment为Middle Center,设置Fixed Width为113,Height为84,如下图:
运行游戏,如下图:
游戏中的摄像机并没有跟随小球,造成了游戏难以操作的现象,所以我新建一个脚本,叫BallCamera.cs,代码如下:
using UnityEngine; using System.Collections; public class BallCamera : MonoBehaviour { //跟随的目标物体 public Transform target; //与目标物体的相对高度 public float relativeHeigth = 10.0f; //与目标物体的相对距离 public float zDistance = 5.0f; //阻尼速度 public float dampSpeed = 2; void Update() { Vector3 newPos = target.position + new Vector3(0, relativeHeigth, -zDistance); //像弹簧一样跟随目标物体 transform.position = Vector3.Lerp(transform.position, newPos, Time.deltaTime * dampSpeed); } }绑定到Main Camera对象上,target为ball对象,运行游戏,如下图: