《飞盘射击》案例总结
第一部分:Unity组件
什么是UI?
UI就是用户操作界面
常用UI介绍
<1>NGUI
NGUI是一款使用最多的第三方软件,国内大多数的游戏界面UI,都是使用NGUI插件编写出来的
<2>
UGUI(Untiy 4.6版本后自带的一套UI系统)
<3>ONGUI
现在主要是用于Unity引擎的界面扩展,NGUI和UGUI都是“”所见即所得“,而OnGUI就像是网页编写中HTML和Css样式表
<Legacy GUI>
旧版UI,只有俩个组件,分别是GUIText组件和GUIImage组件,分别是文本和图片,公司实际游戏项目开发不会用到
GUIText组件,主要用于文字的显示
GUITexture组件
主要用于图片的显示
鼠标事件
OnMosueEnter () 鼠标进入
OnMouseExit () 鼠标离开
OnMouseDown () 鼠标按下
Color结构体
Color.red;Color.green;Color.blue;
特效组件之TrailRenderer(拖尾渲染器)
它的一个重要用途是体现物体的运动速度,它的位置是在Component->Effects->Teail Renderer
材质球丢失的颜色为粉红色
材质球的Shader为Particle/Additive(粒子/添加物)
Time 设置拖尾持续时间
美工的黑白图:“黑透白不透”
特效组件之LineRenderer(线渲染器)
游戏中常用于渲染激光特效 ,或者用于子弹瞄准
同TrailRendere一样
声音组件之AudioSource
我们导入Unity的所有声音文件,他们的资源类型都是Audio Clip类型
Unity能使用的音频格式: .aif .wav .mp3 .ogg
Audio Source音频源组件,你可以将音频源组件当成“音响”
Play On Awake 唤醒时播放
Loop 循环
Mute 静音
Volume 音量
Spatial Blend 空间混合 0是2D声音 1是3D声音
Auido Listener 组件
声音侦听器,其实就是我们在游戏世界中的耳朵,在Main Camera上会挂载一个Auido Listener组件
Auido Source 常用函数
<1>Play() 函数
播放音频剪辑
<2>Stop() 函数
停止播放音频剪辑
<3>Pause() 函数
暂停播放音频剪辑
第二部分:Unity中常用的API函数
常用API之实例化与销毁
GameObeject.Instantiate(Object,Vector3,Quaternion);
Object 是指要实例化的游戏物体
Vector3既能表示方向又能表示位置,在这里表示要实例化的位置
Quaternion[四元数]:实例化后物体的旋转状态
构造随机位置
Random.Range(min,max);
在min和max之间随机生成一个随机数
销毁游戏物体
GameObject.Destroy(Object,float); 定时销毁某个游戏物体
Object 要销毁的游戏物体
float 多少秒后自动销毁
常用API之Invoke函数调用
for循环生成宝箱
for(int i = 0,i<5,i++) {
GameObject.Instantiate(box,Vector3,Quaternion.Identity);
}
一次生成5个宝箱
Invoke(string,float) : 多少秒后执行某个函数,只会调用一次
string :要调用的函数名称,用双引号括起来
float : 多少秒后调用,注意它是浮点数,如5秒,就写成5.0f
InvokeRepeating(string,float1,float2) :重复调用函数
string : 要调用的函数名称,用双引号括起来
float1 : 多少秒后开始调用
float2 : 以后每隔多少秒调用一次
Invoke函数的家在哪?
是Class,类下的函数(方法),字段,属性都可以理解为家庭成员
Invoke函数属于MonoBehaviour类
常用API之消息发送
gameObject.SendMessage(string); 通知这个游戏物体上的脚本执行某个函数
string : 将要执行的方法名,用双引号括起来
常用API之协同程序
在脚本运行过程中,需要执行一些额外的代码,类似开启了一个线程,但协程不是线程,而且协程只能在继承自MonoBehaviour类的子类中使用
协同程序语法格式
IEnumerator Task3 () {
yield return new WaitForSeconds(2);
Debug.Log("执行任务3"):
}
IEnumerator :协同程序的返回值类型
例如接受这个返回值,private IEnumerator m_ienumerator;
yield return : 协同程序返回 xxxxx;
new WaitForSeconds(秒数) : 实例化一个对象,等待多少秒后执行
开启协同程序
StartCoroutine(“协同程序方法名”);
停止协同程序
StopCoroutine("协同程序方法名")
常用API之脚本生命周期
这些生命周期事件是由Unity事先定好的,他们全部定义在MonoBehaviour这个类中,也就意味着只有继承自MonoBehaviour类的脚本,才有这些生命周期事件
1.Awake ()
唤醒事件,只能执行一次
2.OnEnable ()
启用事件,只执行一次,当脚本组件被启用时执行一次
3.Start ()
开始事件,只执行一次
4.FixedUpdate ()
固定更新事件,执行N次,每0.02秒执行一次,Update是0.16秒左右执行一次
5.Update ()
更新事件,执行N次,每帧执行一次
6.LateUpdate ()
稍后更新事件,执行N次,在Update事件之后执行
7.OnGUI ()
GUI渲染时间,执行N次,次数是Update事件的俩倍
8.OnDisable ()
禁用事件,执行一次。在OnDestroy事件前执行
9.OnDestroy ()
销毁事件,执行一次。当脚本所挂载的游戏物体被销毁执行。
这些时间执行顺序有1-9不变。
常用API之工具类
1.Screen 屏幕类
2.Time 时间类
3.Mathf 数学类
1.Screen 包含了与屏幕相关的数据信息,这个类中常用的属性有Screen.width 屏幕的宽度,Screen.height 屏幕的高度,这俩个值取得是Game窗口的宽度和高度,这让我想到了Camera.main.ScreenPointToWorld(Vector3),将屏幕坐标转换为世界坐标
2.Time 最常用的属性有Time.time,指的是从游戏开始到现在所用的时间,Time.timeScale,时间缩放,常用于暂停游戏,值为0,暂停游戏,值为0.5,慢放0.5倍,值为1,正常游戏状态
3.Mathf 包含了各种各样的数学运算相关的函数,常用的函数有Math.Abs() 取绝对值,Mathf.Max 取最大值,Mathf.Min() 取最小值,Mathf.Round() 四舍五入
Mathf.Lerp(float a,float b,float t) : 插值运算
基于t返回a~b之间的值,t的取值范围是0~1,t=0时,返回a,t=0.5时,返回a和b的正中间值,t=1时返回b
例如 a = Mathf.Lerp(a,10,Time.deltaTime)
a~10的范围不断缩小,a的值固定增长,最后会无限接近于10
它的目的是实现"平滑过渡"
第三部分 物理射线
物理射线?
从屏幕的一个点发射一条无限长的射线,这根射线会与场景中的其他游戏物体身上的碰撞体组件碰撞,触发某些函数事件,射线即结束
由于射线会与物理组件Colider发生交互,所以"射线"也被称为"物理射线"
Camera.main 代表Tag标签为"Main Camera"的摄像机的Camera组件
Camera.main.ScreenPointToRay(Vecotor3)
摄像机Camera组件(对象)下的一个方法
往鼠标位置发射一条射线的完整代码:
private Ray ray;
private RaycastHit hit;
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
检查射线与其他物体的碰撞
RaycastHit 用于存储射线的碰撞信息
if(Physics.Raycast(ray,out hit))
{
要执行的代码;
}
Physics.Raycast 物理类下边有一个射线检查的方法,这个方法有16种重载方式,这是第3种
实例运用之打砖块
for循环嵌套实例化一堵墙
for(int l = 0,i < 10,i++)
{
for(int h = 0,h < 10,h++)
{
GameObject.Instantiate(object,new Vector3(l,h,0),Quaternion.Indentity);
}
}
这段代码会通过预制体实例化一堵10x10的墙
RaycastHit.point 获取射线的碰撞点
Vector3向量计算方向:
Vector3(终点) - Vector(起点) = 方向(起点像终点)
让砖块五颜六色
GameObject go = GameObject.Instantiate(object,new Vector3(l,h,0),Quaternion.Indentity);
go.GetComponent.material.color = new Color(Rndom.Range(0.0f,1.0f),Random.Range(0.0f,1.0f),Random.Range(0.0f,1.0f));
UnityRGB的取值范围是0~1;
Debug绘制射线,只能在Scene视图下看到,具体代码为:
Vector3 dir = hit.point - m_Transform.position;
Debug.DrawRay(m_Transform.position,dir,color.red);
第四节 飞盘射击案例
飞盘射击之案例分析
1.UI展示
游戏开始UI : 游戏名称 玩法介绍 开始游戏 退出游戏
游戏UI : 得分 倒计时
结束UI : 游戏结束 总计得分 重新开始
2.主角控制 物理射线 碰撞函数
3.AI控制 随机生成障碍物
4.音效特效
5.调整灯光,摆放资源位置
飞盘射击案例之主角控制
手臂朝向碰撞点代码
Transform.LookAt(Vector3) : 朝向世界中的一个点
场景模型添加碰撞器
Mesh Colider组件,使用制作好的简模,降低物理运算消耗,提高游戏性能
Vertices(verts) : 顶点个数,Mesh网格是由顶点组成面,面组成体,Vertices个数越少,计算量越小
控制手臂的旋转中心
新建空物体的方法,用父物体控制子物体,将脚本挂载带父物体身上
从枪口添加激光特效
新建一个空物体,重命名,添加LineRenderer组件,设置相关属性
代码如下:
LineRenderer.SetPosition(int,Vector3) : 设置线的位置
int:0是起点,1是终点
Vector3: 位置
完整代码如下:
LineRenderer.SetPosition(0,m_transform.position);
LineRenderer.SetPosition(1,hit.point);
飞盘案例之飞盘射击
Transform.parent 属性,当前游戏物体的父物体
Transform.GetComponentsInChildren<T>(); 获取所有子物体的某个组件
GameObejct.AddComponent<T>(); 给脚本所在游戏物体添加组件
Transform.SetParent(Transform); 将当前物体设置为另一个物体的子物体
添加背景音效
主摄像机添加音效
添加射击音效 如果按下鼠标左键就播放一次
飞盘射击之游戏管理器
UI界面的搭建
StartUI:
GUIText : 开始游戏
GUIText : 退出游戏
GUIText : 玩法介绍
GameUI:
GUIText : 总得分
GUIText : 倒计时20s
EndUI:
GUIText : 游戏结束
GUIText : 重新开始
GUIText : 得分
游戏管理器 GameManager Scripts
①创建游戏状态枚举:开始,游戏,结束
public enum GameState {
Start,
Game,
End
}
②查找获取三组UI的引用,并控制他们的显示次序
private GameObject m_startUI; //定义三个GameObject类型进行接收
private GameObject m_gameUI;
private GameObject m_endUI;
void Start () {
m_startUI = GameObject.Find("StartUI"); //查找组件 GameObject.Find() ,返回值类型为GameObject
m_gameUI = GameObject.Find("GameUI");
m_endUI = GameObject.Find("EndUI");
}
③定义一个字段存储当前的游戏状态
private GameState gameState;
④定义一个切换游戏状态的方法
public void ChangeGameState(GameState state) //传递过来一个GameStae参数(Start,Game,End),取名state
{
gameState = state; //存储传递过来的状态,用定义的引用gameState存储枚举的GameState(Start,Game,End)
if (gameState == GameState.Start) //开始
{
m_startUI.SetActive(true); //激活StartUI界面
m_gameUI.SetActive(false); //关闭GameUI界面
m_endUI.SetActive(false); //关闭EndUI界面
m_bg_audioSource.Stop(); //停止播放背景音乐
m_weapon.ChangeCanMove(false); //获取到Weapon脚本组建后,点获取它的ChangeCanMove方法,里面有俩个参数(true和false)
m_Weapon.SetActive(false); //禁用Weapon对象的所有功能,不显示手臂
m_feiPan.StopCreat(); //调用FeiPanGameManager中的StopCreat()方法,即StopCreat方法里的CancelInvoke()
m_guitext_score.text = "得分:" + score; //同步重置得分的UI
}
else if (gameState == GameState.Game) //游戏中
{
m_startUI.SetActive(false); //关闭StartUI
m_gameUI.SetActive(true); //激活GameUI
m_endUI.SetActive(false); //关闭EndUI
m_bg_audioSource.Play(); //播放背景音乐
m_weapon.ChangeCanMove(true); //激活手臂,ChangeCanMove方法里有俩个布尔值,默认为false,如果为true,默认会发射射线,检测碰撞,添加物理组件,自 动销毁
m_Weapon.SetActive(true); //激活weapon对象,显示手臂
m_feiPan.enabled = true; //激活FeiPanGameManager脚本组件,生成飞盘
m_feiPan.StartCreat(); //调用FeiPanManager脚本组件里的StartCreat()方法,即InvokeRepeating()
StartTime(); //调用StartTIme() 方法
}
else if (gameState == GameState.End) //结束
{
m_startUI.SetActive(false); //关闭StartUI界面
m_gameUI.SetActive(false); //关闭GameUI界面
m_endUI.SetActive(true); //激活EndUI界面
m_bg_audioSource.Stop(); //停止播放背景音乐
m_weapon.ChangeCanMove(false); //禁用ChangeCanMove方法,包括发射射线,物理射线检测,设置LineRenderer的Position,检测碰撞,射击音效,添加物理组 件,自动销毁
m_Weapon.SetActive(false); //禁用Weapon对象的所有功能,不显示手臂
m_feiPan.StopCreat(); //停止生成飞盘,即CancelInvoke
m_feiPan.Disapper(); //立即销毁场景内的所有游戏物体 transform.gameObject,GetComponentInChildren<Transform>();
飞盘射击案例之界面逻辑
①开始界面逻辑
private GameManager gameManager; //定义一个GameManager接收脚本
void Start ()
{
gameManager = GameObject.Find("UI").GetComponentInChildren<GameManager>(); //获取UI对象下的GameManager脚本组件
}
void OnMouseDown() //鼠标按下事件
{
gameManager.ChangeGameState(GameManager.GameState.Game); //调用GameManager下的ChangeGameState方法
}
②游戏界面逻辑
1.新建字段存储分数
private int score = 0; //定义一个int类型的字段存储分数
2.定义一个增加分数的公开方法
public void AddScore()
{
score += 1; //分数+1
m_guitext_score.text = "得分:" + score; //同步GameUI下的GameScore的GUIText组件
}
3.在武器射击时调用此方法
if (hit.collider.tag == "FeiPan" && Input.GetMouseButtonDown(0)) //碰撞道德游戏物体的Colider的Tag标签为FeiPan
{
m_gameManager.AddScore(); //调用增加分数的方法
}
4.控制UI显示分数
public void AddScore()
{
score += 1; //分数+1
m_guitext_score.text = "得分:" + score; //同步GameUI下的GameScore的GUIText组件的text文本
}
5.倒计时
private float time = 20; //定义时间
void Update() //是在Update中的方法,逐帧调用
{
if (satrttime) //bool值为True
{
time -= Time.deltaTime; //倒计时效果
m_guitext_time.text = "时间:"+ time + "s" //同步倒计时UI,即GameUI下的GameTimeUI的GUIText的text文本
}
}
飞盘射击之案例总结
结束界面逻辑
1.倒计时为0,修改游戏状态,并且将倒计时重置
if (time <= 0)
{
ChangeGameState(GameManager.GameState.End); //切换到EndUI
m_guitext_end.text = "总计得分:" + score; //同步分数
satrttime = false; //重置时间和分数
time = 20.0f;
score = 0;
]
2.结束界面显示总分数
m_guitext_end.text = "总计得分:" + score;
3.重新开始按钮
private GameManager m_gamemanager; //定义一个GameManager类型接收GameManager脚本组件
void Start (){
m_gamemanager = GameObject.Find("UI").GetComponent(); //获取UI对象下的GameManager组件
}
void OnMouseDown() //鼠标按下事件
{
m_gamemanager.ChangeGameState(GameManager.GameState.Start); //返回StarUI,即重新开始按钮
}
4.细节调整和优化 for循环删除场景内游戏物体
public void Disapper() {
Transform[] fp = transform.gameObject.GetComponentsInChildren(); //取得当前组件的对象下的所有子对象的Transform组件
for (int i = 1; i < fp.Length; i++) //i = 1,防止父物体身上的FeiPanManager脚本组件被删掉
{
GameObject.Destroy(fp[i].gameObject); //删除所有子物体
}
}
本篇完~~~~~~~~~~~
网友评论