插件地址

https://assetstore.unity.com/packages/essentials/unity-samples-ui-25468

Scenes / Controls

展现各类UI基础控件的用法,包括ToggleGroup的用法;Physics Raycaster这里没有什么作用

unity使用so unity samples_3D

- Physics Raycaster
  • 在Camera中添加PhysicsRaycaster,会对3D物理对象产生影响(但此场景没有3D物体)

Scenes / Drag And Drop

在拖拽图片的过程中,图片会随着UI的倾斜而倾斜,当拖拽到目标框上时,框的底色会有变化;宇宙尘埃的粒子比较好用~

unity使用so unity samples_unity使用so_02

- 拖拽接口
using UnityEngine.EventSystems;
public class DragMe : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
	public void OnBeginDrag(PointerEventData eventData) {}
	public void OnDrag(PointerEventData eventData) {}
	public void OnEndDrag(PointerEventData eventData) {}
}

IBeginDragHandle 开始拖动
IDragHandler 拖动时
IEndDragHandler 结束拖动

  • eventData.pointerId作为m_DraggingIcons唯一索引
  • eventData.pointerEnter:鼠键所在的对象
- FindInParents
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;
	}
  • where 做泛型约束
  • 如果自己有此类型,直接返回
  • 没有,再逐层往上找
- SetParent / SetAsLastSibling / SetAsFirstSibling / SetSiblingIndex(*)
  • public void SetParent(Transform parent, bool worldPositionStays);
  • parent 父类
  • worldPositionStays 是否保持世界坐标系的布尔型变量,UI中设置成false,可以避免受到世界坐标的影响
  • 设置好父类后,可以使用SetSibling系列函数,调整好层的位置
- SetNativeSize
  • Image对象,设置图片的原始尺寸

- overrideSprite

  • Image对象,临时修改图片
  • 如果把overrideSprite设置成null,会恢复原来图片
- RectTransformUtility的运用
Vector2 position;
//参照根节点位置(Canvas),把鼠标屏幕位置转换为视图位置;第三个参数为:当Canvas Render Mode为Screen Space-Camera 的Camera
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;
}
  • UGUI鼠标位置转换成视图位置
  • ScreenPointToWorldPointInRectangle
  • 第1个参数:为鼠标在哪个UI上移动
  • 第2个参数:鼠标的坐标
  • 第3个参数:Screen Space-Camera的摄像机
- SetDraggedPosition的过程
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;
	}
}
  1. 根据pointerEnter,记录当前鼠标在哪个UI上移动
  2. 通过RectTransformUtility,计算出拖动图片的世界坐标
  3. 根据pointerEnter的实时物体,修改拖动图片的rotation
- IPointerEnterHandler, IPointerExitHandler
using UnityEngine.EventSystems;
public class DropMe : MonoBehaviour, IDropHandler, IPointerEnterHandler, IPointerExitHandler
{
	public void OnDrop(PointerEventData data) {}
	public void OnPointerEnter(PointerEventData data) {}
	public void OnPointerExit(PointerEventData data) {}
}

五个指针相关事件接口
IPointerEnterHandler:指针进入事件处理器;一瞬间触发。
IPointerExitHandler:指针离开事件处理器;一瞬间触发。
IPointerDownHandler:指针按下事件处理器;一瞬间触发。
IPointerUpHandler:指针抬起事件处理器;一瞬间触发。
IPointerClickHandler:指针单击事件处理器;指针按下+抬起=单击

IDropHandler:不是Drag,当拖动到这个框,并放下的时候触发

- DropMe的过程(拖动到那个框)
  1. PointerEventData.pointerDrag 会获得被拖动的那个图片,GetDropSprite获取了它。
  2. OnPointerEnter / OnPointerExit,作用是改动拖动的那个框的背景色。
  3. 通过OnDrop,修改图片

Scenes / Draggable Panel

框是倾斜的,可以被拉大拉小,可以拖动(空间里);UI使用自适应布局;利用偏移量来定位和改变框的大小

unity使用so unity samples_3D_03

- ScreenPointToLocalPointInRectangle
  • ScreenPointToLocalPointInRectangle与ScreenPointToWorldPointInRectangle的区别是,它返回在GUI中的局部坐标Vector2;
  • 用ScreenPointToLocalPointInRectangle,获得坐标,GUI中调整位置
- DragPanel
  • 实现框的拖动,属性有4个,拖动栏和整个框的RectTransform,鼠标的GUI转换后的坐标,和框实时的localPosition;
  • OnPointerDown : 获得框实时的localPosition,和鼠标转换后的坐标;
  • OnDrag:这里是使用了移动量的逻辑,点击时,获取坐标,移动时,2个坐标相减;在把框的localPosition不断改变变量。
  • ClampToWindow:框不出界
- ClampToWindow
  • rect.min / rect.max :获得4个点的最小值和最大值
  • 把大框和小框减下,获得中间的区间
  • 用Mathf.Clamp把数值夹在中间
- ResizePanel
  • 同样用了移动量的逻辑,点击时,先获取当前框的大小,和点击的位置
  • 拖动时,获得移动的量,再改变框的大小
  • 最后用Mathf.Clamp把值夹在中间

Scenes / Layout Groups

面板随鼠标轻度旋转,按钮可以点击(立体效果),这个效果采用Button - Animation来时间

unity使用so unity samples_3D_04

- 面板旋转
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);
	}
1. 跟随鼠标旋转,用-1到1,来计算range的初始化设置
2. Quaternion相乘来计算最终的角度,开始角度 * 旋转的xyz,获得最终的角度

Scenes / Lighting

UI面板上,集合了灯光的效果,UI用了UI/Lit/Detail材质来渲染,灯光Culling Mask设置成UI

unity使用so unity samples_UI_05

- UI/Lit/Detail材质

unity使用so unity samples_事件处理_06


Scenes / Menu 3D

3D菜单,点击可以切换,切换采用了Animation

unity使用so unity samples_3D_07

- EventSystem.current.SetSelectedGameObject
using UnityEngine.EventSystems;
...
var newPreviouslySelected = EventSystem.current.currentSelectedGameObject;
....
EventSystem.current.SetSelectedGameObject(go);

通过EventSystem.current来获得当前选中的对象

- Animator.StringToHash
const string k_OpenTransitionName = "Open";
const string k_ClosedStateName = "Closed";
...
m_OpenParameterId = Animator.StringToHash (k_OpenTransitionName);
....
m_Open.SetBool(m_OpenParameterId, true);

通过转Hash的方法获得ID,可以提高运算效率


Scenes / RenderTexture

把3D物体,通过相机和Target Texture,来嵌入到UI中

unity使用so unity samples_事件处理_08

- RenderTexture的设置

unity使用so unity samples_UI_09

- RawImage的材质

unity使用so unity samples_UI_10

结束语

Unity Samples: UI展示了GUI的各种用法:

  1. 拖动的用法
  2. 基本组件和UI布局
  3. 灯光
  4. Button + Animation 的动画实现
  5. 把UI放在3D空间里,也可以把3D空间的成像放在UI里
  6. RenderTexture实现与3D物体的结合