前言
在学习凉鞋老师的课程《QFramework系统设计:通用背包系统》第五章时,笔者对物品提示TipPanel界面进行了一些优化。
优化内容包括:
- 解决闪烁问题
- 跟随鼠标移动
- 自适应界面大小
- 生成位置优化
效果还是蛮丝滑的:
解决闪烁问题
由于原代码逻辑是:当鼠标检测到Slot UI时,显示Tips;当未检测到Slot UI时,关闭Tips。
于是当Tips界面叠在Slot UI上时,鼠标移动到重叠部分便会反复触发以上逻辑。
此时只需要将Tips界面的Raycast Target关闭就可以了(如果需要Tips界面有交互,可以考虑其他解决方案)。
跟随鼠标移动
这个比较简单,就是将生成部分的代码封装成方法,在Update()方法中调用即可。
自适应页面大小
笔者给Tips界面添加了ContentSizeFitter组件,使其可以随自身内容改变大小。
但还是遇到一些问题,比如从一个Slot UI移动到另一个Slot UI上时,Tips界面的大小不会立即发生变化以适应新的大小。
原因是ContentSizeFitter的调整发生在布局的重计算阶段,在连续快速地更换内容时可能不会立即反映最新的内容变化。
这时候就需要使用LayoutRebuilder.ForceRebuildLayoutImmediate()方法,立即强制重建布局。
改为默认生成到鼠标的左下方
当鼠标靠近屏幕左边界时,生成到右下方;当鼠标靠近屏幕下边界时,生成到左上方;以此类推。
代码实现
using UnityEngine;
using UnityEngine.UI;namespace QFramework
{public class UIItemTip : MonoBehaviour{public GameObject TipPanel;public Image Icon;public Text NameText;public Text DescriptionText;public Text AttributeText;public Text IDText;private static UIItemTip mDefault;private void Awake(){mDefault = this;}private void Start(){mDefault.TipPanel.Hide();if (AttributeText.text == "")AttributeText.Hide();elseAttributeText.Show();if (IDText.text == "")IDText.Hide();elseIDText.Show();}private void Update(){UpdatePosition();}public static void Show(UISlot slot){if (slot.Data.Item != null){mDefault.Icon.sprite = slot.Data.Item.GetIcon;mDefault.NameText.text = slot.Data.Item.GetName;mDefault.DescriptionText.text = slot.Data.Item.GetDescription;mDefault.TipPanel.Show();UpdatePosition();}}public static void Hide(){mDefault.TipPanel.Hide();}public static void UpdatePosition(){Vector3 mousePos = Input.mousePosition;Vector3[] corners = new Vector3[4];RectTransform rectTrans = mDefault.TipPanel.transform as RectTransform;// 更新TipPanel内容后,强制刷新布局LayoutRebuilder.ForceRebuildLayoutImmediate(rectTrans);// 获取界面的四个角点rectTrans.GetWorldCorners(corners);float width = corners[3].x - corners[0].x;float height = corners[1].y - corners[0].y;// 根据鼠标和屏幕的相对位置,调整生成 TipPanel 的位置if (mousePos.y < height && mousePos.x > width)rectTrans.position = mousePos + 0.5f * height * Vector3.up + 0.5f * width * Vector3.left;else if (mousePos.y > height && mousePos.x < width)rectTrans.position = mousePos + 0.5f * height * Vector3.down + 0.5f * width * Vector3.right;else if (mousePos.y < height && mousePos.x < width)rectTrans.position = mousePos + 0.5f * height * Vector3.up + 0.5f * width * Vector3.right;elserectTrans.position = mousePos + 0.5f * height * Vector3.down + 0.5f * width * Vector3.left;// 0.51f 多了0.01f,使Tips和鼠标保持一小段距离}private void OnDestroy(){mDefault = null;}}
}