NGUI源码路径: cbbbc_CSDN博客
NGUI的UIScrollview的实现原理_chrisfxs的专栏-CSDN博客_ngui原理
NGUI的原理机制:深入剖析UIPanel,UIWidget,UIDrawCall底层原理 - zhibolife - 博客园 //深入剖析UIPanel,UIWidget,UIDrawCall底层原理
Unity-NGUI-Depth分配 - 知乎 //Unity-NGUI-Depth分配
Unity3D_NGUI_性能优化实践_CPU卡顿 - 大表哥的笔记 - 博客园 //NGUI优化
完美像素: 使得像素匹配屏幕,意味着你的UI在高分辨率的设备上看起来更小,在低分辨率设备上看起来更大,但是它总是尽可能的清晰。
Lable:
Overflow: 字体溢出时的操作
Resize Height: 溢出时调整高度的尺寸,其实就是限宽。
Resize Freely: 溢出时自由调整。 其实就是限高。
Alignment: 对齐方式。
<1. 自动对齐,默认是使用居中对齐。
Sprite
Panle
Button:
添加BoxColider(ngui中的)组件和Button组件。
UnityVS插件是连接vs2012和unity之间交互的。
Lable_Button 点击后改变lable;
Sprite_Button 点击后改变Sprite;
Sprite_Button和Lable_Button组合使用:
每个附加的UI Button脚本都有一个Target目标,表示当点击时,控制目标物件的一些变化。所以在组合使用时,
给Sprite_Button再加一个Button脚本组件(黏贴一个组件),用来控制点击时对lable的变化。
问题:ugui自定义的button,在第一次鼠标移动进去时放在button上,直接点击时,第一次没反应。必须要先在场景里点击一下,捕获到鼠标之后再点击才有反应 ????; UGUI是可以的。
打包图集:导入图片;创建图集,new一个,更新,删除;
自己发现:
<1. 图集的大小取决于打包的图片的大小,可以把小图打到一个图集里;
<2. 同时使用的atlas的数量降低到最小;
九宫切图
NGUI使用动态字体:
动态字体:不是图集的一部分,增加drawcall;
静态字体:是图集的一部分,把固定的汉字写到一个图片上。
Widget 支点、锚点
Pivot: 位置,左中右、上中下;
deph: 小->深
snap: 恢复到原来的大小
appect: 比例,设置大小。
11. Anchor:
固定死各个边的距离后,来调整物件的大小。不设置Anchor时,默认是以中心点保持不变。
图片的左边框的位置和target的中心点(左边框、右边框等 +- value)保持不变。
Target: 是目标物体(在这里指ui root)的中心点或者左右边框的位置。
<1. 即 Left=Target Center+(-50) 这段的距离大小是保持不变,表现在试图中,则框出的距离保持不变。
<2. 如果Left=Target Left+(234),即图片的左边框+234这段距离是保持不变的。在自适应时,则会改变图片的宽度来使得这个距离保持不变。
<3. 保持图片大小不变,相对右上角的位置也是不变;
<4. 保持图片大小不变,相对中心的位置也是不变;
SH_moyu:
目标右侧,加10的位置为当前lab的左侧锚点。修改后没自动变,则需要ctrl+s保存下看
12.Itween
缩放、位置、旋转
13.Slider滑动条
<1. creat sprite-->add boxcolider-->add slider script
<2. creat foreBG-->creat thumb(设置anthor)-->creat lable
<3. 设置slider的Notify通知,来通知SetCurrentPrecent()
背景和游标自己控制
15.设置声音、文字打印机
添加声音: 直接添加playsound组件就可以了。
添加打印机效果:给lable添加Typewrtier Effect组件就可以;
17.Popup List 设置下拉列表
creat sprite-->add boxcolider-->add ui popup list-->add notify (SetCrrentSelect())
特别要注意此处的字的大小要一直!!! ui popup list组件中的字体要设置成bitmap的默认字体;
注意:
下拉列表中不要有空格;
对下拉列表的值进行取空格操作:UIPopupList.current.value.Trim()
18. CheckBox 单选框的创建
creat sprite-->add boxcolider&toggle - creat sprite(toggle)
20.获取控件的值
<1. 直接拖。
<2.获取当前正在操作的引用。 UIPopupList.current.value.Trim()
22. 技能冷却
23.在输入框中输入单行文本和多行文本
单行和多行; 回车;
creat sprite-->add BoxColider & InputField-->creat lable
怎么自动拉长出入便捷???
24.用户名,密码
ngui做了基本的校验;限制数字,长度,passward,Name(会自动的进行首字母大写)
怎么自动调用小键盘???
26.添加可拖拽和调节大小的功能
在ngui编辑器下是没有的,需要手动添加脚本,UIDragObject.cs即可拖拽;
添加小控件,调节UI大小。UIDragResize.cs
27.创建ScrollBar滚动条;
value: 滑块可以移动的区域 设置walue=0时,即滑块是在左边; size:滑块的大小
28. 创建可滑动的Lable:
29\30\31 设计聊天框并且设置Anchor
32.使用脚本控制内容显示,输入事件交互
控制输入,添加到面板中UITextList中。
33. 物体添加拖拽功能和事件监听。
UIDragDropItem.cs 是拖和放。自动生成格子??
34,35,36:
protected override void OnDragDropStart()
{
base.OnDragDropStart();
uiSprite.depth++;
}
protected override void OnDragDropRelease(GameObject surface)
{
base.OnDragDropRelease(surface);
if(surface==null)
{
this.transform.localPosition = Vector3.zero;
}
else if (surface.CompareTag("cell"))
{
this.transform.parent = surface.transform;
this.transform.localPosition = Vector3.zero;
}
else if (surface.CompareTag("knapsack_item"))
{
Transform parent = surface.transform.parent;
//把原格子的物品移到新格子的父物体中
surface.transform.parent = this.transform.parent;
surface.transform.localPosition = Vector3.zero;
//放置新物体
this.transform.parent = parent;
this.transform.localPosition = Vector3.zero;
}
uiSprite.depth--;
}
38.血条和3D跟随
HUD Text插件 , creat processSlider -->add UIFollowTarget.cs;
注意:需要把添加了UIFollowTarget.cs脚本的物体的localposition置为0,否则跟随不准确;
39.显示伤害和治疗效果
add HUDText.cs->add 文字;
主要功能是飘字,可以设置美术字体和动态字体;结合跟随使用;
40 .ScrollView :滚动视口组件 滑动窗; 设置滑动窗的位置。
UIGrid:
要reset,它应该和item的大小保持一致。方便位置的对齐;添加UIGrid.cs,会自动跳转item之间的相对位置,设置item在父级中的对齐方式。给UIGrid添加组件UICenterOnChild.cs ,使得当滑动item时该item在ScrollView中自动居中居中。注意,此时不再进行uigrid头和尾的居中。
Item:
item 要reset。添加UIDragScrollView.cs,会使得item有滑动功能。
UICenterOnClick.cs: 使得当点击item时该item在ScrollView中自动居中居中。
ScrollView、Grid和Table: NGUI学习笔记(六):ScrollView、Grid和Table - 阿诚de窝 - 博客园
Table
Grid是对子项进行水平或垂直的排序,而Table是对子项进行可换行的排序。
Table是以Table的左上角开始排序,而Grid是以Grid的center点开始排序;
Table设置 :
Grid设置:
Grid和Table的混合使用:
优化: 三个Item_Table,来循环使用;使用BagWrapContent.cs来实现循环;需要配合UIScrollView.cs->ContentOrigin和Movement;
using UnityEngine;
using System.Collections.Generic;
public class BagWrapContent : MonoBehaviour {
/// <summary>
/// Width or height of the child items for positioning purposes.
/// </summary>
public int itemSize = 100;
/// <summary>
/// Maximum allowed index for items. If "min" is equal to "max" then there is no limit.
/// For vertical scroll views indices increment with the Y position (towards top of the screen).
/// </summary>
public int maxIndex = 0;
public int minIndex = 0;
protected bool mHorizontal = false;
protected Transform mTrans;
protected UIPanel mPanel;
protected UIScrollView mScroll;
List<Transform> mChildren = new List<Transform>();
// Use this for initialization
void Start()
{
if (!CacheScrollView()) return;
mPanel.onClipMove = WrapContent;
mChildren.Clear();
for (int i = 0; i < mTrans.childCount; ++i)
mChildren.Add(mTrans.GetChild(i));
}
/// <summary>
/// Cache the scroll view and return 'false' if the scroll view is not found.
/// </summary>
protected bool CacheScrollView()
{
mTrans = transform;
mPanel = NGUITools.FindInParents<UIPanel>(gameObject);
mScroll = mPanel.GetComponent<UIScrollView>();
if (mScroll == null) return false;
if (mScroll.movement == UIScrollView.Movement.Horizontal) mHorizontal = true;
else if (mScroll.movement == UIScrollView.Movement.Vertical) mHorizontal = false;
else return false;
return true;
}
public void WrapContent(UIPanel panel)
{
float extents = itemSize * mChildren.Count * 0.5f;
Vector3[] corners = mPanel.worldCorners;
for (int i = 0; i < 4; ++i)
{
Vector3 v = corners[i];
v = mTrans.InverseTransformPoint(v);
corners[i] = v;
}
Vector3 center = Vector3.Lerp(corners[0], corners[2], 0.5f);
float ext2 = extents * 2f;
if (mHorizontal)
{
//float min = corners[0].x - itemSize; //Remove Unused
//float max = corners[2].x + itemSize; //Remove Unused
for (int i = 0, imax = mChildren.Count; i < imax; ++i)
{
Transform t = mChildren[i];
float distance = t.localPosition.x - center.x;
if (distance < -extents)
{
Vector3 pos = t.localPosition;
pos.x += ext2;
distance = pos.x - center.x;
int realIndex = Mathf.RoundToInt(pos.x / itemSize);
if (minIndex == maxIndex || (minIndex <= realIndex && realIndex <= maxIndex))
{
t.localPosition = pos;
UpdateItem(t, i);
}
}
else if (distance > extents)
{
Vector3 pos = t.localPosition;
pos.x -= ext2;
distance = pos.x - center.x;
int realIndex = Mathf.RoundToInt(pos.x / itemSize);
if (minIndex == maxIndex || (minIndex <= realIndex && realIndex <= maxIndex))
{
t.localPosition = pos;
UpdateItem(t, i);
}
}
}
}
if (mHorizontal == false)
{
test(center, extents, ext2);
}
}
public void test(Vector3 center,float extents, float ext2)
{
if (mHorizontal == false)
{
for (int i = 0, imax = mChildren.Count; i < imax; ++i)
{
Transform t = mChildren[i];
float distance = t.localPosition.y - center.y;
if (distance < -extents)
{
Vector3 pos = t.localPosition;
pos.y += ext2;
distance = pos.y - center.y;
int realIndex = Mathf.RoundToInt(pos.y / itemSize);
if (minIndex == maxIndex || (minIndex <= realIndex && realIndex <= maxIndex))
{
t.localPosition = pos;
UpdateItem(t, i);
}
}
else if (distance > extents)
{
Vector3 pos = t.localPosition;
pos.y -= ext2;
distance = pos.y - center.y;
int realIndex = Mathf.RoundToInt(pos.y / itemSize);
if (minIndex == maxIndex || (minIndex <= realIndex && realIndex <= maxIndex))
{
t.localPosition = pos;
}
}
}
}
}
protected virtual void UpdateItem(Transform item, int index)
{
if (onInitializeItem != null)
{
if (mHorizontal == true)
{
int realIndex = Mathf.RoundToInt(item.localPosition.x / itemSize);
item.GetComponent<UIData>().mIndex = realIndex + 1;
onInitializeItem(item.gameObject, realIndex + 1);
}
if (mHorizontal == false )
{
int realIndex = Mathf.RoundToInt(item.localPosition.y / itemSize);
item.GetComponent<UIData>().mIndex = realIndex + 1;
onInitializeItem(item.gameObject, realIndex + 1);
}
}
}
public delegate void OnInitializeItem(GameObject go, int realIndex);
public OnInitializeItem onInitializeItem;
}
UGUI深度的问题:
<1. Panel会把材质相同(shader)的图集进行合并;图集不同,图片相同也会增加drawcall;这是为什么每个功能面板用Panel的原因,但是如果太多也不行,因为稍微改变下面板的子物体,则会发生重绘。
Panel Widget DrawCall 三者之间的关系如下:
<1. 不同Panel,图集相同,drawcall不能合并;
<2. 同一个Panel,图集不同,不能合并;
<3. 同一个Panel,图集相同,但是由于中间(depth之间)有夹层(有个不同的图集),则不能合并drawcall;
<4. 嵌套Panel不影响drawcall的个数,Panel和Panel之间是并列的;其实还是看之间是不是有不同材质出现在夹层中。
一定要有材质,且夹在depth中间;
<5. Layer>SubLayer>depth
Layer=SubLayer1+SubLayer2+SubLayer3...;
SubLayer=depth1+depth2+depth3...
触发FillAllDrawCalls():
Sprite:
<1. 切换图片不会引发FillAllDrawCalls()和UIDrawCall.Create();//如果
<2. 换另一个图集里的图片引发重建FillAllDrawCalls()和UIDrawCall.Create();切换时,之前创建的drawcall是被加入到mInctiveList.此时Lable,重建重建dc[从mInctiveList去一个]。
其他情况,除了改变depth,都不会触发。
<3Text:
<4. 添加 改变字体,对字体的所有操作都会触发FillAllDrawCalls();
<5. 设置
SetActive(false)=>RemoveFromPanel()删除此widget,调用FillAllDrawCalls(),然后更新删除后的panel的drawcall;
SetActive(true) ,添加widget,调用FillAllDrawCalls(),更新panel的drawcall;