Unity之NGUI插件(二)

Scrow View

  • 创建一个UI Root
  • 创建一个Sprite:
    • Pivot:中心枢纽选居中
    • Size:160x40
  • 克隆5个Sprite
  • 创建一个Grid,将6个Sprite放到Grid中
  • 选中Grid:
    • Arrangement:Vertical
    • Cell Width:160
    • Cell Height:40
      注意:这里让Cell 宽高和Sprite Size相匹配
  • 创建一个Scroll View,选中Scroll View

    • UI Scroll View脚本中:
      • Content Origin:Top
      • Movement:Vertical


  • 给Sprite添加碰撞盒

    • 选中所有的Sprite
    • 按Shift+Alt+C给Sprite添加碰撞盒(让它可以被拖动)
  • 给Sprite添加UI Drag Scroll View脚本(让它可以被拖动)
    • 选中所有Sprite
    • 在工程目录中搜索UIDragScrollView
    • 将脚本拖到所有Sprite身上


  • 给UI Drag Scroll View脚本添加实例对象
    • 将层级视图中创建的Scroll View拖到脚本中


  • 最后微调一下Grid的位置,让它跟Scroll View的顶部对应上即可

这样一个可以滚动的滚动窗口就做好了


背包

调整屏幕自适应

  • 调整屏幕分辨率
    • 点击屏幕分辨率
      • 点击最下面的加号,添加一个新的分辨率
      • Add窗口中:
        • Label:1920.1080(分辨率的标签)
        • Type:Aspect Ratio
        • Width&Height:1920:1080
        • 点击OK
  • 调整屏幕自适应
    • 创建一个UI Root


    • 选中UI Root

      • UI Root脚本中:
        • Scaling Style:Constrained
        • Content Width:1920,Fit:不勾选
        • Content Height:1080,Fit:勾选

注意:
1. 这里的Content Width、Content Height跟屏幕分辨率的宽高对应
2. 如果是横屏显示则根据高度变化自适应宽度,需要把Content Height后面的Fit勾选上;如果是竖屏显示则根据宽度变化自适应高度,需要把Content Width后面的Fit勾选上

创建背包

  • 创建一个Sprite,命名为Sprite-Cell:
    • Widget Tool:
      • Atlas:Fantasy Atlas
      • Template:Sprite
      • Sprite:Bright
      • Pivot:Center
      • Add To UI Root
    • 选中创建出的精灵
      • Pivot:居中
      • Size:80x80
  • 给Sprite-Cell添加碰撞盒

    • 选中Sprite-Cell,按Shift+Alt+C
  • 克隆15个Sprite

  • 创建一个Grid,将16个Sprite放在Grid中,选中Grid

    • Arrangement:Veritcal
    • Cell Width:80
    • Cell Height:80
    • Row Limit:4
    • Pivot:Center
  • 创建一个Sprite,命名为Sprite-BG,选中该Sprite
    • Pivot:中心
    • Depth:-1(要比Sprite-Cell的渲染深度小,以此来显示在Sprite后面)
    • Size:340x340(要比Row Limit * Sprite-Cell的整体尺寸大一些)
  • 创建一个Sprite,命名为Sprite-Head
    • 调整位置
    • Widget:
      • Pivot:居中
      • Size:340x80(调整合适即可)
    • 选中Sprite-Head,按Shift+Alt+C添加碰撞盒
    • 选中Sprite-Head,给它添加UI Drag Drop Item脚本


  • 给Sprite-Head添加Label
    • 选中Sprite-Head
    • 添加一个Label,命名为Label-Bag
      • 调整一个合适的字体大小,颜色,尺寸
  • 添加打开Button
    • 点击Atlas,选择一个Atlas


      • Select an Atlas:
        • Show All
        • 选择一个Atlas,点击Select


    • 添加Button,命名为Button-Bag
      • 选中Button-Bag,删除它的子物体Label
      • 将它放在屏幕的右下角
      • 选中它,按Shift+Alt+C给它添加碰撞盒
  • 添加关闭按钮
    • 添加一个Button,命名为Button-Close
      • 选中Button-Close,删除它的子物体
      • 将它放在Sprite-Head的右上角位置
  • 将所有的UI设置层级关系


  • 添加游戏物品预设体
    游戏物品必须是格子的子对象,所以我们选中一个Sprite-Cell,给它添加子物体作为游戏物品
    • 选中Sprite-Cell
    • 给它添加Sprite,命名为Sprite-Item
      • 设置它的大小,让它跟格子一样大(否则会出现Bug,在同一个格子中有多个游戏物品)
    • 选中Sprite-Item
    • 给它添加Label,命名为Label-Count
    • 选中Label-Count
      • Font Size:30
      • Text:1
      • Color Tint:红色
      • 调整位置在父物体的右下角
    • 将Sprite-Item拖成预设体

设置Tag

  • 选中一个游戏对象,Tag>>Add Tag


  • Tags&Layers>>Tags>>加号


  • 取一个Tag名字为“Item”,点击Save

  • 取一个Tag名字为“Cell”,点击Save


  • 将Sprite-Item和Label-Count的Tag设为“Item”,然后选中Sprite-Item,在检面板的右上角点击Apply

  • 将所有的Sprite-Cell的Tag设为“Cell”

创建BagItem脚本

  • 挂载对象:Sprite-Item预设体(因为里面的对象都是)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BagItem : UIDragDropItem {
    [HideInInspector]
    public UISprite SprItem;//游戏物品的贴图
    [HideInInspector]
    public UILabel LabItem;//游戏物品的数量

    private int count = 1;
    private int newDepth;
    private int oldDepth;


    public  void AddCount(int num)
    {
        count += num;
        LabItem.text = count.ToString();
    }

    protected override void OnDragStart()
    {
        //实现父类中原有的功能
        base.OnDragStart();
        //将游戏物品的深度调大,使它显示在页面的最上方
        SprItem.depth = newDepth;
        LabItem.depth = newDepth + 1;
    }

    protected override void OnDragEnd()
    {
        base.OnDragEnd();

        SprItem.depth = oldDepth;
        LabItem.depth = oldDepth + 1;
    }
    /// <summary>
    /// 重写的拖拽方法
    /// </summary>
    /// <param name="surface">释放时,游戏对象接触的表明,这里就是背包格子</param>
    protected override void OnDragDropRelease(GameObject surface)
    {
        base.OnDragDropRelease(surface);

        if (surface.CompareTag("Cell"))
        {//底下是一个单元格,而且单元格是空的,直接绑定父物体
            //指定父物体
            transform.parent = surface.transform;
            //对齐父物体的位置
            transform.localPosition = Vector3.zero;
        }
        else if (surface.CompareTag("Item"))
        {//底下是一个游戏物品,也就是拖到的单元格中有游戏物品,交换位置,交换父物体
            //记录单元格的Transform,接触到的游戏物品的父物体
            Transform trP = surface.transform.parent;
            //设置接触到的游戏物品的父物体设置为当前拖动游戏物品的父物体
            surface.transform.parent = transform.parent;
            surface.transform.localPosition = Vector3.zero;
            //当前拖动的游戏物体的父物体设置为trp
            transform.parent = trP;
            transform.localPosition = Vector3.zero;
        }
        else
        {
            print("删除?");
        }
    }
    //注意这里有个new!!!!
    //注意LabelItem在子物体中得到组件
    new void Start()
    {
        SprItem = GetComponent<UISprite>();
        LabItem = GetComponentInChildren<UILabel>();
        newDepth = 10;
        oldDepth = SprItem.depth;
    }

}


创建Bag脚本

  • 挂载对象:随意对象
  • 挂载对象后,指定Bag脚本上的所有数组元素
    • Cells:所有格子精灵(Sprite-Cell)
    • Equipent Names:
      • 首先把Equipent Names的Size设为4
      • 从工程目录中查找需要添加的Sprite的名字
      • 将4个Sprite的名字复制粘贴在Equipent Names数组中的4个Element(元素)中
    • Item:游戏物品预设体
      • 将游戏物品的预设体拖到Item中


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

public class Bag : MonoBehaviour {

    public GameObject[] Cells;//所有格子
    public string[] EquipentNames;//所有装备名字
    public GameObject Item;//游戏物品的预设体
    

    void Update () {
        if (Input.GetKeyDown(KeyCode.A))
        {
            PickUp();
        }
    }

    void PickUp()
    {
        int index = Random.Range(0,EquipentNames.Length);
        string name = EquipentNames[index];
        //默认背包中没有该游戏物品
        bool IsFind = false;

        //遍历单元格,查找背包中有没有
        for (int i = 0; i < Cells.Length; i++)
        {
            if (Cells[i].transform.childCount>0)
            {
                //表示背包格子有子物体
                //BagItem item = Cells[i].transform.GetChild(0).GetComponent<BagItem>();
                BagItem item = Cells[i].GetComponentInChildren<BagItem>();
                //以上两种写法都可以
                //判断子物体的精灵名称是否跟随机出来的游戏物品名称一致,
                if (item.SprItem.spriteName.Equals(name))
                {//如果一致,那么证明背包中有此物品,游戏物品数量+1
                    item.AddCount(1);
                    IsFind = true;
                    break;
                }
                
                
            }
        }

        //如果都不一致,就没有该游戏物品,克隆
        //假如没有该游戏物品
        if (!IsFind)
        {
            //找到没有游戏物品的格子
            for (int i = 0; i < Cells.Length; i++)
            {
                //如果格子是空的
                if (Cells[i].transform.childCount==0)
                {
                    //使游戏物品成为此背包格的子物体
                    GameObject g = NGUITools.AddChild(Cells[i],Item);
                    //给游戏物品替换相应的贴图
                    g.GetComponent<UISprite>().spriteName = name;
                    //调整位置
                    g.transform.localPosition = Vector3.zero;
                    //return:
                    //这里用return,用来跳出本次循环,进入下次循环
                    //也就是说当前格子判断完还要判断下个格子
                    //当所有格子遍历判断是否有子物体完毕后,才会离开循环,打印“背包已满”
                    //break:
                    //注意:在这里不要使用break,break是跳出本层循环,
                    //也就是说,如果当前格子里没有游戏物品的时候,break会跳出本层循环,去打印“背包已满”
                    //显然不合理,还没有遍历所有的格子是否都有子物体,就打印出了“背包已满”
                    return;
                }
                

            }
            print("背包已满");

        }
    }
}

到这里,已经实现了背包的拖拽、背包存放物品、背包中物品的交换


按钮触发事件

刚刚搭建好了背包的UI,以及一些功能,现在需要实现按钮的触发事件
实现按钮触发事件有两种方式:
通过NGUI控件的事件脚本和NGUI动画实现
通过自己写一个触发事件的脚本和NGUI动画实现

1.通过NGUI控件的事件脚本和NGUI动画实现

  • 首先给整个背包添加动画
    • 选中Sprite-Head
    • NGUI>>Tween>>Position,给Sprite-Head添加Tween Position脚本


  • 给它播放动画的一个初始位置和一个终点位置


  • 将Sprite-Head放在初始位置,如图


  • 选中Button-Bag:
    • 在UI Button脚本中:
      • On Click:
        • Notify:将带有动画脚本的Sprite-Head拖到这
        • Method:选为TweenPosition/PlayForward


  • 同理,选中Button-Close:
    • 其他步骤一样,就是最后Method:选为TweenPosition/PlayReverse


  • 最后将Sprite-Head身上的Tween Position脚本禁用掉

    通过以上步骤咱们实现了点击背包按钮,背包出现在UI Root上,点击关闭按钮,背包闪出UI Root

2.通过自己写一个触发事件的脚本和NGUI动画实现

  • 如果你刚刚用了第一种方式触发事件,而现在用第二种方式触发事件,你需要把刚刚在两个按钮控件上的On Click中方法取消掉,点击Notify中的减号按钮取消


  • 创建BtnEvent脚本
    • 挂载对象:随意对象
    • 实例对象:
      • Btn Open:Button-Bag
      • Btn Close:Button-Close
      • BG:Sprite-Head
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BtnEvent : MonoBehaviour
{

    public UIButton BtnOpen;
    public UIButton BtnClose;
    public UISprite BG;
    private TweenPosition tp;

    private void Awake()
    {
        tp = GetComponent<TweenPosition>();
    }

    private void OnEnable()
    {
        BtnOpen.onClick.Add(new EventDelegate(ClickBtnOpen));
        BtnClose.onClick.Add(new EventDelegate(ClickBtnClose));
    }

    private void OnDisable()
    {
        BtnOpen.onClick.Remove(new EventDelegate(ClickBtnOpen));
        BtnClose.onClick.Remove(new EventDelegate(ClickBtnClose));
    }

    void ClickBtnOpen()
    {
        tp.PlayForward();
    }

    void ClickBtnClose()
    {
        tp.PlayReverse();
    }
}

最终样式

  • 层级视图


  • 场景视图



到这里,所有的功能都实现了
按A可以随机添加物品;
可以增加物品数量;
可以交换物品位置;
鼠标按住Sprite-Head可以进行拖拽
按Button-Bag按钮可以显示背包
按Button-Close按钮可以隐藏背包


最后:NGUI的学习内容就到这里了,各位再见,加油!!!
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270