下面我们通过一个具体的实例来了解如何使用物理引擎,该实例通过第三人称视角控制游戏中的小球对象,游戏通过是否与钻石碰撞来界定是否寻找到钻石并获得积分,获得积分满10分后,赢得游戏,当小球冲出跑道时,游戏失败,并提示是否重新开始游戏。


unity 圆形无限滚动列表插件 unity3d滚动小球_System

依次打开文件夹Assets-》object,在object文件夹下找到Runway.fbx文件,拖进场景中,如下图:


unity 圆形无限滚动列表插件 unity3d滚动小球_Time_02

选择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),如下图:


unity 圆形无限滚动列表插件 unity3d滚动小球_unity 圆形无限滚动列表插件_03

然后下面我们添加一个平行光源,依次打开菜单栏中的GameObject->Create Other->Directional light,修改该对象的Transform组件的Position(87,57,58),Rotation(48,-29,1),Scale(1,1,1),如下图:


unity 圆形无限滚动列表插件 unity3d滚动小球_System_04

然后我们添加一个球体,依次打开菜单栏GameObject->Create Other->Sphere,并命名为Ball,设置它的position(84,50,48),Rotation(0,0,0),Scale(1,1,1),然后打开菜单栏Component->Physics->Rigidbody,给Ball对象添加刚体组件,如下图:


unity 圆形无限滚动列表插件 unity3d滚动小球_Time_05

下面给小球添加材质文件,如下图:


unity 圆形无限滚动列表插件 unity3d滚动小球_System_06

现在小球无法移动,所以我们得给小球绑定一个脚本,新建一个文件夹,命名为Scripts,在Scripts文件夹里新建一个C#文件,并命名为BallControl.cs,代码如下:

1. using UnityEngine;  
2. using System.Collections;  
3.   
4. public class BallControl : MonoBehaviour {  
5.   
6. //小球运动的速率  
7. public float movementSpeed=6.0f;   
8. //小球的水平运动  
9. private Vector3 horizontalMovement;  
10. //小球的前后运动  
11. private Vector3 verticalMovement;  
12.   
13.   
14. // Use this for initialization  
15. void Start ()  
16.     {  
17.   
18.   
19.   
20.   
21.       
22.     }  
23.       
24. // Update is called once per frame  
25. void Update ()   
26.     {  
27.   
28. //Vector3.right x zhou  
29. "Horizontal")*Vector3.right*movementSpeed;  
30.           
31. //z zhou  
32. "Vertical")*Vector3.forward*movementSpeed;  
33.           
34. //小球的运动  
35.         Vector3 movement=horizontalMovement+verticalMovement;  
36.           
37. //为小球施加力  
38.         rigidbody.AddForce(movement,ForceMode.Force);  
39.   
40.       
41.     }  
42. }


然后绑定到Ball对象上,如下图:


unity 圆形无限滚动列表插件 unity3d滚动小球_Time_07


点击Play按钮,我们发现可以用键盘控制小球移动了,如下图:

unity 圆形无限滚动列表插件 unity3d滚动小球_Time_08

下面我们添加钻石游戏对象,将Gem.fbx文件拖进场景中,复制10个这样的对象,然后依次命名Gem1--Gem10,依次打开菜单栏创建一个空游戏对象,命名Gems,然后把Gem1-10都拖进Gems对象中,如下图:


unity 圆形无限滚动列表插件 unity3d滚动小球_菜单栏_09

依次设置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对象,设好后如下图:


unity 圆形无限滚动列表插件 unity3d滚动小球_菜单栏_10

我们修改下BallControl.cs脚本,当小球与钻石碰撞时,让钻石消失,添加代码如下:

1. void OnTriggerEnter(Collider other)  
2.     {  
3. //判断小球是否与钻石对象碰撞  
4. if (other.tag == "Pickup")  
5.         {  
6.                   
7. //销毁对象  
8.             Destroy(other.gameObject);  
9.           
10.           
11.           
12.           
13.         }  
14.   
15.   
16.   
17.   
18.     }



接下来,我们创建一个平面,依次打开菜单栏GameObject->Create Other->Cune,命名为GameOverTrigger,该对象用于判断小球是否与其碰撞,如果是,表示小球冲出了跑道,游戏失败,我们设置Transform组件属性,Position(90,40,55),Rotation(0,0,0),Scale(165,1,118),如下图:


unity 圆形无限滚动列表插件 unity3d滚动小球_unity 圆形无限滚动列表插件_11

勾选Box Collider下的Is Trigger复选框,并取消勾选Mesh Renderer组件,创建一个c#脚本,叫GameOverTrigger.cs,代码如下:



1. using UnityEngine;  
2. using System.Collections;  
3.   
4. public class GameOverTrigger : MonoBehaviour {  
5.   
6. void OnTriggerEnter()  
7.     {  
8.           
9.   
10. "over");  
11.     }  
12. }


把脚本绑定到GameOverTrigger对象上,预览游戏,当小球冲出跑道后,我们打印over字样。接下来我们在新建一个脚本,叫CrayBallManager.cs,用来处理一些输赢得分之类的逻辑,代码如下:

    1. using UnityEngine;  
    2. using System.Collections;  
    3.   
    4. //枚举  
    5. public enum CrazyBallState { playing, won, lost };  
    6.   
    7. public class CrazyBallManager : MonoBehaviour  
    8. {     
    9.   
    10. //单例  
    11. public static CrazyBallManager CB;  
    12.   
    13. //按钮  
    14. public GUIStyle buttonStyle;  
    15.   
    16. //标签  
    17. public GUIStyle labelStyle;  
    18.   
    19. //钻石总共的数量  
    20. private int totalGems;  
    21.   
    22. //找到钻石的数量  
    23. private int foundGems;  
    24.   
    25. //游戏的状态  
    26. private CrazyBallState gameSate;  
    27.   
    28. void Awake()  
    29.     {  
    30.   
    31.   
    32. this;  
    33.         foundGems = 0;  
    34.         gameSate = CrazyBallState.playing;  
    35.   
    36. "Pickup").Length;  
    37.   
    38. //开始游戏  
    39.         Time.timeScale = 1.0;  
    40.   
    41.     }  
    42.   
    43.   
    44. void OnGUI()  
    45.     {  
    46.   
    47.   
    48.         GUI.skin.label = labelStyle;  
    49.   
    50.         GUI.skin.button = buttonStyle;  
    51.   
    52. //显示找到的钻石数量  
    53. "Found gems:"+foundGems+"/"+totalGems);  
    54.   
    55. if (gameSate == CrazyBallState.lost)  
    56.         {  
    57.           
    58. //提示游戏失败  
    59. "You Lost");  
    60.   
    61. if(GUI.Button(new Rect(Screen.width/2,Screen.height/2,113,84),"Play again"))  
    62.             {  
    63.   
    64. //重新加载场景  
    65.                 Application.LoadLevel(Application.loadedLevel);  
    66.   
    67.   
    68.             }  
    69.   
    70.   
    71.         }  
    72. else if(gameSate==CrazyBallState.won)  
    73.         {  
    74. "You won");  
    75.   
    76.   
    77. if(GUI.Button(new Rect(Screen.width/2,Screen.height/2,113,84),"Play again"))  
    78.             {  
    79.                   
    80. //重新加载场景  
    81.                 Application.LoadLevel(Application.loadedLevel);  
    82.                   
    83.                   
    84.             }  
    85.   
    86.         }  
    87.   
    88.     }  
    89.   
    90.   
    91. public void FoundGem()  
    92.     {  
    93.   
    94.   
    95.         foundGems++;  
    96. if(foundGems>=totalGems)  
    97.         {  
    98.   
    99.   
    100.             WonGame();  
    101.   
    102.   
    103.         }  
    104.   
    105.   
    106.   
    107.     }  
    108.   
    109.   
    110. public void WonGame()  
    111.     {  
    112.   
    113. //暂停游戏  
    114.         Time.timeScale = 0.0;  
    115.   
    116.   
    117.         gameSate = CrazyBallState.won;  
    118.   
    119.     }  
    120.   
    121. public void SetGameOver()  
    122.     {  
    123.   
    124. //暂停游戏  
    125.         Time.timeScale = 0.0;  
    126.   
    127.         gameSate = CrazyBallState.lost;  
    128.   
    129.     }  
    130.   
    131.   
    132. }


    CrayBallManager脚本文件中,每调用一次FoundGem()函数,对FoundGems变量累加一次,所以我们在BallControl.cs中修改如下代码:



    1. {  
    2. //判断小球是否与钻石对象碰撞  
    3. if (other.tag == "Pickup")  
    4.         {  
    5.                   
    6.   
    7.             CrazyBallManager.CB.FoundGem();  
    8.   
    9. //销毁对象  
    10.             Destroy(other.gameObject);  
    11.           
    12.           
    13.           
    14.           
    15.         }  
    16.   
    17.   
    18.   
    19.   
    20.     }


    GameOverTrigger.cs修改如下:


    1. void OnTriggerEnter()  
    2.    {  
    3.          
    4.   
    5.     CrazyBallManager.CB.SetGameOver ();  
    6. //


    将CrayBallManager.cs脚本绑定到Main Camera对象上,然后我们单击Main Camera对象,单击ButtonStyle属性,设置Background属性,放入一张图片,设置FontSize为18,Alignment为Middle Center,设置Fixed Width为113,Height为84,如下图:


    unity 圆形无限滚动列表插件 unity3d滚动小球_System_12

    运行游戏,如下图:


    unity 圆形无限滚动列表插件 unity3d滚动小球_菜单栏_13

    游戏中的摄像机并没有跟随小球,造成了游戏难以操作的现象,所以我新建一个脚本,叫BallCamera.cs,代码如下:


    1. using UnityEngine;  
    2. using System.Collections;  
    3.   
    4. public class BallCamera : MonoBehaviour  
    5. {  
    6. //跟随的目标物体  
    7. public Transform target;  
    8. //与目标物体的相对高度  
    9. public float relativeHeigth = 10.0f;  
    10. //与目标物体的相对距离  
    11. public float zDistance = 5.0f;  
    12. //阻尼速度  
    13. public float dampSpeed = 2;  
    14.   
    15. void Update()  
    16.     {  
    17.   
    18. new Vector3(0, relativeHeigth, -zDistance);  
    19. //像弹簧一样跟随目标物体  
    20.         transform.position = Vector3.Lerp(transform.position, newPos, Time.deltaTime * dampSpeed);  
    21.     }  
    22. }


    绑定到Main Camera对象上,target为ball对象,运行游戏,如下图:


    unity 圆形无限滚动列表插件 unity3d滚动小球_unity 圆形无限滚动列表插件_14


    unity 圆形无限滚动列表插件 unity3d滚动小球_Time_15