原创文章如需转载请注明:转载自雨松MOMO程序研究院本文链接地址:NGUI研究院之开始学习制作第一个例子(一)
NGUI是Unity的一个插件,使用它来制作你的游戏UI必定将事半功倍。为什么这么说呢?首先我们说说GUI与NGUI的区别,GUI是Unity自带的绘制界面工具,它的成像原理是基于表层的,所以执行效率非常的低,并且没有提供复杂的UI的接口,就算开发者硬着头皮写上去只能让UI的执行效率更低。然而NGUI 完全依赖与3D就好比在游戏世界中的摄像机直直的照射在一个平面中,在平面之上再去绘制自己的UI,所以它的执行效率会非常高。
NGUI是一款收费的插件,在Asset Store中大家可以看到价格。在未购买正版的前提下我们可以通过两种方法来使用NGUI,第一种:使用官方提供的免费版本,但是这个版本中有NGUI的水印,无法正式发布不过完全可以作为学习使用。第二种:使用别人购买过的正版插件,在互联网中有朋友放出NGUI的插件。
这里提供免费版本NGUI的下载地址,欢迎大家和MOMO一起学习
下载地址: http://www.tasharen.com/get.php?file=NGUI
插件下载完毕后打开Unity开始导入插件,首先在Project视图中右键选择Import Package->Custom Package->ngui_free.unitypackage(刚刚下载至本地的插件)导入完毕后,请刷新一下你的工程确保Unity导航菜单栏中出现NGUI的菜单项,Unity的版本不同可能导致NGUI导入时不存在菜单项,也可以退出Unity在重新进入即可。
首先在新创建的Unity工程中删除Hierarchy视图中原有的摄像机对象,在Unity导航栏菜单中选择NGUI->Create a New UI。可以理解为创建摄像机,并且这个摄像机直直的照射在平面中,该平面就是我们的UI平面。如下图所示,点击Create a New UI 菜单项后弹出UI Tool工具栏。Layer下拉列表表示摄像机的显示层,用过摄像机的都应当清楚吧? Camera下拉列表设置摄像机的朝向是2D 还是3D,最后直接点击Create Your UI即可创建一个新的界面。
接着NGUI会自动帮我们在Hierarchy视图中生成如下的对象关系。
UI ROOT(2D):看着名字我想搞程序的都应该知道是啥意思吧?界面根节点、入口点。
Camera :NGUI生成的摄像机对象,它将直直的照射在锚点面板。
Anchor:界面的锚点,影响UI的显示位置。它下面会挂着面板。
Panel:面板,摄像机照射着它,它下面会挂一些控件,比如标签、按钮、精灵、拖动条等等。
接着我们开始创建界面组件,在Unity导航菜单栏中选择NGUI-> Create a Widget创建小部件,然后选择字体与图像集合,这里先选择它自带的图像集合,后面我们在学习如何制作自己的图像集合。接着选择贴图的模板最后完成创建即可,这里我们创建一个简单的贴图。
(点击图片查看大图)
OK下面我们将材质绑定在刚刚创建的Simple Texture身上。如下图所示,Transform中是名对象的变换。
P:X、Y、Z坐标
R:X、Y、Z轴的旋转
S :X可理解为图片宽,Y理解为图片高
刚刚我们创建的模板为Simple Texture,NGUI会帮我们绑定UITexture脚本。
Material:添加的材质对象,为了让材质显示的更加清晰,我们设置材质的着色器为Unlit/Texture
Depth:表示深度,就好比UI绘制的先后顺序,数值越高越先绘制,它主要应用于Sprite精灵(后面详细说),在Simple Texture中设置无效,不过可以通过修改Z轴坐标的形式来更改绘制顺序。
Color Tint: 设置颜色,用于没有贴图的材质。
Correction:自动设置图片宽高,就好比本例中我的图片宽高是128X128,点击该按钮后会自动修改Transform中S的X = 128与Y = 128。
Pivot:贴图显示的锚点,没什么大问题。
Preview:是否在监测面板视图中预览下方我的头像贴图。
继续创建一个Simple Texture 绑定在面板中,男生和女生的头像都显示了出来 嚯嚯。如图所示最后的效果图。
OK接着我们创建一个简单的按钮,Fantasv Atlas是NGUI 资源包中自带的一组图像集合。下一篇文章中我会介绍如何自定义这个图像集合,Template中选择Button,Background选择“NGUI”,“NGUI”是Fantasv Atlas图片集合中的一个图像,我们用他做为我们的按钮背景。
然后编写简单的脚本来监听这个按钮的点击事件、这段代码的意思就是点击按钮后删除女生头像。
Test.cs
using UnityEngine; using System.Collections; public class Test : MonoBehaviour { void OnClick () { Destroy(GameObject.Find("Texture1")); } }
OnClik()方法当点击按钮时调用,前提是在UICamera脚本绑定的对象或子对象中,并且该对象具有Box Collider组件。
如下图所示,项目的结构如下。点击按钮后女生头像消失!
Button background是按钮背景图像,它是由精灵组成
Label是标签框,可以写入文本内容。
NGUI真的挺给力的!好玩!好用!有意思!哇咔咔!!
NGUI研究院之Sprite精灵与精灵动画的使用(二)
原创文章如需转载请注明:转载自雨松MOMO程序研究院本文链接地址:NGUI研究院之Sprite精灵与精灵动画的使用(二)
学习了几天Unity3D强大的NGUI插件,MOMO觉得NGUI中最大的亮点之一就是Sprite精灵。我们先说说精灵是什么东西?它可以在一张大图中去截取一部分(大图就是整体图像集合,而截取的小图就是一个精灵),然后起一个精灵的名称,使用时通过精灵的名称就能直接绘制,并且精灵还可以播放动画。总之真的非常强大。本节我们学习如何创建自己的精灵文件。
首先我们在Project中创建一个Prefab对象,默认给它Transform变换属性,暂时我们给Prefab对象起名为MySprite。接着给Prefab挂上图像集合组件。在Unity导航菜单栏中选择Component->NGUI->UI->Atlas(图像集合)即可。
常用的属性介绍:
Coordinates :UI坐标单位,用默认Pixels(像素)就行。
Pixel Size:像素的长度单位1。
Add/Delete:添加与删除精灵。
first就是当前精灵的名称,如果已添加了多个精灵都会出现在Sprite下拉列表中。再往下就是设置该精灵在大图的显示区域以及坐标,下图中我们可看到已经在整个大图中框选了一个区域,就是绿色的矩形,矩形中就是当前精灵中的内容。
下面我们将这张图片分为4块完全相等的精灵,接着我们学习在代码中如何控制这些精灵的绘制以及排序。创建脚本Test.cs并且将它挂在刚刚创建的精灵对象身上。
Test.cs
01 |
using UnityEngine; |
02 |
using System.Collections; |
03 |
using System.Collections.Generic; |
04 |
|
05 |
public class Test : MonoBehaviour { |
06 |
|
07 |
void Start() |
08 |
{ |
09 |
|
10 |
//得到精灵组件脚本 |
11 |
UISprite ui = gameObject.GetComponent<UISprite>(); |
12 |
|
13 |
//得到图像集合中精灵的数量 |
14 |
Debug.Log( "精灵的数量" + ui.atlas.spriteList.Count); |
15 |
|
16 |
//得到图像集合数组中对应角标精灵对象的名称 |
17 |
string name = ui.atlas.spriteList[2].name; |
18 |
|
19 |
//设置显示精灵的名称 |
20 |
ui.spriteName = name; |
21 |
|
22 |
//设置精灵的深度,数值越大绘制的越靠前 |
23 |
ui.depth = 2; |
24 |
} |
25 |
} |
如下图所示,精灵已经在代码中动态的修改完毕,并且设置了它的深度让它靠前显示。如果想修改它的X、Y位置,直接修改Transform即可。Z轴的话修改它的深度就行,不用修改Z轴坐标。
下面我们再来学习一下精灵动画,NGUI已经帮我们封装了专门播放精灵动画的类UISpriteAnimation 专门处理精灵动画。MOMO在网上随便找了一组2D主角的行走动画,按照上面介绍的方法将整个图片导入工程中。如下图所示,这组人物的行走动画我们选区取左移动的4帧。
这里我在强调一下,需要修改修改材质的着色器,让他支持背景透明,对当前材质的着色器我们选择Unlit/TransparentColored。
接着在Hierarchy视图中选择Sprite(NGUI)(刚刚创建的精灵对象),然后在Unity导航菜单栏中选择Component->NGUI->UI->Sprite Animation(帧动画)组件即可。此时直接运行游戏我们就会发现主角已经按照刚刚裁剪的精灵顺序动了起来,这还没有完,我们下面学习在代码中如何动态的控制精灵。
本例我们的目的是使用NGUI在屏幕中创建一个按钮,第一次点击按钮主角播放行走动画,再次点击按钮主角动画将停止。上篇文章中我们已经学习了NGUI中按钮的相应事件,如果想在别的对象或者脚本中监听某个按钮的点击事件那么就可以使用传递消息的方式。NGUI帮我们封装了一次传递消息的类,Unity导航菜单栏中选择NGUI-》Interaction->ButtonMessage。它的原理也是使用Unity的sendMessage,有兴趣的朋友可以去看看。接着说正题,创建脚本Test.cs挂在刚刚创建的按钮上。
Test.cs
01 |
using UnityEngine; |
02 |
using System.Collections; |
03 |
using System.Collections.Generic; |
04 |
|
05 |
public class Test : MonoBehaviour { |
06 |
|
07 |
//播放动画与不播放 |
08 |
bool isPlayAnim = false ; |
09 |
//得到精灵对象 |
10 |
GameObject animObj = null ; |
11 |
|
12 |
void Start() |
13 |
{ |
14 |
//得到精灵对象 |
15 |
animObj = GameObject.Find( "Sprite" ); |
16 |
|
17 |
} |
18 |
|
19 |
void OnClick () |
20 |
{ |
21 |
if (isPlayAnim) |
22 |
{ |
23 |
//停止动画 |
24 |
isPlayAnim = false ; |
25 |
//销毁UISpriteAnimation组件 |
26 |
Destroy(animObj.GetComponent<UISpriteAnimation>()); |
27 |
|
28 |
//动画停止后设置精灵默认的帧 |
29 |
UISprite ui = animObj.GetComponent<UISprite>(); |
30 |
string name = ui.atlas.spriteList[0].name; |
31 |
ui.spriteName = name; |
32 |
|
33 |
} |
34 |
else |
35 |
{ |
36 |
//播放播放 |
37 |
isPlayAnim = true ; |
38 |
//加入播放动画组件 |
39 |
animObj.AddComponent( "UISpriteAnimation" ); |
40 |
//设置播放动画的速度 |
41 |
//1-60之间数值越大播放速度越快 |
42 |
UISpriteAnimation uiAnim = animObj.GetComponent<UISpriteAnimation>(); |
43 |
uiAnim.framesPerSecond = 10; |
44 |
} |
45 |
|
46 |
} |
47 |
|
48 |
} |
如下图所示,运行游戏点击按钮。主角开始迈着大步开始行走了,再次点击主角将停止播放行走动画。嚯嚯。最后MOMO祝大家学习愉快啦啦啦!!
NGUI研究院之自制ListView动态增加与删除(三)
原创文章如需转载请注明:转载自雨松MOMO程序研究院本文链接地址:NGUI研究院之自制ListView动态增加与删除(三)
在NGUI中可以很方便的实现ListView的控件,ListView就好比IOS或Android平台中使用手势上下拖动的控件。在Unity3D中实现ListView的原理无非就两种,第一种是摄像机不动只移动控件,第二种是控件不动只移动摄像机。在官方的Demo中已经有这两种的例子,为了活灵活现的使用listView,MOMO还是决定详细的写一篇文章帮助初学者快速上手listView。
和之前的文章开始一样,我们先创建一个2D的游戏平面。接着给Panel面板绑定游戏组件,Unity导航菜单栏中选择Component->NGUI->Interaction->Grid,它主要设定ListView中每一个item的属性。继续在Unity导航菜单栏中选择Component->NGUI->Interaction->UIDraggablePanel,它主要设定listView的触摸区域以及与拖动条事件等。
如下图所示,我详细说说Panel面板中一些需要注意的属性。
UIGrid(Script):Arrangement 选择Vertical表示这个ListView表示纵向,这里如果选择Horizontal表示该ListView是横向的。
Cell Width:ListView中每一个item的宽度。
Cell Height:listView中每一个item的高度。
UIDraggable Panel(Script):选项中的Scale非常重要,这里设置y = 1 表示ListView只支持纵向的拖动,如果设置X=1表示列表只支持横向的拖动,如果两个都=1表示列表同时支持横向与纵向的拖动。
Horizontal Scroll Bar 与 Vertical Scroll Bar表示横向或纵向的拖动条与listView结合,然而这里我们无需写一行代码,它会自动帮我们计算,将你的ListView与拖动条结合。
再说说最上面的UIPanel(Script) ,我们选择Clipping的类型为SoftClip,这里可设置listView整体的显示区域。如下图所示,整体的显示区域就是紫色框中的区域。橙色框是ListView整体的显示内容,它会依次的排列下去,但是永远只会显示紫色框中的内容。
OK。接着我们看看目前工程的结构。在Hierarchy视图中Anchor下面同级的目录中有Button、Panel、Scroll Bar。Button就是上图中添加列表的按钮,Panel中是通过点击添加列表按钮后自动添加的列表预设。Scroll Bar表示上图中左侧的纵向拖动条。在右侧监测面板视图中,BoxCollider组件必须添加,该组件中Center与Size可设置ListView中的Item的触摸响应区域,这个区域应当与Item的显示区域相当。
还有一个重要的组件就是UIDrag Panel Contents(Script),如果没有它ListView就无法拖动。在Unity导航菜单栏中选择Component->NGUI->Interaction->UIDrag Panel Contents即可。切记 >_<
将预设资源放在Resources文件夹中是为了使用Resource来读取。
下面我们看看动态添加列表的脚本,把脚本绑定在Button上。噢对,这里还有个小插曲,本文中的中文字体需要感谢kuku小妖制作的:字体的下载地址如下:http://game.ceeger.com/forum/read.php?tid=729
Test.cs (为什么又是Test.cs 嚯嚯 上瘾了 改不了了 哇咔咔!!)
01 |
using UnityEngine; |
02 |
using System.Collections; |
03 |
using System.Collections.Generic; |
04 |
|
05 |
public class Test : MonoBehaviour { |
06 |
|
07 |
public UIGrid grid; |
08 |
int count = 0; |
09 |
void Start() |
10 |
{ |
11 |
//得到grid对象 |
12 |
grid = GameObject.Find( "Panel" ).GetComponent<UIGrid>(); |
13 |
} |
14 |
|
15 |
void OnClick () |
16 |
{ |
17 |
|
18 |
//克隆预设 |
19 |
GameObject o =(GameObject) Instantiate(Resources.Load( "item" )); |
20 |
//为每个预设设置一个独一无二的名称 |
21 |
o.name = "item" + count; |
22 |
//将新预设放在Panel对象下面 |
23 |
o.transform.parent = GameObject.Find( "Panel" ).transform; |
24 |
|
25 |
////下面这段代码是因为创建预设时 会自动修改旋转缩放的系数, |
26 |
//我不知道为什么会自动修改,所以MOMO重新为它赋值 |
27 |
//有知道的朋友麻烦告诉我一下 谢谢!!! |
28 |
|
29 |
GameObject item = GameObject.Find(o.name); |
30 |
item.transform.localPosition = new Vector3(0,0,0); |
31 |
item.transform.localScale= new Vector3(1,1,1); |
32 |
|
33 |
count ++; |
34 |
|
35 |
//列表添加后用于刷新listView |
36 |
grid.repositionNow = true ; |
37 |
} |
38 |
|
39 |
} |
我们在创建一个Button用于动态的删除列表。我们编写脚本Delete.cs绑定上该按钮,原理和添加差不多大家看看哈~~
Delete.cs
01 |
using UnityEngine; |
02 |
using System.Collections; |
03 |
|
04 |
public class Delete : MonoBehaviour { |
05 |
|
06 |
public UIGrid grid; |
07 |
|
08 |
void Start() |
09 |
{ |
10 |
//得到grid对象 |
11 |
grid = GameObject.Find( "Panel" ).GetComponent<UIGrid>(); |
12 |
|
13 |
} |
14 |
|
15 |
void OnClick() |
16 |
{ |
17 |
//通过标签名称找到多有对象,前提是给预设起一个tag,这里我叫它player |
18 |
GameObject []items = GameObject.FindGameObjectsWithTag( "Player" ); |
19 |
//当预设数量大于 0时 |
20 |
if (items.Length >0) |
21 |
{ |
22 |
//删除列表的item |
23 |
Destroy(items[0]); |
24 |
//刷新UI |
25 |
grid.repositionNow = true ; |
26 |
} |
27 |
|
28 |
} |
29 |
|
30 |
} |
接着我们学习点击某项Item后修改显示的内容,将如下脚本挂在item当中。
item.cs
01 |
using UnityEngine; |
02 |
using System.Collections; |
03 |
|
04 |
public class item : MonoBehaviour { |
05 |
|
06 |
void OnClick() |
07 |
{ |
08 |
//得到item自对象的精灵组建。 |
09 |
//因为得到的组建采取深度优先 |
10 |
//所以我们需要修改数组中元素为1的精灵 |
11 |
//数组中元素为0的精灵是按钮的背景 |
12 |
UISprite ui = GetComponentsInChildren<UISprite>()[1]; |
13 |
//修改头像为女生头像 |
14 |
ui.spriteName = "icon1" ; |
15 |
|
16 |
//得到文字对象 |
17 |
UILabel label = GetComponentInChildren<UILabel>(); |
18 |
//修改文字内容 |
19 |
label.text = "若若" ; |
20 |
} |
21 |
} |
如下图所示,这里本文的所有知识点,NGUI是不是很给力呢?哇咔咔!啦啦啦!
本节教学下载地址:http://115.com/file/annrwwm6#ListView.unitypackage 祝大家学习愉快,一起学习一起进步哇咔咔~~
NGUI研究院之自制 Scroll View实现触摸滚动相册效果(四)
原创文章如需转载请注明:转载自雨松MOMO程序研究院本文链接地址:NGUI研究院之自制 Scroll View实现触摸滚动相册效果(四)
MOMO与图灵合作的《Unity 3D游戏开发》没想到开售不到1个月就售罄了,心里实在是太高兴了。不过高兴归高兴,学习生活工作我是不能耽误的,加油哇咔咔。 NGUI系列的文章在上一章提到的活灵活现ListView相信大家已经熟练掌握,但是这些是满足不了程序猿的欲望的,哇咔咔~~NGUI中提供了两种Scroll View 一种是通过手指或鼠标滑动视图时移动平面物体,另一种则是直接移动摄像机,他们各有各的好处。但是NGUI提供的Scroll View很难实现类似Android 与 IOS 中的Scroll View 滚动相册的那种效果,至少MOMO没有很快的找到方法,不过程序猿的力量是伟大无穷的。虽然不能用它提供的API做出来,但是我们可以通过另外的手打巧妙的实现。不用担心MOMO会在这篇文章仔细向大家介绍如何实现自制Scroll View实现滚动相册。
如下图所示,这是我们的工程页面,程序的实现原理是将相册在Unity3D世界中呈横向队列,摄像机固定的照射在第一个Item相册,当手指发生滑动事件时,计算向左滑动还是向右滑动,此时整体移动相册队列,而摄像机不动。为了让滑动效果更加好看我们需要使用插值计算滑动的时间,使滑动队列不是直接移动过去,而是以一定惯性移动过去。相册下方我们制作一个小白点用来记录当前滑动的位置,在做几个灰色的点表示队列一共的长度,滑动时下方的小白点也会跟随移动,这样就更想高级控件啦。当然小白点与小灰点是要根据item的数量居中显示的喔。
注解1:滚动相册一般可分为两种,第一种为数量已知的情况,第二种为数量未知的情况。因为第一种比较简单所以我们主要探讨第二种。
Script historyInit.cs: 该脚本用于相册队列的初始化工作。在这里初始化相册队列的数量,计算完毕让队列以横向线性的排列方式在Unity3D中。
Prefab item:每个相册的预设,我这里每个相册上还会有一些文字的描述,我需要动态的修改它们的内容。大家也可根据自己的情况制作自己的相册item。
Prefabhui:相册滚动时下方用来记录相册队列总数的灰色小点。
Prefabbai :相册滚动时下方用来记录当前滚动页面ID的白色小点。
Point :因为灰色、白色的点不能和相册队列在一个面板之上,否则会跟着相册队列移动而移动,所以这里将灰色白色的点放在两外一个面板之上。
注解2:这个面板上的4个item就是我们通过historyinit脚本初始化时动态生成赋值的、当界面发生触摸事件时,会整体移动该面板让自对象的相册队列跟随移动。
注解3:button0 – button3 是下方的Tabar。bai(Clone)表示白色的小点,hui(Clone)表示灰色的小点,它们的位置是需要根据滑动事件而改变的。
因为我们需要监听每一个Item的滑动事件,所以肯定要在每一个item预设之上绑定监听事件的脚本,如下图所示。
注解1:因为需要监听触摸滑动事件,所以肯定要绑定Box Collider组件,这个是NGUI的标准用法。
注解2:Move脚本用来监听向左滑动 向右滑动 点击事件。
注解3:这个就是每一个相册的item,在上图中挂在historyInit脚本之上。
historyInit.cs
001 |
using UnityEngine; |
002 |
using System.Collections; |
003 |
using System.Collections.Generic; |
004 |
|
005 |
public class historyInit :MonoBehaviour |
006 |
{ |
007 |
|
008 |
//相册列表的每一个item |
009 |
public GameObject prefab; |
010 |
//灰色的小点 |
011 |
public GameObject prefabhui; |
012 |
//白色的小点 |
013 |
public GameObject prefabbai; |
014 |
//另外一个显示面板 |
015 |
//用来放置灰色、白色小点 |
016 |
public Transform ponit; |
017 |
//白色小点的临时对象 |
018 |
private GameObject bai; |
019 |
|
020 |
//链表,用来记录每一个相册中的一些用户信息 |
021 |
List<UserData> users = new List<UserData>(); |
022 |
//灰色、白色小点下方的起始位置。 |
023 |
int start; |
024 |
|
025 |
void Start () |
026 |
{ |
027 |
//将当前面板对象储存在全局静态变量中 |
028 |
Globe.ListPanel = gameObject; |
029 |
loadSQL (); |
030 |
initItem(); |
031 |
} |
032 |
|
033 |
//以前是读取数据库 |
034 |
//写例子程序就没必要使用数据库了 |
035 |
//这里直接写4个死值,当然数量是灵活使用的 |
036 |
|
037 |
void loadSQL () |
038 |
{ |
039 |
//表示一共向U3D世界中添加横向4个相册队列 |
040 |
for ( int i =0; i< 4; i ++) |
041 |
{ |
042 |
//简单的对象储存 |
043 |
string name = "momo =" + i; |
044 |
string age = "26 = " + i; |
045 |
string height = "183 =" + i; |
046 |
users.Add( new UserData(name,age,height)); |
047 |
} |
048 |
|
049 |
} |
050 |
|
051 |
void initItem() |
052 |
{ |
053 |
//因为下方灰色 白色的小点需要根据相册列表的数量来计算居中显示 |
054 |
int size = users.Count; |
055 |
//乘以16表示计算所有小点加起来的宽度 |
056 |
int length = (size - 1) * 16; |
057 |
//得到下方灰色 白色 小点的居中起始位置 |
058 |
start = (-length) >>1; |
059 |
|
060 |
for ( int i=0; i< size; i++) |
061 |
{ |
062 |
//把每一个相册加入相册列表 |
063 |
GameObject o =(GameObject) Instantiate(prefab); |
064 |
//设置这个对象的父类为 当前面板 |
065 |
o.transform.parent = transform; |
066 |
//设置相对父类的坐标,这些值可根据自己的情况而设定, |
067 |
//总之就是设置相册列表中每一个item的坐标,让它们横向的排列下来就行 |
068 |
o.transform.localPosition = new Vector3(25 + i* 243,-145f,-86f); |
069 |
//设置相对父类的缩放 |
070 |
o.transform.localScale= new Vector3(0.7349999f,0.66f,0.7349999f); |
071 |
|
072 |
//得到每一个user的信息 |
073 |
UserData data = users[i]; |
074 |
//遍历每一个相册对象的子组件, |
075 |
UILabel []label = o.GetComponentsInChildren<UILabel>(); |
076 |
//拿到UILabel并且设置它们的数据 |
077 |
label[0].text = data.age; |
078 |
label[1].text = data.height; |
079 |
label[2].text = data.name; |
080 |
|
081 |
//把每一个灰色小点加入3D世界 |
082 |
GameObject hui =(GameObject) Instantiate(prefabhui); |
083 |
//设置灰色小点的父类为另外一个面板 |
084 |
hui.transform.parent = ponit; |
085 |
//设置每一个灰色小点的位置与缩放,总之让它们居中排列显示在相册列表下方。 |
086 |
hui.transform.localPosition = new Vector3(start + i* 16,-120f,0f); |
087 |
hui.transform.localScale= new Vector3(8,8,1); |
088 |
|
089 |
//深度 因为是先在屏幕下方绘制4个灰色的小点, 然后在灰色上面绘制白色小点 |
090 |
//表示当前的窗口ID 所以深度是为了设置白色小点在灰色小点之上绘制 |
091 |
hui.GetComponent<UISprite>().depth = 0; |
092 |
} |
093 |
|
094 |
//下面的数据是把当前初始化的数据放在一个static类中 |
095 |
//在Move脚本中就可以根据这里的数据来判断了。 |
096 |
//滑动列表的长度 |
097 |
Globe.list_count = size -1; |
098 |
//相册每一项的宽度 |
099 |
Globe.list_offset = 243; |
100 |
//当前滑动的索引 |
101 |
Globe.list_currentIndex = 0; |
102 |
//点击后打开的新游戏场景 |
103 |
Globe.list_go_name= "LoadScene" ; |
104 |
|
105 |
//把白色小点也加载在3D世界中 |
106 |
bai =(GameObject) Instantiate(prefabbai); |
107 |
//设置它的深度高于 灰色小点,让白色小点显示在灰色小点之上 |
108 |
bai.GetComponent<UISprite>().depth = 1; |
109 |
//设置白色小点的位置 |
110 |
setBaiPos(); |
111 |
} |
112 |
|
113 |
void Update() |
114 |
{ |
115 |
//当用户滑动界面 |
116 |
//在Update方法中更新 |
117 |
//当前白色小点的位置 |
118 |
setBaiPos(); |
119 |
} |
120 |
|
121 |
void setBaiPos() |
122 |
{ |
123 |
//Globe.list_currentIndex 就是当前界面的ID |
124 |
//根据ID 重新计算白色小点的位置 |
125 |
bai.transform.parent = ponit; |
126 |
bai.transform.localPosition = new Vector3(start + Globe.list_currentIndex* 16,-120f,-10f); |
127 |
bai.transform.localScale= new Vector3(8,8,1); |
128 |
|
129 |
} |
130 |
} |
如下图所示,我们可以看出Tabbar 、 下方记录界面的灰色、白色小点、摄像机 它们是不会发生改变的。唯一改变的就是面板之上的相册队列。为了让滑动界面的效果更加连贯,我们需要以插值的形式来计算真个相册面板的坐标。
触摸的事件全都写在Move.cs脚本中。
01 |
using UnityEngine; |
02 |
using System.Collections; |
03 |
|
04 |
public class Move : MonoBehaviour { |
05 |
|
06 |
//是否触摸 |
07 |
bool isTouch = false ; |
08 |
//是否向左滑动 |
09 |
bool isRight = false ; |
10 |
//是否向右滑动 |
11 |
bool isLeft = false ; |
12 |
//是否正在滑动中 |
13 |
bool isOnDrag = false ; |
14 |
|
15 |
//滑动中事件 |
16 |
void OnDrag (Vector2 delta) |
17 |
{ |
18 |
//为了避免事件冲突 |
19 |
//这里只判断一个滑动的事件 |
20 |
if (!isTouch) |
21 |
{ |
22 |
if (delta.x > 0.5) |
23 |
{ |
24 |
//向左滑动 |
25 |
isRight = true ; |
26 |
isOnDrag = true ; |
27 |
} else if (delta.x < -0.5) |
28 |
{ |
29 |
//向右滑动 |
30 |
isLeft = true ; |
31 |
isOnDrag = true ; |
32 |
} |
33 |
isTouch = true ; |
34 |
} |
35 |
} |
36 |
|
37 |
//滑动后松手调用OnPress事件 |
38 |
void OnPress() |
39 |
{ |
40 |
//重新计算当前界面的ID |
41 |
if (Globe.list_currentIndex < Globe.list_count && isLeft) |
42 |
{ |
43 |
Globe.list_currentIndex++; |
44 |
} |
45 |
|
46 |
if (Globe.list_currentIndex >0 && isRight) |
47 |
{ |
48 |
Globe.list_currentIndex--; |
49 |
} |
50 |
|
51 |
//表示一次滑动事件结束 |
52 |
isTouch = false ; |
53 |
isLeft = false ; |
54 |
isRight = false ; |
55 |
} |
56 |
|
57 |
void Update() |
58 |
{ |
59 |
//这个方法就是本节内容的核心 |
60 |
//Globe.ListPanel 这个对象是我们在historyInit脚本中得到的,它用来当面相册面板对象使用插值,让面板有惯性的滑动。 |
61 |
|
62 |
//Vector3.Lerp() 这个是一个插值的方法, 参数1 表示开始的位置 参数2 表示结束的位置 参数3 表示一共所用的时间, 在Time.deltaTime * 5 时间以内 Update每一帧中得到插值当前的数值,只到插值结束 |
63 |
|
64 |
//-(Globe.list_currentIndex * Globe.list_offset) 得到当前需要滑动的目标点。 |
65 |
//请大家仔细看这个方法。 |
66 |
|
67 |
Globe.ListPanel.transform.localPosition =Vector3.Lerp(Globe.ListPanel.transform.localPosition, new Vector3(-(Globe.list_currentIndex * Globe.list_offset),0,0), Time.deltaTime * 5); |
68 |
} |
69 |
|
70 |
void OnClick () |
71 |
{ |
72 |
//当点击某个item时进入这里 |
73 |
|
74 |
if (!isOnDrag) |
75 |
{ |
76 |
//如果不是在拖动中 进入另一个场景 |
77 |
Application.LoadLevel(Globe.list_go_name); |
78 |
} |
79 |
else |
80 |
{ |
81 |
//否则等待用户重新发生触摸事件 |
82 |
isOnDrag = false ; |
83 |
} |
84 |
} |
85 |
} |
还有两个辅助的类,我也贴出来。
UserData.cs
01 |
using UnityEngine; |
02 |
using System.Collections; |
03 |
|
04 |
public class UserData{ |
05 |
|
06 |
public string name; |
07 |
public string age; |
08 |
public string height; |
09 |
public string hand; |
10 |
|
11 |
public UserData( string _name, string _age, string _height) |
12 |
{ |
13 |
age = _age; |
14 |
height = _height; |
15 |
name = _name; |
16 |
} |
17 |
|
18 |
} |
Globe.cs 这个静态类用来共享记录多个脚本甚至多个场景所需的数据。
01 |
using System.Collections.Generic; |
02 |
public class Globe |
03 |
{ |
04 |
|
05 |
public static GameObject ListPanel; |
06 |
public static int list_count; |
07 |
public static int list_currentIndex; |
08 |
public static int list_offset; |
09 |
public static string list_go_name; |
10 |
|
11 |
} |
写到这里,本篇博文就写的差不多了。这篇文章我是用NGUI来实现的触摸滚动效果,仔细想想,其实不用NGUI完全也能实现这样的效果。在脚本中完全可以通过射线 以及 触摸的时间去计算当前用户操作的事件,这篇文章里的工程最后我是打包在Android上面的,效果挺不错,滑动的效果图不好截取我也不截取了,主要还是文章的书写内容,希望大家学习愉快,雨松MOMO祝大家晚安,哇咔咔,啦啦啦。
NGUI研究院之开发项目的一些使用心得比较细节(五)
原创文章如需转载请注明:转载自雨松MOMO程序研究院本文链接地址:NGUI研究院之开发项目的一些使用心得比较细节(五)
不知不觉MOMO使用NGI插件已经有一段时间了,感觉NGUI真的是目前Unity3D中最好用的UI插件。但是它也有一些不是BUG的BUG,这些问题可能会让新人摸不着头脑,那么这篇文章MOMO将总结一下这段时间用NGUI的一些开发心得,这些也好几个朋友问题我的一些问题,我将这些东西列出来。 哇咔咔~
1.对图片的限制
如果是移动平台中iPhone 或Android请保持的你的图片尺寸在小于等于1024 X 1024 ,否则载入的图片将无法显示,绘制图片的地方会是一片黑漆漆的东西,PC平台的话图片最大使用的尺寸是4096X4096 。
注意!这还没完、如下图所示,无论在任何平台中请保持你的图片宽或高的尺寸和下图中的一样。比如 32X32 、32X64 、 128 X 32、 1024 X519、 1024 X1024、 512 X 32 像这样和下图所出现的尺寸数值一样的比例才行。
举个例子,比如美术给你出了一张960X640的图片,此时你直接放在程序中,NGUI会自动将这张图片拉伸。所以你需要让美术把这张960X640的图片放在1024X1024 尺寸的图中给你,这样图片就不会拉伸了,如下图所示,就好像这样,这张图的尺寸是 1024X1024 但是程序中通过精灵切割的只是 960X640这部分,所以这个图就不会在iPhone或Android中拉伸。
接着是材质,对材质着色器的选择也有一点要求.如下图所示,请选择你的材质着色器为Unlit/Transparent Colored 如果你选择的不是它将会造成你的UI无法显示背景透明的图片喔。
2.精灵预设或者字体预设
在导航栏中创建用NGUI创建一个新UI后,并且在Project视图中已经创建了精灵预设和字体预设后。然后在Panel(面板)中创建新部件时,如下图所示,点击Atlas 或 Font后如果发现找不到对应的预设。不要紧张其实很简单,只需你将Project视图中的精灵或字体预设先拖拽至Hierarchy视图中,此时在重新点击创建新部件,然后在点击Atlas或Font就会出现你需要的精灵或字体预设。选择完毕再将Hierarchy视图中拖拽的预设删掉即可。 对于任何一个新精灵预设或字体预设都要用一次这样的方法,再次使用就不会出现这个问题。
(补充,引用评论中的一句,鼠标在Project视图中点一下就可以 感谢回复~~)
3.在3D世界之上创建你的UI。
比如3D游戏中界面中选择技能、物品、人物状态等的一些UI。这些UI不会以因主角移动而发生位置的改变,并且永远出现在界面最前面。如下图所示,把你游戏世界中原本的摄像机放在UI Root (2D)下面,并且让所有的UI都是这个Camera的子类,这么做是为了解决摄像机发生移动后所有的UI也能和他保持原本的距离关系,至于其它的3D游戏对象请保持与UI Root (2D) 为同级关系即可。因为需要显示3D物体,请设置你的摄像机Projection为Perspective。
4.Scroll View列表的显示区域
如何修改Scroll View列表的显示区域。这个问题我记得有好几个朋友都问过我,我觉得这个问题是NGUI的一个BUG。 但是我们使用另外一种方式可以很好的解决这个问题,那么MOMO和大家说说我的开发心得。
如下图所示,在这里可以修改ScrollView中整体的显示区域,但是请注意这里紧紧是修改它的显示区域,,因为之前设定在ScrollView中的item的位置是不会因为scrollView显示区域的修改而修改。建议修改ScrolleView显示的宽 和高 在这里修改,但是显示的X Y轴坐标就不要在这里改了,因为改了也没用。
如果你要修改Scroll View显示X Y轴坐标的话,如下图所示,直接在Hierarchy视图中选择ScrollView显示的父面板对象,然后在Scene视图中更改这个对象的XYZ坐标即可,这样对应下方所有的ScrollView 的item也会跟着修改。继而达到完美修改NGUI ScrollView的显示区域喔。
最后,这篇文章也没什么代码,不过MOMO希望能给一些刚刚入门NGUI的朋友一些帮助,哇咔咔。