UGUI 学习
1. Grid Layout Group(网格布局)
Hierachy:

Game:

属性和功能:

2. 根据鼠标位置旋转界面实现:
public class TiltWindow : MonoBehaviour
{
public Vector2 range = new Vector2(5f, 3f); Transform mTrans;
Quaternion mStart;
Vector2 mRot = Vector2.zero; void Start ()
{
mTrans = transform;
mStart = mTrans.localRotation;
} void Update ()
{
Vector3 pos = Input.mousePosition; float halfWidth = Screen.width * 0.5f;
float halfHeight = Screen.height * 0.5f;
float x = Mathf.Clamp((pos.x - halfWidth) / halfWidth, -1f, 1f);
float y = Mathf.Clamp((pos.y - halfHeight) / halfHeight, -1f, 1f);
mRot = Vector2.Lerp(mRot, new Vector2(x, y), Time.deltaTime * 5f); mTrans.localRotation = mStart * Quaternion.Euler(-mRot.y * range.y, mRot.x * range.x, 0f);
}
}
3. 按钮动画实现:
修改 Transisition 为 Animation,设置触发器

在 Animator 设计状态机

4. HorizontalLayoutGroup(垂直布局)
Hierachy:

Game:

属性和功能:

5. 拖拽功能实现
Hierarchy(其中 Panel 中 Image 绑定 DragMe,Panel2,Panel3 中 Image 绑定 DropMe):

public class DragMe : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
public bool dragOnSurfaces = true; private Dictionary<int,GameObject> m_DraggingIcons = new Dictionary<int, GameObject>();
private Dictionary<int, RectTransform> m_DraggingPlanes = new Dictionary<int, RectTransform>(); // 开始拖拽
// 创建拖拽图片的 clone 体
public void OnBeginDrag(PointerEventData eventData)
{
var canvas = FindInParents<Canvas>(gameObject);
if (canvas == null)
return; // We have clicked something that can be dragged.
// What we want to do is create an icon for this.
m_DraggingIcons[eventData.pointerId] = new GameObject("icon"); m_DraggingIcons[eventData.pointerId].transform.SetParent (canvas.transform, false);
m_DraggingIcons[eventData.pointerId].transform.SetAsLastSibling(); var image = m_DraggingIcons[eventData.pointerId].AddComponent<Image>();
// The icon will be under the cursor.
// We want it to be ignored by the event system.
var group = m_DraggingIcons[eventData.pointerId].AddComponent<CanvasGroup>();
group.blocksRaycasts = false; image.sprite = GetComponent<Image>().sprite;
image.SetNativeSize(); if (dragOnSurfaces)
m_DraggingPlanes[eventData.pointerId] = transform as RectTransform;
else
m_DraggingPlanes[eventData.pointerId] = canvas.transform as RectTransform; SetDraggedPosition(eventData);
} // 正在拖拽
// 更新拖拽物位置
public void OnDrag(PointerEventData eventData)
{
if (m_DraggingIcons[eventData.pointerId] != null)
SetDraggedPosition(eventData);
} // 根据鼠标位置更新拖拽物位置和旋转
private void SetDraggedPosition(PointerEventData eventData)
{
if (dragOnSurfaces && eventData.pointerEnter != null && eventData.pointerEnter.transform as RectTransform != null)
m_DraggingPlanes[eventData.pointerId] = eventData.pointerEnter.transform as RectTransform; var rt = m_DraggingIcons[eventData.pointerId].GetComponent<RectTransform>();
Vector3 globalMousePos;
if (RectTransformUtility.ScreenPointToWorldPointInRectangle(m_DraggingPlanes[eventData.pointerId], eventData.position, eventData.pressEventCamera, out globalMousePos))
{
rt.position = globalMousePos;
rt.rotation = m_DraggingPlanes[eventData.pointerId].rotation;
}
} // 结束拖拽
// 销毁克隆体
public void OnEndDrag(PointerEventData eventData)
{
if (m_DraggingIcons[eventData.pointerId] != null)
Destroy(m_DraggingIcons[eventData.pointerId]); m_DraggingIcons[eventData.pointerId] = null;
} // 在父亲节点中寻找 T 组件
static public T FindInParents<T>(GameObject go) where T : Component
{
if (go == null) return null;
var comp = go.GetComponent<T>(); if (comp != null)
return comp; var t = go.transform.parent;
while (t != null && comp == null)
{
comp = t.gameObject.GetComponent<T>();
t = t.parent;
}
return comp;
}
}
public class DropMe : MonoBehaviour, IDropHandler, IPointerEnterHandler, IPointerExitHandler
{
public Image containerImage;
public Image receivingImage;
private Color normalColor;
public Color highlightColor = Color.yellow; public void OnEnable ()
{
if (containerImage != null)
normalColor = containerImage.color;
} // 放置图片
public void OnDrop(PointerEventData data)
{
containerImage.color = normalColor; if (receivingImage == null)
return; Sprite dropSprite = GetDropSprite (data);
if (dropSprite != null)
receivingImage.overrideSprite = dropSprite;
} // 鼠标移入
// 背景高亮
public void OnPointerEnter(PointerEventData data)
{
if (containerImage == null)
return; Sprite dropSprite = GetDropSprite (data);
if (dropSprite != null)
containerImage.color = highlightColor;
} // 鼠标移出
public void OnPointerExit(PointerEventData data)
{
if (containerImage == null)
return; containerImage.color = normalColor;
} // 得到拖拽图片
private Sprite GetDropSprite(PointerEventData data)
{
var originalObj = data.pointerDrag;
if (originalObj == null)
return null; var dragMe = originalObj.GetComponent<DragMe>();
if (dragMe == null)
return null; var srcImage = originalObj.GetComponent<Image>();
if (srcImage == null)
return null; return srcImage.sprite;
}
}
6. 拖拽改变面板位置(屏幕坐标到本地坐标的转换)
public class DragPanel : MonoBehaviour, IPointerDownHandler, IDragHandler {
private Vector2 originalLocalPointerPosition;
private Vector3 originalPanelLocalPosition;
private RectTransform panelRectTransform;
private RectTransform parentRectTransform;
void Awake () {
panelRectTransform = transform.parent as RectTransform;
parentRectTransform = panelRectTransform.parent as RectTransform;
}
public void OnPointerDown (PointerEventData data) {
originalPanelLocalPosition = panelRectTransform.localPosition;
// 屏幕坐标转成本地坐标
RectTransformUtility.ScreenPointToLocalPointInRectangle (parentRectTransform, data.position, data.pressEventCamera, out originalLocalPointerPosition);
}
public void OnDrag (PointerEventData data) {
if (panelRectTransform == null || parentRectTransform == null)
return;
Vector2 localPointerPosition;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle (parentRectTransform, data.position, data.pressEventCamera, out localPointerPosition)) {
Vector3 offsetToOriginal = localPointerPosition - originalLocalPointerPosition;
panelRectTransform.localPosition = originalPanelLocalPosition + offsetToOriginal;
}
ClampToWindow ();
}
// 将面板限制在父组件之内
// Clamp panel to area of parent
void ClampToWindow () {
Vector3 pos = panelRectTransform.localPosition;
Vector3 minPosition = parentRectTransform.rect.min - panelRectTransform.rect.min;
Vector3 maxPosition = parentRectTransform.rect.max - panelRectTransform.rect.max;
pos.x = Mathf.Clamp (panelRectTransform.localPosition.x, minPosition.x, maxPosition.x);
pos.y = Mathf.Clamp (panelRectTransform.localPosition.y, minPosition.y, maxPosition.y);
panelRectTransform.localPosition = pos;
}
}
7. 拖拽改变面板大小
public class ResizePanel : MonoBehaviour, IPointerDownHandler, IDragHandler {
public Vector2 minSize = new Vector2 (, );
public Vector2 maxSize = new Vector2 (, );
private RectTransform panelRectTransform;
private Vector2 originalLocalPointerPosition;
private Vector2 originalSizeDelta;
void Awake () {
panelRectTransform = transform.parent.GetComponent<RectTransform> ();
}
public void OnPointerDown (PointerEventData data) {
originalSizeDelta = panelRectTransform.sizeDelta;
RectTransformUtility.ScreenPointToLocalPointInRectangle (panelRectTransform, data.position, data.pressEventCamera, out originalLocalPointerPosition);
}
public void OnDrag (PointerEventData data) {
if (panelRectTransform == null)
return;
Vector2 localPointerPosition;
RectTransformUtility.ScreenPointToLocalPointInRectangle (panelRectTransform, data.position, data.pressEventCamera, out localPointerPosition);
Vector3 offsetToOriginal = localPointerPosition - originalLocalPointerPosition;
// 根据鼠标偏移改变窗口大小
Vector2 sizeDelta = originalSizeDelta + new Vector2 (offsetToOriginal.x, -offsetToOriginal.y);
sizeDelta = new Vector2 (
Mathf.Clamp (sizeDelta.x, minSize.x, maxSize.x),
Mathf.Clamp (sizeDelta.y, minSize.y, maxSize.y)
);
panelRectTransform.sizeDelta = sizeDelta;
}
}
8. 根据滑动条调节光源颜色
效果图:

先设置 Slider 的 OnValueChange(其他两个同理) :

public class ChangeColor : MonoBehaviour, IPointerClickHandler
{
public void SetRed(float value)
{
OnValueChanged(value, );
} public void SetGreen(float value)
{
OnValueChanged(value, );
} public void SetBlue(float value)
{
OnValueChanged(value, );
} public void OnValueChanged(float value, int channel)
{
Color c = Color.white; if (GetComponent<Renderer>() != null)
c = GetComponent<Renderer>().material.color;
else if (GetComponent<Light>() != null)
c = GetComponent<Light>().color; c[channel] = value; if (GetComponent<Renderer>() != null)
GetComponent<Renderer>().material.color = c;
else if (GetComponent<Light>() != null)
GetComponent<Light>().color = c;
}
}
9. 面板切换
效果图:

面板管理代码:
public class PanelManager : MonoBehaviour {
public Animator initiallyOpen;
private int m_OpenParameterId;
private Animator m_Open;
private GameObject m_PreviouslySelected;
const string k_OpenTransitionName = "Open";
const string k_ClosedStateName = "Closed";
public void OnEnable()
{
// 根据参数名字得到id
m_OpenParameterId = Animator.StringToHash (k_OpenTransitionName);
if (initiallyOpen == null)
return;
// 打开初始面板
OpenPanel(initiallyOpen);
}
// 打开面板
public void OpenPanel (Animator anim)
{
if (m_Open == anim)
return;
anim.gameObject.SetActive(true);
var newPreviouslySelected = EventSystem.current.currentSelectedGameObject;
// 最先显示
anim.transform.SetAsLastSibling();
CloseCurrent();
m_PreviouslySelected = newPreviouslySelected;
m_Open = anim;
m_Open.SetBool(m_OpenParameterId, true);
GameObject go = FindFirstEnabledSelectable(anim.gameObject);
SetSelected(go);
}
static GameObject FindFirstEnabledSelectable (GameObject gameObject)
{
GameObject go = null;
var selectables = gameObject.GetComponentsInChildren<Selectable> (true);
foreach (var selectable in selectables) {
if (selectable.IsActive () && selectable.IsInteractable ()) {
go = selectable.gameObject;
break;
}
}
return go;
}
// 关闭当前面板
public void CloseCurrent()
{
if (m_Open == null)
return;
m_Open.SetBool(m_OpenParameterId, false);
SetSelected(m_PreviouslySelected);
StartCoroutine(DisablePanelDeleyed(m_Open));
m_Open = null;
}
// 关闭面板
IEnumerator DisablePanelDeleyed(Animator anim)
{
bool closedStateReached = false;
bool wantToClose = true;
while (!closedStateReached && wantToClose)
{
if (!anim.IsInTransition())
closedStateReached = anim.GetCurrentAnimatorStateInfo().IsName(k_ClosedStateName);
wantToClose = !anim.GetBool(m_OpenParameterId); // 关闭的时候可打断
yield return new WaitForEndOfFrame(); // 等待关闭动画播放完
}
if (wantToClose)
anim.gameObject.SetActive(false);
}
private void SetSelected(GameObject go)
{
EventSystem.current.SetSelectedGameObject(go);
}
}
10. RenderTexure 在 UI 上显示模型
设置 Camera TargetTexture,将 相机内容渲染到 RenderTexure 中。

添加 RawImage,设置 Texture 为之前的 RenderTexture。

效果图:

11. 图片遮挡(Mask,ScrollRect)
Hierarchy:

在 GameObject 中添加组件:

效果图:

UGUI 学习的更多相关文章
- Unity3D UGUI学习系列索引(暂未完成)
U3D UGUI学习1 - 层级环境 U3D UGUI学习2 - Canvas U3D UGUI学习3 - RectTransform U3D UGUI学习4 - Text U3D UGUI学习5 - ...
- Unity3D之UGUI学习笔记(三):EventSystem
在UGUI中,EventSystem实现了所有关于交互方面的功能,和NGUI不一样的地方是,我们终于可以摆脱添加Box Collider了! 下面我们来学习一下. 对于按钮来说,直接有onClick的 ...
- Unity3D之UGUI学习笔记(一):UGUI介绍以及Canvas
UGUI是Unity3D4.6官方提供的UI系统,支持2D和3D UI的开发. Unity3D UI史 OnGUI 在Unity4.6之前,官方提供的是OnGUI函数来开发UI界面,当然问题也比较多, ...
- UGUI 学习笔记
1.UGUI中是没有depth的概念,那要怎么在脚本中动态的改变一个UI元素在hierarchy中的排序位置呢? 放到最上面 Transform.SetAsFirstSibling最下面Transfo ...
- U3D UGUI学习1 - 层级环境
就像主动碰撞检测需要刚体,刚体需要Mesh Filter.Unity的一些组件都需要基础配置. UGUI的基础配置和NGUI差不多,把NGUI的那些中间件全部削减干净,甚至连快捷键也没有. 1.基础层 ...
- U3D UGUI学习2 - Canvas
Canvas Render Mode - UGUI不像NGUI,它没有UI摄像机.但有时候需要做相机动画就要调出来. 在Canvas里设置第二个选项即可调出. Pixel Perferct - 这个似 ...
- U3D UGUI学习3 - RectTransform
总的来说整合了NGUI很多零散功能,比如NGUI2.X处理拉伸要额外套脚本,NGUI3.X开始引入新的锚点.再加上依赖BoxCollider使得整个HUD显示非常乱 而UGUI很清晰明了,你也能看清楚 ...
- U3D UGUI学习4 - Text
1.对应NGUI的四种文字显示模式 Shrink Content 对应NGUI第一种模式 勾选Best Fit 但似乎有一个Bug,文字过多的时候会爆框.解决方法是改变Line Spacing ...
- U3D UGUI学习5 - Layout和文字适配
Layout这部分UGUI算是比NGUI做的到位 之前遇到了一个问题,NGUI做文字和背景框适配和容易,绑定一下就好了.UGUI你得弄Layout才可以,而且还需要配置. 但这个Layout使用场合是 ...
- Unity3D之UGUI学习笔记(二):Rect Transform与Anchor
Rect Transform 我们都知道,Unity3D中所有的GameObject都必须要携带一个Transform组件,且该组件无法移除,那么作为UI显示的GameObject则不是携带Trans ...
随机推荐
- tensorflow图像基本处理
tensorflow库提供的专门的图片处理库,以下只是部分示例,更多函数请参照源码'\tensorflow_api\v1\image__init__.py' 加载图像 方式1: 使用tf.gfile. ...
- Unrecoverable error: corrupted cluster config file.
from: https://www.cnblogs.com/topicjie/p/7603227.html 缘起 正在欢乐的逗着孩子玩耍,突然间来了一通电话,值班人员告诉我误重启了一台服务器,是我负责 ...
- REST服务开发实战【转】
原文:http://kb.cnblogs.com/page/91827/ REST介绍 如果要说什么是REST的话,那最好先从Web(万维网)说起. 什么是Web呢?读者可以查看维基百科的词条(htt ...
- 洛谷P1876开灯
题目描述 有n盏灯,一开始全是关闭的.来n个人, 第一个人把一的倍数的灯开着的关上,关上的打开. 第二个人把二的倍数的灯开着的关上,关上的打开. 第三个人把三的倍数的灯开着的关上,关上的打开. ... ...
- 使用模块化编译缩小 apk 体积
libcocos2dlua.so编译出来有11M多,其中包含了很多不需要的模块,模块化编译,把不需要用到的模块弄成0,体积就小了. 如: 修改D:\codeide\sDiShu2formm\frame ...
- vuejs2.0的生命周期解读
每个 Vue 实例在被创建之前都要经过一系列的初始化过程.例如,实例需要配置数据观测(data observer).编译模版.挂载实例到 DOM ,然后在数据变化时更新 DOM .下图展示的就是一个v ...
- Apache DBUtils使用总结 【转】
Apache DBUtils使用总结 DBUtils是个小巧的JDBC轻量级封装的工具包,其最核心的特性是结果集的封装,可以直接将查询出来的结果集封装成JavaBean,这就为我们做了最枯燥乏味. ...
- Hibernate学习8—Hibernate 映射关系(多对多)
第二节:Hibernate 多对多映射关系实现 比如学生和课程是多对多的关系: 一个学生可以选多个课程: 一个课程可以被多个学生选中,所以是多对多的关系: 1,多对多单向实现: 单向关系: 这 ...
- ElasticSearch所使用的倒排索引的思想和使用场景
背景: 在关系数据库系统里,索引是检索数据最有效率的方式,.但对于搜索引擎,它并不能满足其特殊要求: 1)海量数据:搜索引擎面对的是海量数据,像Google,百度这样大型的商业搜索引擎索引都是亿级甚至 ...
- HBase之二:Hbase优化
1. 预先分区 默认情况下,在创建 HBase 表的时候会自动创建一个 Region 分区,当导入数据的时候,所有的 HBase 客户端都向这一个 Region 写数据,直到这个 Region ...