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
- UI Scroll View脚本中:
-
给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:勾选
- UI Root脚本中:
-
注意:
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
- Widget Tool:
-
给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
- Select an Atlas:
- 添加Button,命名为Button-Bag
- 选中Button-Bag,删除它的子物体Label
- 将它放在屏幕的右下角
- 选中它,按Shift+Alt+C给它添加碰撞盒
-
- 添加关闭按钮
- 添加一个Button,命名为Button-Close
- 选中Button-Close,删除它的子物体
- 将它放在Sprite-Head的右上角位置
- 添加一个Button,命名为Button-Close
-
将所有的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
- On Click:
- 在UI Button脚本中:
- 同理,选中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按钮可以隐藏背包