1. Grid Layout Group(网格布局)
Hierachy:
Game:
属性和功能:
2. 根据鼠标位置旋转界面实现:
1 public class TiltWindow : MonoBehaviour 2 { 3 public Vector2 range = new Vector2(5f, 3f); 4 5 Transform mTrans; 6 Quaternion mStart; 7 Vector2 mRot = Vector2.zero; 8 9 void Start () 10 { 11 mTrans = transform; 12 mStart = mTrans.localRotation; 13 } 14 15 void Update () 16 { 17 Vector3 pos = Input.mousePosition; 18 19 float halfWidth = Screen.width * 0.5f; 20 float halfHeight = Screen.height * 0.5f; 21 float x = Mathf.Clamp((pos.x - halfWidth) / halfWidth, -1f, 1f); 22 float y = Mathf.Clamp((pos.y - halfHeight) / halfHeight, -1f, 1f); 23 mRot = Vector2.Lerp(mRot, new Vector2(x, y), Time.deltaTime * 5f); 24 25 mTrans.localRotation = mStart * Quaternion.Euler(-mRot.y * range.y, mRot.x * range.x, 0f); 26 } 27 }
3. 按钮动画实现:
修改 Transisition 为 Animation,设置触发器
在 Animator 设计状态机
4. HorizontalLayoutGroup(垂直布局)
Hierachy:
Game:
属性和功能:
5. 拖拽功能实现
Hierarchy(其中 Panel 中 Image 绑定 DragMe,Panel2,Panel3 中 Image 绑定 DropMe):
1 public class DragMe : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler 2 { 3 public bool dragOnSurfaces = true; 4 5 private Dictionary<int,GameObject> m_DraggingIcons = new Dictionary<int, GameObject>(); 6 private Dictionary<int, RectTransform> m_DraggingPlanes = new Dictionary<int, RectTransform>(); 7 8 // 开始拖拽 9 // 创建拖拽图片的 clone 体 10 public void OnBeginDrag(PointerEventData eventData) 11 { 12 var canvas = FindInParents<Canvas>(gameObject); 13 if (canvas == null) 14 return; 15 16 // We have clicked something that can be dragged. 17 // What we want to do is create an icon for this. 18 m_DraggingIcons[eventData.pointerId] = new GameObject("icon"); 19 20 m_DraggingIcons[eventData.pointerId].transform.SetParent (canvas.transform, false); 21 m_DraggingIcons[eventData.pointerId].transform.SetAsLastSibling(); 22 23 var image = m_DraggingIcons[eventData.pointerId].AddComponent<Image>(); 24 // The icon will be under the cursor. 25 // We want it to be ignored by the event system. 26 var group = m_DraggingIcons[eventData.pointerId].AddComponent<CanvasGroup>(); 27 group.blocksRaycasts = false; 28 29 image.sprite = GetComponent<Image>().sprite; 30 image.SetNativeSize(); 31 32 if (dragOnSurfaces) 33 m_DraggingPlanes[eventData.pointerId] = transform as RectTransform; 34 else 35 m_DraggingPlanes[eventData.pointerId] = canvas.transform as RectTransform; 36 37 SetDraggedPosition(eventData); 38 } 39 40 // 正在拖拽 41 // 更新拖拽物位置 42 public void OnDrag(PointerEventData eventData) 43 { 44 if (m_DraggingIcons[eventData.pointerId] != null) 45 SetDraggedPosition(eventData); 46 } 47 48 // 根据鼠标位置更新拖拽物位置和旋转 49 private void SetDraggedPosition(PointerEventData eventData) 50 { 51 if (dragOnSurfaces && eventData.pointerEnter != null && eventData.pointerEnter.transform as RectTransform != null) 52 m_DraggingPlanes[eventData.pointerId] = eventData.pointerEnter.transform as RectTransform; 53 54 var rt = m_DraggingIcons[eventData.pointerId].GetComponent<RectTransform>(); 55 Vector3 globalMousePos; 56 if (RectTransformUtility.ScreenPointToWorldPointInRectangle(m_DraggingPlanes[eventData.pointerId], eventData.position, eventData.pressEventCamera, out globalMousePos)) 57 { 58 rt.position = globalMousePos; 59 rt.rotation = m_DraggingPlanes[eventData.pointerId].rotation; 60 } 61 } 62 63 // 结束拖拽 64 // 销毁克隆体 65 public void OnEndDrag(PointerEventData eventData) 66 { 67 if (m_DraggingIcons[eventData.pointerId] != null) 68 Destroy(m_DraggingIcons[eventData.pointerId]); 69 70 m_DraggingIcons[eventData.pointerId] = null; 71 } 72 73 // 在父亲节点中寻找 T 组件 74 static public T FindInParents<T>(GameObject go) where T : Component 75 { 76 if (go == null) return null; 77 var comp = go.GetComponent<T>(); 78 79 if (comp != null) 80 return comp; 81 82 var t = go.transform.parent; 83 while (t != null && comp == null) 84 { 85 comp = t.gameObject.GetComponent<T>(); 86 t = t.parent; 87 } 88 return comp; 89 } 90 }
1 public class DropMe : MonoBehaviour, IDropHandler, IPointerEnterHandler, IPointerExitHandler 2 { 3 public Image containerImage; 4 public Image receivingImage; 5 private Color normalColor; 6 public Color highlightColor = Color.yellow; 7 8 public void OnEnable () 9 { 10 if (containerImage != null) 11 normalColor = containerImage.color; 12 } 13 14 // 放置图片 15 public void OnDrop(PointerEventData data) 16 { 17 containerImage.color = normalColor; 18 19 if (receivingImage == null) 20 return; 21 22 Sprite dropSprite = GetDropSprite (data); 23 if (dropSprite != null) 24 receivingImage.overrideSprite = dropSprite; 25 } 26 27 // 鼠标移入 28 // 背景高亮 29 public void OnPointerEnter(PointerEventData data) 30 { 31 if (containerImage == null) 32 return; 33 34 Sprite dropSprite = GetDropSprite (data); 35 if (dropSprite != null) 36 containerImage.color = highlightColor; 37 } 38 39 // 鼠标移出 40 public void OnPointerExit(PointerEventData data) 41 { 42 if (containerImage == null) 43 return; 44 45 containerImage.color = normalColor; 46 } 47 48 // 得到拖拽图片 49 private Sprite GetDropSprite(PointerEventData data) 50 { 51 var originalObj = data.pointerDrag; 52 if (originalObj == null) 53 return null; 54 55 var dragMe = originalObj.GetComponent<DragMe>(); 56 if (dragMe == null) 57 return null; 58 59 var srcImage = originalObj.GetComponent<Image>(); 60 if (srcImage == null) 61 return null; 62 63 return srcImage.sprite; 64 } 65 }
6. 拖拽改变面板位置(屏幕坐标到本地坐标的转换)
1 public class DragPanel : MonoBehaviour, IPointerDownHandler, IDragHandler { 2 3 private Vector2 originalLocalPointerPosition; 4 private Vector3 originalPanelLocalPosition; 5 private RectTransform panelRectTransform; 6 private RectTransform parentRectTransform; 7 8 void Awake () { 9 panelRectTransform = transform.parent as RectTransform; 10 parentRectTransform = panelRectTransform.parent as RectTransform; 11 } 12 13 public void OnPointerDown (PointerEventData data) { 14 originalPanelLocalPosition = panelRectTransform.localPosition; 15 // 屏幕坐标转成本地坐标 16 RectTransformUtility.ScreenPointToLocalPointInRectangle (parentRectTransform, data.position, data.pressEventCamera, out originalLocalPointerPosition); 17 } 18 19 public void OnDrag (PointerEventData data) { 20 if (panelRectTransform == null || parentRectTransform == null) 21 return; 22 23 Vector2 localPointerPosition; 24 if (RectTransformUtility.ScreenPointToLocalPointInRectangle (parentRectTransform, data.position, data.pressEventCamera, out localPointerPosition)) { 25 Vector3 offsetToOriginal = localPointerPosition - originalLocalPointerPosition; 26 panelRectTransform.localPosition = originalPanelLocalPosition + offsetToOriginal; 27 } 28 29 ClampToWindow (); 30 } 31 32 // 将面板限制在父组件之内 33 // Clamp panel to area of parent 34 void ClampToWindow () { 35 Vector3 pos = panelRectTransform.localPosition; 36 37 Vector3 minPosition = parentRectTransform.rect.min - panelRectTransform.rect.min; 38 Vector3 maxPosition = parentRectTransform.rect.max - panelRectTransform.rect.max; 39 40 pos.x = Mathf.Clamp (panelRectTransform.localPosition.x, minPosition.x, maxPosition.x); 41 pos.y = Mathf.Clamp (panelRectTransform.localPosition.y, minPosition.y, maxPosition.y); 42 43 panelRectTransform.localPosition = pos; 44 } 45 }
7. 拖拽改变面板大小
1 public class ResizePanel : MonoBehaviour, IPointerDownHandler, IDragHandler { 2 3 public Vector2 minSize = new Vector2 (100, 100); 4 public Vector2 maxSize = new Vector2 (400, 400); 5 6 private RectTransform panelRectTransform; 7 private Vector2 originalLocalPointerPosition; 8 private Vector2 originalSizeDelta; 9 10 void Awake () { 11 panelRectTransform = transform.parent.GetComponent<RectTransform> (); 12 } 13 14 public void OnPointerDown (PointerEventData data) { 15 originalSizeDelta = panelRectTransform.sizeDelta; 16 RectTransformUtility.ScreenPointToLocalPointInRectangle (panelRectTransform, data.position, data.pressEventCamera, out originalLocalPointerPosition); 17 } 18 19 public void OnDrag (PointerEventData data) { 20 if (panelRectTransform == null) 21 return; 22 23 Vector2 localPointerPosition; 24 RectTransformUtility.ScreenPointToLocalPointInRectangle (panelRectTransform, data.position, data.pressEventCamera, out localPointerPosition); 25 Vector3 offsetToOriginal = localPointerPosition - originalLocalPointerPosition; 26 // 根据鼠标偏移改变窗口大小 27 Vector2 sizeDelta = originalSizeDelta + new Vector2 (offsetToOriginal.x, -offsetToOriginal.y); 28 sizeDelta = new Vector2 ( 29 Mathf.Clamp (sizeDelta.x, minSize.x, maxSize.x), 30 Mathf.Clamp (sizeDelta.y, minSize.y, maxSize.y) 31 ); 32 33 panelRectTransform.sizeDelta = sizeDelta; 34 } 35 }
8. 根据滑动条调节光源颜色
效果图:
先设置 Slider 的 OnValueChange(其他两个同理) :
1 public class ChangeColor : MonoBehaviour, IPointerClickHandler 2 { 3 public void SetRed(float value) 4 { 5 OnValueChanged(value, 0); 6 } 7 8 public void SetGreen(float value) 9 { 10 OnValueChanged(value, 1); 11 } 12 13 public void SetBlue(float value) 14 { 15 OnValueChanged(value, 2); 16 } 17 18 public void OnValueChanged(float value, int channel) 19 { 20 Color c = Color.white; 21 22 if (GetComponent<Renderer>() != null) 23 c = GetComponent<Renderer>().material.color; 24 else if (GetComponent<Light>() != null) 25 c = GetComponent<Light>().color; 26 27 c[channel] = value; 28 29 if (GetComponent<Renderer>() != null) 30 GetComponent<Renderer>().material.color = c; 31 else if (GetComponent<Light>() != null) 32 GetComponent<Light>().color = c; 33 } 34 }
9. 面板切换
效果图:
面板管理代码:
1 public class PanelManager : MonoBehaviour { 2 3 public Animator initiallyOpen; 4 5 private int m_OpenParameterId; 6 private Animator m_Open; 7 private GameObject m_PreviouslySelected; 8 9 const string k_OpenTransitionName = "Open"; 10 const string k_ClosedStateName = "Closed"; 11 12 public void OnEnable() 13 { 14 // 根据参数名字得到id 15 m_OpenParameterId = Animator.StringToHash (k_OpenTransitionName); 16 17 if (initiallyOpen == null) 18 return; 19 // 打开初始面板 20 OpenPanel(initiallyOpen); 21 } 22 23 // 打开面板 24 public void OpenPanel (Animator anim) 25 { 26 if (m_Open == anim) 27 return; 28 29 anim.gameObject.SetActive(true); 30 var newPreviouslySelected = EventSystem.current.currentSelectedGameObject; 31 32 // 最先显示 33 anim.transform.SetAsLastSibling(); 34 35 CloseCurrent(); 36 37 m_PreviouslySelected = newPreviouslySelected; 38 39 m_Open = anim; 40 m_Open.SetBool(m_OpenParameterId, true); 41 42 GameObject go = FindFirstEnabledSelectable(anim.gameObject); 43 44 SetSelected(go); 45 } 46 47 static GameObject FindFirstEnabledSelectable (GameObject gameObject) 48 { 49 GameObject go = null; 50 var selectables = gameObject.GetComponentsInChildren<Selectable> (true); 51 foreach (var selectable in selectables) { 52 if (selectable.IsActive () && selectable.IsInteractable ()) { 53 go = selectable.gameObject; 54 break; 55 } 56 } 57 return go; 58 } 59 60 // 关闭当前面板 61 public void CloseCurrent() 62 { 63 if (m_Open == null) 64 return; 65 66 m_Open.SetBool(m_OpenParameterId, false); 67 SetSelected(m_PreviouslySelected); 68 StartCoroutine(DisablePanelDeleyed(m_Open)); 69 m_Open = null; 70 } 71 72 // 关闭面板 73 IEnumerator DisablePanelDeleyed(Animator anim) 74 { 75 bool closedStateReached = false; 76 bool wantToClose = true; 77 while (!closedStateReached && wantToClose) 78 { 79 if (!anim.IsInTransition(0)) 80 closedStateReached = anim.GetCurrentAnimatorStateInfo(0).IsName(k_ClosedStateName); 81 82 wantToClose = !anim.GetBool(m_OpenParameterId); // 关闭的时候可打断 83 84 yield return new WaitForEndOfFrame(); // 等待关闭动画播放完 85 } 86 87 if (wantToClose) 88 anim.gameObject.SetActive(false); 89 } 90 91 private void SetSelected(GameObject go) 92 { 93 EventSystem.current.SetSelectedGameObject(go); 94 } 95 }
10. RenderTexure 在 UI 上显示模型
设置 Camera TargetTexture,将 相机内容渲染到 RenderTexure 中。
添加 RawImage,设置 Texture 为之前的 RenderTexture。
效果图:
11. 图片遮挡(Mask,ScrollRect)
Hierarchy:
在 GameObject 中添加组件:
效果图: