下面我们通过一个具体的实例来了解如何使用物理引擎,该实例通过第三人称视角控制游戏中的小球对象,游戏通过是否与钻石碰撞来界定是否寻找到钻石并获得积分,获得积分满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);
- }
- }
点击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);
- }
- }
接下来,我们创建一个平面,依次打开菜单栏GameObject->Create Other->Cune,命名为GameOverTrigger,该对象用于判断小球是否与其碰撞,如果是,表示小球冲出了跑道,游戏失败,我们设置Transform组件属性,Position(90,40,55),Rotation(0,0,0),Scale(165,1,118),如下图:
勾选Box Collider下的Is Trigger复选框,并取消勾选Mesh Renderer组件,创建一个c#脚本,叫GameOverTrigger.cs,代码如下:
- using UnityEngine;
- using System.Collections;
- public class GameOverTrigger : MonoBehaviour {
- void OnTriggerEnter()
- {
- Debug.Log("over");
- }
- }
把脚本绑定到GameOverTrigger对象上,预览游戏,当小球冲出跑道后,我们打印over字样。接下来我们在新建一个脚本,叫CrayBallManager.cs,用来处理一些输赢得分之类的逻辑,代码如下:
- 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;
- }
- }
- {
- //判断小球是否与钻石对象碰撞
- 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);
- }
- }