Unity3d学习之路——UI系统之公告牌
作业内容要求
以下作业四选一:
1、血条(Health Bar)的预制设计。具体要求如下
分别使用 IMGUI 和 UGUI 实现
使用 UGUI,血条是游戏对象的一个子元素,任何时候需要面对主摄像机
分析两种实现的优缺点
给出预制的使用方法2、 UI 效果制作(你仅需要实现以下效果之一)
进入 NGUI 官方网站,使用 UGUI 实现以下效果- Inventory 背包系统
- Quest Log 公告牌
- Scroll View 选择板
以上例子需要使用 Unity web player, 仅支持以下操作系统与浏览器,参见官方下载
Windows 版 IE11
Mac OS X 10.7 Safari
出现界面需要等待较长时间,打开页面让它慢慢加载3、 如果你觉得 UI 不是你的菜,喜欢复杂的设计与代码研究DOTween 网站 , 它在 Specific settings 中 transform.DoMove 返回 Tween 对象。请实现该对象,实现对动作的持续管理。
本作业有较大难度,务必参考师兄的作业4、如果你喜欢凭空构思场景,请自制有趣的 UI 场景
例如:“几个小动物(3D)开会,语句从每个动物头上飘出,当达到一个大小,会出现清晰的文字!如果文字较多,会自动滚动”
成品图:
实现过程
本来想实现游戏中经常出现的一个开始场景:一个菜单栏,点击“开始游戏”会有进度条加载的画面。但没找到合适的游戏资源做进度条,就转而做菜单栏,如果仅仅是菜单栏又好像不太好,就留了两个按钮学习师兄的博客做公告牌,第三个按钮用于退出。
- Step1:创建UI界面,首先要添加Canvas画布,如果一开始没加,添加按钮等UI元素时Unity也会自动帮你补上,然后在Canvas下添加ScrollView组件和Image组件(用于背景图片显示):
+ Step2 :往ScrollView组件里的Content添加三个Button和两个Text,往ScrollView里的Viewport添加Image组件作为菜单栏的背景图片,组件层次目录如下:
然后将本地图片拖到Assets里,要将图片的Texture Type类型改为Sprite(2D and UI)才能作为背景图片放到UI里(具体操作:Inspector -> Texture Type -> Sprite(2D and UI)),还有一点是不是所有大小的图片都能将类型改为Sprite(2D and UI)的,如果不符合规格Unity会给出警告。具体要什么规格的图片我也不是十分清楚。改变按钮的背景图不用另外加一个Image组件,因为Button自带Image组件。
改完背景图后往Content里添加组件Vertical Layout Group用于排版里面的Button和Text,这个组件我也是看了师兄的博客才知道的,如果不加Button会叠加在一起:
那么改完背景图和Content里的属性后,一切正确的话就出现以下界面了(当然,图片和样式大家都不一样)。
- Step3:页面基本完成了,接下来是逻辑的了。往Button添加点击事件,这个还是比较简单的,因为Button已经留好接口给你绑定事件的了:
也可以在代码里实现:
private Button btn;
// text 是公告牌的文本框
public Text text;
// Use this for initialization
void Start()
{
btn = this.gameObject.GetComponent<Button>();
btn.onClick.AddListener(OnClick);
}
void OnClick(){}
- Step4:公告牌的逻辑是简单的,在OnClick函数里判断text的状态是否活跃的,如果不是Active,就设为true,反之亦然。但这样的UI交互太僵化了,所以要通过一定事件的变化才更具交互性,想过用Animation来实现这个变换过程,但没弄好!好吧,Animation我没学好。看了师兄的博客后,他用的是协程的方法做,协程这个概念一脸懵逼啊,百度一下后,还好,找到一个好详细很好的教程,介绍给大家:Unity3D协程介绍 以及 使用
协程的执行有点像多线程,协程比多线程有极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销;还有,协程不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突。
对应的代码:
// Text的原本高度
private float text_height;
//协程循环的帧数
private int frame = 20;
// 收回Text
IEnumerator rotateIn()
{
float rotatex = 0;
float height = text_height;
for (int i = 0; i < frame; i++)
{
rotatex -= 90f / frame;
height -= text_height / frame;
// 以下两行是为了让Text的收回有一个渐变过程
text.transform.rotation = Quaternion.Euler(rotatex, 0, 0);
text.rectTransform.sizeDelta = new Vector2(text.rectTransform.sizeDelta.x, height);
// 保存现存变量的值,等到下一帧继续执行
yield return null;
}
text.gameObject.SetActive(false);
}
IEnumerator rotateOut()
{
float rotatex = -90;
float xy = 0;
text.gameObject.SetActive(true);
for (int i = 0; i < frame; i++)
{
rotatex += 90f / frame;
xy += text_height / frame;
// 以下两行是为了让Text的淡出有一个渐变过程
text.transform.rotation = Quaternion.Euler(rotatex, 0, 0);
text.rectTransform.sizeDelta = new Vector2(text.rectTransform.sizeDelta.x, xy);
// 保存现存变量的值,等到下一帧继续执行
yield return null;
}
}
- Step5:最后一步就是退出按钮的实现了,这个就两三句主要代码:
public class Quit : MonoBehaviour
{
private Button btn;
private void Start()
{
btn = gameObject.GetComponent<Button>();
btn.onClick.AddListener(QuitManager);
}
public void QuitManager()
{
#if UNITY_EDITOR
UnityEditor.EditorApplication.isPlaying = false;
#else
Application.Quit();
#endif
}
}
至此,一个简单的具有退出功能的公告牌就做好了。
总结
Unity还真的是强大,想做出更精美的界面,下周要考毛概了就暂时不深入了。我的项目传送门