实例:星际航行游戏
一、整体结构说明
Unity3d创建工程与场景。
我们玩过的各种游戏,都是一个个的应用程序。而这个应用程序在创建初期叫做工程项目,我们都知道游戏中有许多关卡,而在创建初期他们叫做场景。所以,Unity3d创建游戏就是创建工程项目,而一个项目下有许多的场景。
1、基本功能介绍
(1)键盘控制飞船移动
(2)发射子弹射击目标
(3)随机生成大量障碍物(小行星)
(4)计分
(5)实现游戏对象的生命周期管理
2、涉及的方法
(1)场景元素的编辑
(2)脚本文件的创建
(3)GUI(图形用户界面)的处理
(4)音频文件的添加
3、8个对象
在软件界面中,显示五个视图:Hierarchy Project Inspector Scene Game。
其中,Hierarchy视图首先自动生成Untitled工程项目,下辖自动生成两个对象:Main Camera Directional Light。
后更改当前的场景文件名,改为Main,在Main场景中除了下辖自动生成两个对象:Main Camera Directional Light。还需创建6个对象,分别为:Player,Background,Boundary,GameController,Canvas,StarField.
4、8个资源文件
Project视图下,Project/Assets中:_Scene,_Scripts,Audio,Done,Materials,Models,Prefabs,Textures。
Assets资源文件中可以包含多个_Scene,如arincar_real项目文件。
5、Inspector视图中常显2个组件:
几乎新建一个游戏对象GameObject,就有2个附带的组件:Transform,Mesh Renderer.
6、本MySpaceShooter中应用的:
(1)脚本组件(Script):PlayerController.cs,DestroyBoundary.cs,DestroyByContact.cs,DestroyByTime.cs,GameController.cs,Mover.cs,RandomRotator.cs。
(2)预设体(Prefabs):Asteroid,Bolt,explosion_asteroid,explosion_player。这几个不在Hierarchy视图中出现,并被拖到Inspector视图组件变量中。
(3)模型(Models):prop_asteroid_01,vehicle_playerShip,vehicle_playerShip_colider。
(4)材质(Materials):fx_bolt_orange,vehicle_playerShip_glass_mat,vehicle_playerShip_metal_mat。
(5)纹理(Textures):tile_nebula_green_dff。
(6)音频(Audio):explosion_asteroid,explosion_player,music_background,weapon_player。
(7)场景文件(Scene):Main。
7、说明6中的各种资源,包括模型,纹理,音频等,全部都由Unity Projects Space Shooter.unitypackage资源包提供的。我们只需要根据自己的设计需求添加拖动他们。
8、在Inspector中添加的组件时,有时添加某个组件,其瞎下的列表变量属性都会罗列出来,这是根据资源包自动提供的。但是,有时该组件并没有自动出现有些变量属性,这时需要在脚本语言中创建并赋给这个组件,方才才在组件下更新出现创建的变量属性。如:拖动explosion_player文件到变量playerExplosion中;无法拖动explosion_astteroid文件到变量explosion中。这两个文件都是在脚本中创建的。
9、在Hierarchy(层次视图)中,大部分对象都会带有Script脚本组件,在Inspector中是常显的。而预设体Prefab中,应用到的预设体也带有Script脚本组件,但是是隐藏的,没有应用到的预设体不带Script脚本组件。
如:(1)Player对象中带有的预设体Bolt,带有Mover脚本。(2)GameController对象中带有的预设体Asteroid,带有DestroyByContact,Mover,RandomRotator脚本。(3)隐藏的预设体explosion_asteroid,explosion_player均带DestroyByTime脚本。
10、在对象的Inspector中,其脚本下列的变量需要预设体,就直接从Assets/Frefabs中拖过来。如:(1)Player对象中PlayerController.cs脚本下预设体Bolt。(2)GameController对象中GameController.cs脚本下预设体Asteroid。
所以,要么预设体的组件中带有脚本语言;要么脚本语言辖下的变量需要预设体。9和10正好说明了这一切。
二、MySpaceShooter脚本实现过程详解
1、新建文件夹,桌面文件MySpaceShooter9.9来存储即将新建的Unity3D工程。
2、打开Unity3D软件界面,New新建,Unity3D工程命名MySpaceShooter,存储位置选择桌面文件MySpaceShooter9.9,选择3D,点击Create Project。(5个步骤)
3、新建MySpaceShooter工程文件介绍。在桌面MySpaceShooter9.9\ MySpaceShooter中,首先自动生成4个文件夹:Assets Library ProjectSettings Temp,其中Assets文件夹为空,其他Library、ProjectSettings、Temp 3个文件里面生成有各种不同的子文件。
4、新生成Unity3D工程 MySpaceShooter软件界面介绍。在软件界面中,显示五个视图:Hierarchy Project Inspector Scene Game。
其中,Hierarchy视图首先自动生成Untitled工程项目,下辖自动生成两个对象:Main Camera Directional Light。 Project视图中,分为(1)Favorites,下辖自动包含有:All Materials All Models All Prefabs All Scripts (2)Assets,里面为空。
5、Unity3D软件界面中,顶部的Unity-Untitled xxx是Unity 工程项目标题。MySpaceShooter正是创建的工程项目名,后面的PC, Mac & Linux Standalone 是游戏开发平台。
6、插播一条局外知识:Unity3d创建工程与场景。
我们玩过的各种游戏,都是一个个的应用程序。而这个应用程序在创建初期叫做工程项目,我们都知道游戏中有许多关卡,而在创建初期他们叫做场景。所以,Unity3d创建游戏就是创建工程项目,而一个项目下有许多的场景。
在飞船MySpaceShooter工程项目中,立方体图标+ Untitled表示场景文件,场景文件名为Untitled,后期可以Save Scene,保存默认场景文件名为Main。而此时,顶部的Untitled将变为Main.unity。
7、导入资源包,按照正常步骤导入Unity Projects Space Shooter.unitypackage资源包,此时Console会出现异常报错,这是因为导入的资源包中已经包含了一个完整的Done_Main场景,并可以正常运行。我们为了制作飞船游戏,将重新创建一个新的空场景文件Main。
8、创建一个新的场景,File-New Scene,默认生成的就是Untitled场景文件,文件名为Untitled。Save Scene,改名为Main,再在Assets下新建一个文件_Scene,将场景文件Main拖给它。
9、按要求,创建游戏窗口400X600。
10、按照文档pdf认真一个个执行下来。到了键盘控制飞船移动。
键盘控制飞船移动,PlayerController.cs中,
重载时间函数
void FixedUpdate ()
{
float moveHorizontal = Input.GetAxis (“Horizontal”); //刚体水平方向输入
float moveVertical = Input.GetAxis (“Vertical”); //刚体垂直方向输入
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
GetComponent().velocity = movement; // 创建 Vector3,作为刚体速度
}
即,此时只需要把上述几行代码复制到PlayerController.cs中,至于PlayerController.cs中自动生成的void Start () { } 和void Update () { }不用管他们。
上述代码能够成功对飞船进行键盘移动操作。
11、添加速度控制变量。
(1)加入一行速度控制代码,在public class PlayerController : MonoBehaviour { 下面添加一个:
public float speed = 5.0f; //速度控制变量初值
注意:在没添加之前,Player的PlayerController(Script)脚本那里只有Script,在VS2015中添加了public float speed = 5.0f; //速度控制变量初值
后,也没有出现Speed变量,这里需要在VS2015中把代码保存下,Speed变量才会在Unity3D软件中更新,才会出现Speed。
(2)
在下面代码更改:
GetComponent().velocity = movement;改为
GetComponent().velocity = movement* speed; // 创建 Vector3,作为刚体速度
上述代码能成功实现飞船的移动速度加快功能。
12、飞船是活动在XZ平面上,出现飞出界外问题,需要添加新的类文件管理飞船活动边界值。
(1)首先添加;
[System.Serializable]//为Boundary类添加可序列化属性,使得Boundary的实例boundary变量在Unity中的Inspector中显示出来。
public class Boundary //声明边界类Boundary
{
public float xMin, xMax, zMin, zMax; //声明边界类Boundary,管理飞船的活动边界
}
(2)添加:
public Boundary boundary; //添加边界类Boundary的实例boundary,访问权限为public
(3)在void FixedUpdate()中重新添加更新的代码:
void FixedUpdate ()
{
float moveHorizontal = Input.GetAxis (“Horizontal”); //刚体水平方向输入
float moveVertical = Input.GetAxis (“Vertical”); //刚体垂直方向输入
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
// GetComponent().velocity = movement; // 创建 Vector3,作为刚体速度
Rigidbody rb = GetComponent ();
if (rb != null) {
rb.velocity = movement * speed; //velocity为刚体速度,speed为作为速度变量初始值
rb.position = new Vector3
(
//Unity提供的Mathf.Clamp函数,限定刚体的活动范围
Mathf.Clamp (rb.position.x, boundary.xMin, boundary.xMax),
0.0f,
Mathf.Clamp (rb.position.z, boundary.zMin, boundary.zMax)
);
//函数Euler声明为 static Quaternion Euler(float x,float y,float z);
//它是类Quaternion的一个静态方法,接收绕X/Y/Z轴旋转角度为参数,并返回一个Quaternion对象。
}
13、添加飞船旋转效果。
public float tilt = 4.0f; //添加一个飞船倾斜系数变量,定义初值为4.0f
rb.rotation = Quaternion.Euler (0.0f, 0.0f, rb.velocity.x * -tilt);//飞船的左右倾斜效果。
14、控制飞船移动出现的问题:
一直出现飞船在添加边界boundary后不能移动的问题,原因是没有添加Boundary的值为(-6.0f,6.0f,-4.0f,14.0f)。在Unity3D界面中,在Boundary下面的四个值一点要输入。之前是默认的四个0,所以造成飞船不能移动的问题。
在此提醒,对文档pdf一定要认真逐字逐句的审查。
15、对于在PlayerController.cs脚本中:
public float speed = 5.0f; //速度控制变量初值
注意:在没添加之前,Player的PlayerController(Script)脚本那里只有Script,在VS2015中添加了public float speed = 5.0f; //速度控制变量初值 后,也没有出现Speed变量,这里需要在VS2015中把代码保存下,Speed变量才会在Unity3D软件中更新,才会出现Speed。
但是,即使这样做了,也不行,这个原因的解决办法是:
在脚本后面小圆圈里,选择reset重置,这样速度值才会更新。
16、在把脚本拖给Hierarchy中的对象时,如果出错,则删掉脚本重新新建,再重新拖。
17、暂时将Player隐藏就是,把其前面的对号去掉,变暗。
18、添加小行星随机产生逻辑功能
添加小行星逻辑功能,GameController.cs中,
public GameObject hazard; //实例化hazard对象,这里是指小行星
public Vector3 spawnValues; //定义一个轴上的值
private Vector3 spawnPosition = Vector3.zero;
private Quaternion spawnRotation; //实例化hazard对象的位置spawnRotation
void SpawnWaves ()//调用SpawnWaves函数
{
spawnPosition.x = Random.Range (-spawnValues.x, spawnValues.x);//在x轴极大值和极小值之间随机生成一个X值
spawnPosition.z = spawnValues.z;
spawnRotation = Quaternion.identity;//表示无旋转
Instantiate (hazard, spawnPosition, spawnRotation);//实例化hazard为批量小行星的位置和旋转角度
}
void Start () {
SpawnWaves ();
}
添加了以上代码后,在Inspector视图里才会出现Hazard变量。
三、飞船游戏中出现的关键低级错误
1、对照Unity官方案例精讲2015优化资料,严格按照资料说明来。(1)资料前半部分讲的非常细,有配图,而后面开始省略了,容易出错,这个时候要仔细按资料说明来,不能跳过对每一个对象,预设体,组件的说明。(2)对于资料中凡是进行的组件,预设体的设置都是有道理的,包括它说的例子,按它说的操作不跳过,就不会出错。(3)与成功的Demo中的MySpaceShooter进行一一对比,找出不能成功的原因。
2、对于C# Visual Studio 类代码中,更改的变量值,比如Speed,需要保存下,Unity3D中的Inspector组件中才会跟着更新,即使保存后没有更新,在组件里对某属性选择reset重置,再重新设置保存,应该会更新成功。
3、Inspector组件中有些添加的组件的属性变量既可以在Unity3D跟着组件出现,也有的需要在代码中添加,才会在Inspector组件中出现那个变量。
4、在资料Unity官方案例精讲2015优化的第66页中,对于:在Project视图Assets/_Scripts的目录中新建一个脚本DestroyByTime.cs,并绑定到粒子效果explosion_asteroid和explosion_player上(可以通过在Inspector视图中依次点击AddComponent—Scripts选项来给预设体绑定脚本)。
解决:仔细按说明文件来,新建一个脚本DestroyByTime.cs不拖给任何一个对象或预设体,直接找到Assets/Prefabs/VFX,选定explosion_asteroid,然后在其右边的Inspector视图中依次点击AddComponent—Scripts选项来绑定DestroyByTime.cs脚本。
5、在飞船游戏中,游戏结束后,小行星还在往下掉,按R键重新开始文本也不出现。
解决:对照成功的demo飞船SpaceShooter,发现Player的Tag值为默认的Untagged,选择Player,最后恢复正常。
6、Assets/Done/Done_Scripts/Done_EvasiveManeuver.cs(39,13): error CS1061: Type UnityEngine.Component' does not contain a definition for
velocity’ and no extension method velocity' of type
UnityEngine.Component’ could be found. Are you missing an assembly reference?
这是因为导入的资源包中有可以正确运行已做好的 Done_Main 场景, 将其删除, 创建一个全新的空场景文件 Main, 实践复原 Done_Main 的功能。
见网址说明:对 Unity 太空射击游戏的实践 http://www.cnblogs.com/isayes/p/6567043.html
7、UnassignedReferenceException: The variable shotSpawn of PlayerController has not been assigned.
You probably need to assign the shotSpawn variable of the PlayerController script in the inspector.
UnityEngine.Transform.get_position () (at C:/buildslave/unity/build/artifacts/generated/common/runtime/TransformBindings.gen.cs:26)
PlayerController.Update () (at Assets/_Scripts/PlayerController.cs:34)
这是因为子弹那个脚本在下面内容中,我一下子把整个的C#代码都复制粘贴到VS 2015里面去了,而实际上Unity中的Inspector的组件属性还没有跟上代码的脚步,这章才说到飞船移动,还没说子弹,而代码里已经提前复制了子弹的代码shotSpawn,就报错了。
解决:把还未出现的变量等先注释掉。
8、The associated script can not be loaded,Please fix any compile errors and assign a valid script.并且在资料中的explosion变量和player Explosion变量在DestoryByContact脚本下没有出现,根本就无法拖动explosion_player文件,拖入到变量playerExplosion中;无法拖动explosion_astteroid文件,拖入到变量explosion中。这一切的原因是因为后面GameController.cs脚本的原因,GameController.cs还没输入进去,其前面DestoryByContact.cs中已经含有GameController.cs的GameController字段,肯定抱错了,一报错,组件的属性变量explosion变量和player Explosion变量就不会出现了。
解决:在前面DestoryByContact.cs中把还未出现的GameController字段注释掉。
9、The referenced script on this Behaviour (Game Object ‘Boundary’) is missing!
这是因为脚本名为DestroyByBoundary.cs,而里面代码的类为DestroyBoundary.cs。
10、unity3d界面还原到初始设置
http://jingyan.baidu.com/article/c275f6ba343c5ee33c75674e.html
选择菜单“Window”–》”Layouts”–》”revert factory settings
11、飞船之前能够实现移动的功能,在添加移动区域界限Boundary后,不能移动了,主要原因是Boundary那里的上下左右界限值都为0。
解决:按pdf资料Unity官方案例精讲2015优化中,改为-6,6,-4,14即可。
12、出现的异常报错问题
UnassignedReferenceException: The variable shotSpawn of PlayerController has not been assigned.
You probably need to assign the shotSpawn variable of the PlayerController script in the inspector.
原因是:没有添加 Bolt和 Shot Spawn
解决:在资料说的组件那里拖动过去。
四、脚本功能实现
7个脚本:
1、DestroyBoundary.cs
using UnityEngine;
using System.Collections;
public class DestroyBoundary : MonoBehaviour
{
// Use this for initialization
void Start (){
}
// Update is called once per frame
void Update (){
}
//OnTriggerExit为事件响应处理函数(事件函数)
void OnTriggerExit (Collider other)
{
Destroy (other.gameObject); //销毁与小行星发生碰撞的其他游戏对象
}
}
2、DestroyByContact.cs
using UnityEngine;
using System.Collections;
//在子弹与小行星中,小行星与飞船碰撞事件中,添加碰撞销毁类DestroyByContact
public class DestroyByContact : MonoBehaviour
{
//explosion为小行星碰撞发生爆炸的粒子对象(变量)
public GameObject explosion;
//playerExplosion为飞船碰撞发生爆炸的粒子对象(变量)
public GameObject playerExplosion;
//下面scoreValue表示小行星被击中后玩家分值增加的数量
public int scoreValue; // how many score will be added when an asteroid’s shot
//实例化GameController类的成员gameController
private GameController gameController; // GameController script instance
void Start ()
{
//GameController为GameController游戏对象,
//gameControllerObject为GameController脚本对象
GameObject gameControllerObject = GameObject.FindWithTag (“GameController”);
//上面 用静态方法FindWithTag来查询Tag为指定名称的GameController的游戏对象
if (gameControllerObject != null)
//gameController为上面实例化GameController类的成员
//得到游戏对象GameController的脚本组件
gameController = gameControllerObject.GetComponent ();
else
Debug.Log ("找不到tag为GameController的对象");
if (gameController == null)
Debug.Log ("找不到 GameController 脚本");
}
void OnTriggerEnter (Collider other) //添加事件函数
{
if (other.gameObject.CompareTag (“Boundary”))
return;
//实例化explosion为小行星的位置和旋转角度
Instantiate (explosion, transform.position, transform.rotation);
if (other.gameObject.CompareTag (“Player”))
{
//实例化playerExplosion为位置的位置和旋转角度
Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
//当小行星碰撞的是Player对象时,游戏结束
gameController.GameOver();
}
//更新分值,为更新分值函数,scoreValue为玩家分值增加的数量
gameController.AddScore (scoreValue);
Destroy (other.gameObject);//碰撞中销毁与小行星发生碰撞的其他物体(对象)
Destroy (gameObject);//碰撞中销毁小行星Asteroid
}
}
3、DestroyByTime.cs
using UnityEngine;
using System.Collections;
public class DestroyByTime : MonoBehaviour
{
public float lifetime = 2.0f; //爆炸粒子对象的生命周期
void Start ()
{
// Destroy(gameObject, lifetime);为控制游戏对象的生命周期的方法
//在生命周期lifetime后销毁游戏物体(对象)gameObject
Destroy (gameObject, lifetime);
}
}
4、GameController.cs
using UnityEngine;
//因为下面类Text声明是在命名空间UnityEngine.UI中,这里需要添加命名空间UnityEngine.UI
using UnityEngine.UI;
using System.Collections;
//下面有类SceneManager,这里添加命名空间UnityEngine.SceneManagement
using UnityEngine.SceneManagement;
public class GameController : MonoBehaviour
{
public GameObject hazard; //实例化hazard对象,这里是指小行星
public Vector3 spawnValues; //定义一个轴上的值
public int hazardCount; //用变量hazardCount表示小行星的数量
public float spawnWait; //每次生成一个小行星后,生成下一个小行星的等待时间
//开始生成小行星之前等待一段时间,并不是一进入游戏小行星马上生成
public float startWait;
public float waveWait; //表示一批一批生成小行星之间的时间间隔
//添加计分组件Text文件类型的变量scoreText,scoreText用于更新计分
public Text scoreText;
private int score; //定义计分变量score,score表示当前分值
private Vector3 spawnPosition = Vector3.zero;
private Quaternion spawnRotation; //实例化hazard对象的位置spawnRotation
//添加文本类型Text的变量gameOverText,gameOverText用于Text组件的显示
public Text gameOverText;
private bool gameOver; //定义游戏结束变量gameOver
//添加文本类型Text的变量restartText,restartText用于更新Text组件
public Text restartText;
private bool restart; //定义游戏重新开始的变量restart
void Start ()
{
// Initialize score and update text.
score = 0;//在函数Start中初始化计分变量score
UpdateScore ();
//在游戏开始时应该将游戏结束时的文本组件删除,所以设置其text属性为空字符串//gameOver设置为false
gameOverText.text = "";
gameOver = false;
//同理,在游戏开始时应该将游戏重新开始时的文本组件删除,所以设置其text属性为空字//符串,restart设置为false
restartText.text = "";
restart = false;
StartCoroutine (SpawnWaves ()); //开启一个协程函数,函数为SpawnWaves
}
void Update ()
{
if(restart) //在函数Updata中,当restart为true时
{
//当restart为true时,处理键盘事件,R键被按下
if( Input.GetKeyDown(KeyCode.R))
//重新加载场景,在以前Unity4.x版本,重新加载场景为下面语句
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
//Application.LoadLevel(Application.loadedLevel);
}
}
IEnumerator SpawnWaves ()//调用SpawnWaves函数
{
yield return new WaitForSeconds (startWait);//协程类WaitForSeconds
while (true)
{
if(gameOver)
{
restartText.text = “按R键重新开始”;
restart = true;
break; //在SpawnWaves函数中跳出while循环
}
//批量随机生成一些小行星
for (int i = 0; i < hazardCount; ++i) {
//在x轴极大值和极小值之间随机生成一个X值
spawnPosition.x = Random.Range (-spawnValues.x, spawnValues.x);
spawnPosition.z = spawnValues.z;
spawnRotation = Quaternion.identity;//表示无旋转
//实例化hazard为批量小行星的位置和旋转角度
Instantiate (hazard, spawnPosition, spawnRotation);
//每生成一个小行星后等待时间
yield return new WaitForSeconds (spawnWait);
}
//每批量生成一批小行星后等待时间
yield return new WaitForSeconds (waveWait);
}
}
//添加函数AddScore来更新(增加)分值。
public void AddScore (int newScoreValue)
{
//上面AddScore函数访问权限为public,
//因此可以在另一脚本DestroyByContact.cs中调用这个函数
score += newScoreValue;
UpdateScore ();
}
void UpdateScore ()
{
scoreText.text = “得分: ” + score; //显示游戏得分,得分:score
}
//添加函数GameOver表示游戏结束,
//在该项目其他脚本中当飞船与小行星碰撞爆炸后就调用此函数来结束游戏
public void GameOver()
{
gameOver = true;
gameOverText.text = “游戏结束”;
}
}
5、Mover.cs
using UnityEngine;
using System.Collections;
public class Mover : MonoBehaviour
{
public float speed = 20.0f; //定义子弹的初始化速度
void Start ()
{
//得到子弹的向前移动刚体速度
GetComponent().velocity = transform.forward * speed;
}
}
6、PlayerController.cs
using UnityEngine;
using System.Collections;
//为Boundary类添加可序列化属性,
//使得Boundary的实例boundary变量在Unity中的Inspector中显示出来。
[System.Serializable]
//声明边界类Boundary
public class Boundary
{
//声明边界类Boundary,管理飞船的活动边界
public float xMin, xMax, zMin, zMax;
}
//键盘控制飞船移动脚本
public class PlayerController : MonoBehaviour
{
public float speed = 5.0f; //速度控制变量初值
public float tilt = 4.0f; //添加一个飞船倾斜系数变量,定义初值为4.0f
public Boundary boundary; //添加边界类Boundary的实例boundary,访问权限为public
public float fireRate = 0.5f;//定义一个类型变量,fireRate表示发射间隔时间
public GameObject shot;//shot为Bolt预制体,实例化预制体或变量shot
//shotSpawn是空的子对象,Transform为类型,shotSpawn为变量对象
public Transform shotSpawn;
//下次可以发射的最早时间,从0开始。Unity控制发射间隔的方法。
private float nextFire = 0.0f;
// Use this for initialization
void Start (){
}
//Update is called once per frame
void Update ()
{
//Input.GetButton为函数
if (Input.GetButton (“Fire1”) && Time.time > nextFire)
{
//下一次开火时间为当前时间 + 发射间隔时间
nextFire = Time.time + fireRate;
//Instantiate为函数
Instantiate (shot, shotSpawn.position, shotSpawn.rotation);
//得到Player对象上绑定的AudioSource组件,
//调用AudioSource类的成员函数Play来播放音频
GetComponent ().Play ();
}
}
void FixedUpdate ()
{
float moveHorizontal = Input.GetAxis (“Horizontal”); //刚体水平方向输入
float moveVertical = Input.GetAxis (“Vertical”); //刚体垂直方向输入
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
// GetComponent().velocity = movement;
// 创建 Vector3,作为刚体速度
Rigidbody rb = GetComponent ();
if (rb != null) {
//velocity为刚体速度,speed为作为速度变量初始值
rb.velocity = movement * speed;
rb.position = new Vector3
(
//Unity提供的Mathf.Clamp函数,限定刚体的活动范围
Mathf.Clamp (rb.position.x, boundary.xMin, boundary.xMax),0.0f,
Mathf.Clamp (rb.position.z, boundary.zMin, boundary.zMax));
//函数Euler声明为 static Quaternion Euler(float x,float y,float z);
//它是类Quaternion的一个静态方法,接收绕X/Y/Z轴旋转角度为参数,
//并返回一个Quaternion对象。
//飞船的左右倾斜效果。
rb.rotation = Quaternion.Euler (0.0f, 0.0f, rb.velocity.x * -tilt);
}
}
}
7、RandomRotator.cs
using UnityEngine;
using System.Collections;
public class RandomRotator : MonoBehaviour
{
public float tumble = 5.0f;//小行星的旋转系数变量
void Start ()
{
//GetComponent ()为刚体组件,angularVelocity为角速度,
//Random.insideUnitSphere为单位长度半径球体内一个随机点(向量)
//因此,随机点与小行星旋转系数乘积为随机旋转角速度
GetComponent ().angularVelocity = Random.insideUnitSphere * tumble; //tumble为小行星旋转系数
}
void Update (){
}
}