[UnityUI]一些有趣的UI例子

1.环形进度条

2.图形匹配

using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;

/// <summary>
/// 被拖拽的大方块
/// </summary>
public class DragBrick : MonoBehaviour {

    private List<Transform> childrenTra = new List<Transform>();//大方块下的小方块
    private List<GameObject> targetGo = new List<GameObject>();//小方块匹配的空方块
    private GameObject[] tempGo;
    private Vector3 posOffset;

    void Start()
    {
        Transform[] tra = transform.GetComponentsInChildren<Transform>();
        for (int i = 1; i < tra.Length; i++)//tra[0]是自身,故不算上
            childrenTra.Add(tra[i]);
    }

    public void DragStart()
    {
        posOffset = transform.position - Input.mousePosition;
        transform.SetAsLastSibling();
    }

    public void DragUpdate()
    {
        transform.position = Input.mousePosition + posOffset;
    }

    /// <summary>
    /// 注意点:
    /// 1.被射线检测的物体要带有Collider
    /// 2.被射线检测的物体的z轴 > 发出射线检测的物体的z轴
    /// 3.当没有给Raycast函数传layerMask参数时,仅仅只忽略使用IgnoreRaycast层的碰撞器。
    /// </summary>
    public void DragEnd()
    {
        tempGo = new GameObject[childrenTra.Count];
        int suitableBrickAmount = 0;//能正确匹配的砖块数目

        for (int i = 0; i < childrenTra.Count; i++)
        {
            RaycastHit hit;
            if (Physics.Raycast(childrenTra[i].position, Vector3.forward, out hit))
            {
                tempGo[i] = hit.transform.gameObject;
                suitableBrickAmount++;
            }
            else break;
        }

        if (suitableBrickAmount == childrenTra.Count)//完全匹配
        {
            if (targetGo.Count == 0)//初次完全匹配
            {
                Match();
            }
            else//已经完全匹配,再次完全匹配
            {
                Clear();
                Match();
            }
        }
        else//不能完全匹配
        {
            Clear();
        }
    }

    void Match()
    {
        for (int i = 0; i < tempGo.Length; i++)
        {
            targetGo.Add(tempGo[i]);
            targetGo[i].layer = 2;//忽略射线碰撞
            Vector3 pos = targetGo[i].transform.position;
            pos.z--;
            childrenTra[i].position = pos;
            childrenTra[i].GetComponent<Outline>().enabled = true;
        }
    }

    void Clear()
    {
        for (int i = 0; i < targetGo.Count; i++)
            targetGo[i].layer = 0;
        targetGo.Clear();

        for(int i = 0;i < childrenTra.Count;i++)
            childrenTra[i].GetComponent<Outline>().enabled = false;
    }
}

3.多重血条

描述:

1.当受到伤害较小时,出现“残血”效果

2.当受到伤害较大时,出现“流水”效果

3.多重血条主要由四种血条组成:

a.最底层血条

b.当前血条与下一血条,就像下图中的紫色和红色

c.过渡血条,一般为深红色

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class BossBloodBar : MonoBehaviour {

    public Image nowBar;
    public Image middleBar;
    public Image nextBar;
    public Text countText;

    private int count;//血条数
    private float nowBlood;//在一条血中的当前血量,如:100/1000则为100
    private float oneBarBlood = 1500f;//一条血的容量,如:100/1000则为1000   

    private int colorIndex;
    public Color[] colors;//普通血条的颜色,注意Alpha值
    public Color middleBarColor;//过渡血条的颜色,注意Alpha值

    public float slowSpeed = 0.1f;//受到重伤时( >oneBarBlood)或者处于加血状态,普通血条的流动速度
    public float quickSpeed = 1f;//受到轻伤时( <oneBarBlood),普通血条的流动速度
    private float speed;//当前普通血条采用的速度
    public float middleBarSpeed = 0.1f;//过渡血条的流动速度

    private float targetBloodValue = 1f;//血条移动的目标点
    private bool isBloodMove = false;//控制血条的移动

	void Update ()
    {
        MoveBloodMiddle();//过渡血条的流动
        MoveBloodNormal();//普通血条的流动
	}

    /// <summary>
    /// 传入总血量,初始化血条
    /// </summary>
    /// <param name="number"></param>
    public void InitBlood(float number)
    {
        count = (int)(number / oneBarBlood);
        nowBlood = number % oneBarBlood;

        colorIndex = count % colors.Length;
        nowBar.color = colors[colorIndex];
        nowBar.fillAmount = nowBlood / oneBarBlood;

        if (count != 0)
        {
            int nextColorIndex = (colorIndex - 1 + colors.Length) % colors.Length;
            nextBar.color = colors[nextColorIndex];
        }

        middleBar.color = middleBarColor;
        middleBar.gameObject.SetActive(false);

        countText.text = count + "";
    }

    /// <summary>
    /// 血量变化,并根据伤害判断是否使用过渡血条
    /// </summary>
    /// <param name="number"></param>
    public void ChangeBlood(float number)
    {
        nowBlood += number;
        targetBloodValue = nowBlood / oneBarBlood;
        isBloodMove = true;

        if ((number < 0) && (Mathf.Abs(nowBar.fillAmount - targetBloodValue) <= 1))//处于受伤状态并且伤害量较低时
        {
            speed = quickSpeed;
            middleBar.gameObject.SetActive(true);
            middleBar.fillAmount = nowBar.fillAmount;
            targetValue = targetBloodValue;
        }
        else
        {
            speed = slowSpeed;
            middleBar.gameObject.SetActive(false);
        }
    }

    private float targetValue;
    void MoveBloodMiddle()
    {
        if (speed == quickSpeed)
        {
            middleBar.fillAmount = Mathf.Lerp(middleBar.fillAmount, targetValue, middleBarSpeed);
            if (Mathf.Abs(middleBar.fillAmount - 0) < 0.01f)
            {
                middleBar.transform.SetSiblingIndex(nextBar.transform.GetSiblingIndex() + 1);
                middleBar.fillAmount = 1;
                targetValue++;
            }
        }
    }

    void MoveBloodNormal()
    {
        if (!isBloodMove) return;

        nowBar.fillAmount = Mathf.Lerp(nowBar.fillAmount, targetBloodValue, speed);

        if (Mathf.Abs(nowBar.fillAmount - targetBloodValue) < 0.01f)//到达目标点
            isBloodMove = false;

        if (count == 0)
            nextBar.gameObject.SetActive(false);
        else
            nextBar.gameObject.SetActive(true);

        if (nowBar.fillAmount >= targetBloodValue)
            SubBlood();
        else
            AddBlood();
    }

    void AddBlood()
    {
        float subValue = Mathf.Abs(nowBar.fillAmount - 1);
        if (subValue < 0.01f)//到达1
        {
            count++;
            countText.text = count.ToString();

            nowBar.fillAmount = 0;
            targetBloodValue -= 1;
            nowBlood -= oneBarBlood;

            nextBar.color = colors[colorIndex];

            colorIndex++;
            colorIndex %= colors.Length;
            nowBar.color = colors[colorIndex];
        }
    }

    void SubBlood()
    {
        float subValue = Mathf.Abs(nowBar.fillAmount - 0);
        if (subValue < 0.01f)//到达0
        {
            middleBar.transform.SetSiblingIndex(nextBar.transform.GetSiblingIndex() + 2);
            if (count <= 0)
            {
                middleBar.gameObject.SetActive(false);
                Destroy(this);
                return;
            };
            count--;
            countText.text = count.ToString();

            nowBar.fillAmount = 1;
            targetBloodValue += 1;
            nowBlood += oneBarBlood;

            colorIndex--;
            colorIndex += colors.Length;
            colorIndex %= colors.Length;
            nowBar.color = colors[colorIndex];

            int nextColorIndex = colorIndex - 1 + colors.Length;
            nextColorIndex %= colors.Length;
            nextBar.color = colors[nextColorIndex];
        }
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-09 02:50:34

[UnityUI]一些有趣的UI例子的相关文章

Android学习笔记(三六):横屏竖屏的切换

1.准备环境 对模拟器,只要“Ctrl+F12“,就可以可以实现竖屏(portrait)和横屏(landscape)的切换. 2.UI的屏幕切换实现 下面一个简单的例子,如图. 我们需要写两个Android XML文件,假定文件为chapter_19_test1.xml,放在常规目录位置layout/内容如下: [plain] view plaincopy <?xml version="1.0" encoding="utf-8"?> <Linear

RxAndroid 学习

链接:https://medium.com/@kurtisnusbaum/rxandroid-basics-part-1-c0d5edcf6850 如果你在阅读这篇文章,相信你一定很想了解RxJava以及如何在Android应用中使用它.可能你已经见过RxJava的代码了,但仍然有些疑惑,愿你能在这篇文章里找到答案. 当我第一次使用RxJava的时候我只是在照搬代码,这些代码能跑起来,但是我对RxJava的基础部分仍然存在误解,而且我找不到好的源码来学习.所以为了理解RxJava,我不得不一点一

SaaS技术栈的走势

本地部署时代 在软件还是“本地部署(on-premise)”的时候,SaaS的版图被大型玩家把持着,几乎所有的垂直领域(营销.支持.销售.人力)都被微软.SAP等大公司的解决方案占据.那时候的用户并没有什么“软件栈”可供选择. 第一代SaaS冠军 随着互联网的不断普及,SaaS模式开始发挥作用.第一代纯“SaaS”玩家获得了很好的发展势头.这些玩家提供的是垂直化而非水平化方案,满足了垂直领域的诸多需求. 而用户开始有了更多的选择. SaaS的第一次爆发 随着SaaS日益普及(即企业无论大小都已准

JQuery实现图片切换(自动切换+手动切换)

学习JS的时候本来积攒了很多有趣的小例子,但是苦于没有找到一些好的平台来展示这些JS效果.今天发现了RunJS这个分享代码的平台,迫不及待得想跟大家分享. 在浏览各大商城网站的时候,或者某些网站的首页,都会展示与本网站相关的一些实时切换的图片, 本文就给大家分享一个用jQuery实现图片自动切换的例子. 主页核心代码(Default.aspx): <!DOCTYPE html> <html> <head> <meta http-equiv="Conten

.NET 中获取调用方法名

在写记录日志功能时,需要记录日志调用方所在的模块名.命名空间名.类名以及方法名,想到使用的是反射(涉及到反射请注意性能),但具体是哪一块儿还不了解,于是搜索,整理如下: 需要添加相应的命名空间: using System; using System.Diagnostics; using System.Reflection; 如果仅是获取当前方法名,可以使用如下代码: public static void WriteSysLog(int level, string content) { Metho

探秘static——类不需实例化就能用?

一般情况下,需要用到某个类的时候,都必须先实例化这个类,才能对其进行调用.在编程过程中发现,有些类不用实例化就可以直接拿来使用,使用它的字段.方法等等. 这时候,靠的就是static作用.static英文意思为"静止的,静态的",在编程中可以作为修饰符,类.字段.属性.方法等被static修饰后,变为静态类.静态字段.静态属性.静态方法-- static修饰的类成为静态类,静态类中只能包含静态成员(被static修饰的字段.属性.方法),不能被实例化,不能被继承:非静态中可以包含静态成

Android 快速开发框架CommonLibsForAndroid(有Demo)

这个项目所包含的功能,全部是从实际项目中提取,开发这个类库的初衷也只是为了方便自己开发Android项目.由于时间所限,目前大量的内容还没整理到这个开源项目中,doc和demo也有所欠缺,我将尽快完善.而其中大量不合理的内容,也将逐步改进. 欢迎大家提各种意见,当然更欢迎fork和pull request. https://github.com/cymcsg/CommonLibsForAndroid CommonLibsForAndroid Using CommonLibs is a fast

PowerShell runspace 的创建,使用和查错

今天拜读了The Scripting Guy关于runspace的几篇大作,温故而知新,一些忽略的地方更为清楚. https://blogs.technet.microsoft.com/heyscriptingguy/2015/11/26/beginning-use-of-powershell-runspaces-part-1/ runspace这两年在PowerShell使用的频率越来越高,由于他的高效率,基本上很多时候已经取代了传统的Job后台操作.不管是多线程实现,或者是后台操作,亦或是入

Qt5官方demo解析集36——Wiggly Example

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集35--Music Player 今天同样带来一个有趣的小例子,如下图所示,我们输入的文字将在中央窗口显示并以正弦波形浮动. 这个例子中涉及到 Qt 定时器族中的 QBasicTimer 类以及十分实用的 QFontMetrics 类. 当我们将应用部署在移动设备上时,Qt 将为该应用添加 "-small-screen&q