Unity记录7.2-界面-UI的点击、拖动与长按

汇总:Unity 记录
开源地址:asd123pwj/asdGame
摘要:UI的点击事件判断,以及拖动UI,长按UI的实现。
点击UI的边缘-2024/05/11
- 在各种意义上都卡了挺久,本来是想实现UI窗口的手动调节,但是如何判断点击在窗口上?如何判断点击在边缘上?点击在哪个窗口上?
- 总之现在只实现了点击在指定窗口的边缘,但可能会因窗口重叠而产生问题,但那是之后要解决的了。
- 最终,在实现上,简言之,鼠标在UI窗口的框框内,且鼠标在比UI窗口小一点点的框框外。
- 首先获取屏幕缩放,先获得原始分辨率,在Canvas的Canvas Scaler里有Reference Resolution,我这里是1920x1080。
- 然后用
Screen.width
与Screen.height
获取当前分辨率,两者相除,获取当前缩放。 - 然后获取原始UI坐标与大小。
- 用
GameObject.GetComponent<RectTransform>()
获取RectTransform,RectTransform.position
与RectTransform.sizeDelta
分别为UI的原始坐标与原始大小。 - 将大小转换为缩放后的UI大小。
- 用上步和上上步获取的两个数据相乘即可。
- 将UI坐标转换为屏幕坐标,再将UI窗口的坐标原点从中心映射至左下角(仅计算)。
- 用此代码转换为屏幕坐标:
RectTransformUtility.WorldToScreenPoint(Camera.main, rect_transform.position);
- 上面获取的是UI窗口的中心,要映射为左下角,仅需减去窗口大小的一半即可。
- 基于上面的信息,能够获取UI的实际坐标与实际大小,进而生成一个矩形框。
Rect window_rect = new(UI_pos, UI_size);
- 再定义一个边界大小,获取一个比上面矩形框小一点点的小框。
- 判断鼠标的屏幕坐标,是否在大框内部,并且在小框外部。
- 这份代码大概率会被优化,或者被Unity的方法替代,因为我实在不认为这种判断要这么麻烦。
- 但我确实没找到替代方法。
- 具体代码如下,
- 判断鼠标点击的函数和"记录6.6"中"再次优化的即时技能"章节的方法一样,虽然想过是否要在那里判断鼠标位置,但是最终还是移至UI的交互代码中,只是稍微修改了一点。
- 转换UI大小至实际的函数是
convert_UIRect_to_screenRect()
,判断是否在UI边缘的是check_border()
。
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections.Generic;
public class UIInteract{
UIConfig UIConfig;
RectTransform rect_transform;
Vector2 UI_pos, UI_size;
Vector2 tmp_original_resolution = new(1920f, 1080f);
bool isInit = true;
float border_size = 10f;
public UIInteract(UIConfig UIConfig){
this.UIConfig = UIConfig;
this.rect_transform = UIConfig._self.GetComponent<RectTransform>();
register_input_action();
}
public void _update(KeyPos keyPos, Dictionary<string, KeyInfo> _keyStatus){
if (_keyStatus["fire1"].isDown){
convert_UIRect_to_screenRect();
if (check_border(keyPos.mouse_pos_world)){
Debug.Log("resize");
}
}
}
void register_input_action(){
UIConfig._InputSystem._register_UI("Fire1", resize_rectTransform, true);
}
void convert_UIRect_to_screenRect(){
Vector2 scale = new(Screen.width / tmp_original_resolution.x, Screen.height / tmp_original_resolution.y);
UI_size = rect_transform.sizeDelta * scale;
UI_pos = RectTransformUtility.WorldToScreenPoint(Camera.main, rect_transform.position);
UI_pos = new(UI_pos.x - UI_size.x / 2f, UI_pos.y - UI_size.y / 2f);
}
bool check_border(Vector2 mouse_pos){
Vector2 UISmall_pos = new(UI_pos.x + border_size, UI_pos.y + border_size);
Vector2 UISmall_size = new(UI_size.x - border_size * 2f, UI_size.y - border_size * 2f);
Rect window_rect = new(UI_pos, UI_size);
Rect windowSmall_rect = new(UISmall_pos, UISmall_size);
// Debug.Log(mouse_pos + " - " + window_rect + " - " + scale);
return window_rect.Contains(mouse_pos) && !windowSmall_rect.Contains(mouse_pos);
}
bool resize_rectTransform(KeyPos keyPos, Dictionary<string, KeyInfo> _keyStatus){
if (!_keyStatus["Fire1"].isFirstDown) return false;
if (check_border(keyPos.mouse_pos_UI)){
Debug.Log("resize");
}
return true;
}
}
UI交互事件-2024/05/12
- 改为了用Unity自带的UI事件
public class UITrigger{
UIConfig UIConfig;
EventTrigger eventTrigger;
public UITrigger(UIConfig UIConfig){
this.UIConfig = UIConfig;
this.UIConfig._UITrigger = this;
init_eventTrigger();
init_eventTrigger_trigger();
}
void init_eventTrigger(){
eventTrigger = UIConfig._self.GetComponent<EventTrigger>();
if (eventTrigger == null) eventTrigger = UIConfig._self.AddComponent<EventTrigger>();
}
void init_eventTrigger_trigger(){
EventTrigger.Entry entry;
entry = new(){eventID = EventTriggerType.PointerEnter}; entry.callback.AddListener((data) =>UIConfig._UIInteract._action_pointer_enter()); eventTrigger.triggers.Add(entry);
entry = new(){eventID = EventTriggerType.PointerExit}; entry.callback.AddListener((data) =>UIConfig._UIInteract._action_pointer_exit()); eventTrigger.triggers.Add(entry);
entry = new(){eventID = EventTriggerType.PointerDown}; entry.callback.AddListener((data) =>UIConfig._UIInteract._action_pointer_down()); eventTrigger.triggers.Add(entry);
entry = new(){eventID = EventTriggerType.PointerUp}; entry.callback.AddListener((data) =>UIConfig._UIInteract._action_pointer_up()); eventTrigger.triggers.Add(entry);
entry = new(){eventID = EventTriggerType.PointerClick}; entry.callback.AddListener((data) =>UIConfig._UIInteract._action_pointer_click()); eventTrigger.triggers.Add(entry);
entry = new(){eventID = EventTriggerType.Drag}; entry.callback.AddListener((data) =>UIConfig._UIInteract._action_drag()); eventTrigger.triggers.Add(entry);
entry = new(){eventID = EventTriggerType.Drop}; entry.callback.AddListener((data) =>UIConfig._UIInteract._action_drop()); eventTrigger.triggers.Add(entry);
entry = new(){eventID = EventTriggerType.Scroll}; entry.callback.AddListener((data) =>UIConfig._UIInteract._action_scroll()); eventTrigger.triggers.Add(entry);
entry = new(){eventID = EventTriggerType.UpdateSelected}; entry.callback.AddListener((data) =>UIConfig._UIInteract._action_update_selected()); eventTrigger.triggers.Add(entry);
entry = new(){eventID = EventTriggerType.Select}; entry.callback.AddListener((data) =>UIConfig._UIInteract._action_select()); eventTrigger.triggers.Add(entry);
entry = new(){eventID = EventTriggerType.Deselect}; entry.callback.AddListener((data) =>UIConfig._UIInteract._action_deselect()); eventTrigger.triggers.Add(entry);
entry = new(){eventID = EventTriggerType.Move}; entry.callback.AddListener((data) =>UIConfig._UIInteract._action_move()); eventTrigger.triggers.Add(entry);
entry = new(){eventID = EventTriggerType.InitializePotentialDrag}; entry.callback.AddListener((data) =>UIConfig._UIInteract._action_initialize_potential_drag()); eventTrigger.triggers.Add(entry);
entry = new(){eventID = EventTriggerType.BeginDrag}; entry.callback.AddListener((data) =>UIConfig._UIInteract._action_begin_drag()); eventTrigger.triggers.Add(entry);
entry = new(){eventID = EventTriggerType.EndDrag}; entry.callback.AddListener((data) =>UIConfig._UIInteract._action_end_drag()); eventTrigger.triggers.Add(entry);
entry = new(){eventID = EventTriggerType.Submit}; entry.callback.AddListener((data) =>UIConfig._UIInteract._action_submit()); eventTrigger.triggers.Add(entry);
entry = new(){eventID = EventTriggerType.Cancel}; entry.callback.AddListener((data) =>UIConfig._UIInteract._action_cancel()); eventTrigger.triggers.Add(entry);
}
}
UI的拖动-2024/05/12, 2024/05/17
- 用FixedUpdate和Update里的鼠标位移来更新UI的位移,失败了。
- 具体表现为鼠标移动一点点,UI移动一大堆,时灵时不灵。
- 在事件内部的鼠标唯一来更新UI的位移,失败了。
- 具体表现为鼠标移动一点点,UI十万八千里,时灵时不灵。
- GPT4o告诉了我一个方法,能较为正常的移动了,但在移动时UI中心会到鼠标上。
- 看来上一步的问题还是坐标系的问题,鼠标位置的宽度是1000+
- 然而,
rect_transform.position
以及转换坐标系之后的位置globalMousePos
,宽度60左右。 - 差了20倍,怪不得UI乱飞。
void drag(PointerEventData eventData) {
if (RectTransformUtility.ScreenPointToWorldPointInRectangle(rect_transform, eventData.position, eventData.pressEventCamera, out Vector3 globalMousePos)) {
rect_transform.position = globalMousePos;
}
}
- 最终的鼠标拖动UI代码如下
- 相较上一步,鼠标点击时,记录UI位置与鼠标位置的偏移,然后在drag时加上偏移。
- 下面第一部分代码是一些相关信息,第二部分的代码是控制函数。
- 代码有点乱,估计不好看,可以找gpt问问,它给的更简洁
entry = new(){eventID = EventTriggerType.PointerEnter};
entry.callback.AddListener((data) =>UIConfig._UIInteract._action_pointer_down((PointerEventData)data));
eventTrigger.triggers.Add(entry);
public void _action_pointer_down(PointerEventData eventData){
UIConfig._UIStatus._update_mouse_down(eventData);
}
public void _action_drag(PointerEventData eventData){
UIConfig._UIStatus._drag(eventData);
}
public class UIStatus{
Vector3 mouse_pos_offset_down = new();
RectTransform rect_transform;
public UIStatus(UIConfig UIConfig){
this.rect_transform = UIConfig._self.GetComponent<RectTransform>();
}
public void _update_mouse_down(PointerEventData eventData){
RectTransformUtility.ScreenPointToWorldPointInRectangle(rect_transform, eventData.position, eventData.pressEventCamera, out Vector3 globalMousePos);
mouse_pos_offset_down = rect_transform.position - globalMousePos;
}
public void _drag(PointerEventData eventData){
RectTransformUtility.ScreenPointToWorldPointInRectangle(rect_transform, eventData.position, eventData.pressEventCamera, out Vector3 globalMousePos);
rect_transform.position = globalMousePos + mouse_pos_offset_down;
}
}
UI的点击按键判断-2024/05/18
- 用下面的
switch
判断触发事件的鼠标按键。
public void _action_pointer_down(PointerEventData eventData){
switch (eventData.button){
case PointerEventData.InputButton.Left:
UIConfig._UIStatus._update_mouse_down(eventData);
break;
case PointerEventData.InputButton.Right:
break;
case PointerEventData.InputButton.Middle:
break;
}
}
UI的点击时长-2024/05/18
- 这个比较简单,鼠标按下开始计时,Update判断当前时间是否满足一个周期,满足则触发事件,松开鼠标时关闭计时。
- 下面的代码中
- 函数
_update()
即放在Update中的函数。 _update_mouseDownTime()
开始计时。_check_downTime_period()
判断计时周期。_update_mouseUp()
取消计时。
- 函数
float mouse_down_time;
int elapsed_period = 0;
bool isDown = false;
public void _update(){
if(isDown){
if(_check_downTime_period()){
Debug.Log("elapsed_period: " + elapsed_period);
}
}
}
public void _update_mouseDownTime(){
mouse_down_time = Time.time;
elapsed_period = 0;
isDown = true;
}
public bool _check_downTime_period(float period=0.5f){
float time_now = Time.time;
if(time_now - mouse_down_time - period * elapsed_period > period){
elapsed_period += 1;
return true;
}
return false;
}
public void _update_mouseUp(){
isDown = false;
}
文章目录
关闭
共有 0 条评论