Unity3d学习之路——UI系统之公告牌

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还真的是强大,想做出更精美的界面,下周要考毛概了就暂时不深入了。我的项目传送门

猜你喜欢

转载自blog.csdn.net/ke1950523491/article/details/80551395