21.UGUI进阶-屏幕坐标转UI相对坐标
21.1 知识点
RectTransformUtility类
RectTransformUtility类是一个RectTransform的辅助类,主要用于进行一些坐标的转换等操作。其中对于我们目前来说最重要的函数是将屏幕空间上的点转换成UI本地坐标下的点。
将屏幕坐标转换为UI本地坐标系下的点
RectTransformUtility.ScreenPointToLocalPointInRectangl方法 将屏幕坐标点转换为父对象的本地坐标系中的点
- 参数一:相对父对象
- 参数二:屏幕点坐标
- 参数三:摄像机
- 参数四:最终得到的点坐标
一般配合拖拽事件使用。
让脚本继承拖拽接口,挂载到要被拖拽的对象上,在拖拽方法中用转换方法写逻辑,让被拖拽的对象跟着鼠标动。
public class Lesson21_UGUI进阶_屏幕坐标转UI相对坐标 : MonoBehaviour,IDragHandler
{
public RectTransform parent; //父对象
public void OnDrag(PointerEventData eventData)
{
// 方法:RectTransformUtility.ScreenPointToLocalPointInRectangle
// 将屏幕坐标点转换为父对象的本地坐标系中的点
// 参数一:相对父对象
// 参数二:屏幕点坐标
// 参数三:摄像机
// 参数四:最终得到的点坐标
// 一般配合拖拽事件使用
Vector2 nowPos;//当前位置
//执行完这个函数后 会把屏幕坐标转换成UI本地坐标系下的值赋值给nowPos
RectTransformUtility.ScreenPointToLocalPointInRectangle(
parent, // 相对父对象
eventData.position, // 屏幕点坐标
eventData.enterEventCamera, // 摄像机
out nowPos); // 最终得到的点坐标
this.transform.localPosition = nowPos; // 将当前对象的本地位置设置为转换后的坐标
//之前的做法 以后就不用这样做了 选择这种方法更准确
//this.transform.position += new Vector3(eventData.delta.x, eventData.delta.y, 0);
// 根据鼠标/触摸滑动的位移,调整当前对象的世界坐标位置
}
}
21.2 知识点代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class Lesson21_UGUI进阶_屏幕坐标转UI相对坐标 : MonoBehaviour,IDragHandler
{
public RectTransform parent; //父对象
void Start()
{
#region 知识点一 RectTransformUtility类
//RectTransformUtility 公共类是一个RectTransform的辅助类
//主要用于进行一些 坐标的转换等等操作
//其中对于我们目前来说 最重要的函数是 将屏幕空间上的点,转换成UI本地坐标下的点
#endregion
}
public void OnDrag(PointerEventData eventData)
{
#region 知识点二 将屏幕坐标转换为UI本地坐标系下的点
// 方法:RectTransformUtility.ScreenPointToLocalPointInRectangle
// 将屏幕坐标点转换为父对象的本地坐标系中的点
// 参数一:相对父对象
// 参数二:屏幕点坐标
// 参数三:摄像机
// 参数四:最终得到的点坐标
// 一般配合拖拽事件使用
Vector2 nowPos;//当前位置
//执行完这个函数后 会把屏幕坐标转换成UI本地坐标系下的值赋值给nowPos
RectTransformUtility.ScreenPointToLocalPointInRectangle(
parent, // 相对父对象
eventData.position, // 屏幕点坐标
eventData.enterEventCamera, // 摄像机
out nowPos); // 最终得到的点坐标
this.transform.localPosition = nowPos; // 将当前对象的本地位置设置为转换后的坐标
//之前的做法 以后就不用这样做了 选择这种方法更准确
//this.transform.position += new Vector3(eventData.delta.x, eventData.delta.y, 0);
// 根据鼠标/触摸滑动的位移,调整当前对象的世界坐标位置
#endregion
}
}
21.3 练习题
在上节课的练习题基础上,修改其中的代码,用新学的屏幕坐标转UI坐标的知识,制作一个UGUI摇杆可以控制场景上的对象移动
修改GamePanel脚本中摇杆事件函数,调用了 RectTransformUtility 类的 ScreenPointToLocalPointInRectangle 方法,将屏幕坐标点转换为图标父对象的本地坐标系中的点,并将结果保存在 nowPos 变量中。把nowPos变量赋值给当前摇杆点位置。注释掉以前加上鼠标偏移计算摇杆点位置的代码
//定义一个私有方法JoyDrag,在摇杆被拖动时执行,接受一个BaseEventData类型的参数data,表示拖动事件的数据
private void JoyDrag(BaseEventData data)
{
//将data强制转换为PointerEventData类型,并赋值给eventData变量,表示拖动事件的指针数据
PointerEventData eventData = data as PointerEventData;
//以前的知识 是通过加上 鼠标偏移位置 让图标动起来
//imgJoy.position += new Vector3(eventData.delta.x, eventData.delta.y, 0);
//用新知识点来制作
//定义一个Vector2类型的变量nowPos,表示当前位置
Vector2 nowPos;
//调用RectTransformUtility类中的ScreenPointToLocalPointInRectangle静态方法,将屏幕坐标转换为矩形变换中的本地坐标,并将结果赋值给nowPos变量
RectTransformUtility.ScreenPointToLocalPointInRectangle(
//传入imgJoy对象的parent属性强制转换为RectTransform类型,表示摇杆图标的父对象的矩形变换组件
imgJoy.parent as RectTransform,
//传入eventData对象的position属性,表示拖动事件的屏幕坐标
eventData.position,
//传入eventData对象的enterEventCamera属性,表示拖动事件的相机
eventData.enterEventCamera,
//传出nowPos变量,表示当前位置
out nowPos);
//将imgJoy对象的localPosition属性赋值为nowPos变量,表示摇杆图标的本地位置
imgJoy.localPosition = nowPos;
//我们有专门的参数 得到相对于锚点的点
//如果imgJoy对象的anchoredPosition属性的magnitude属性大于170,表示摇杆图标超出了摇杆背景圆形范围
if (imgJoy.anchoredPosition.magnitude > 170)
{
//拉回来
//单位向量 乘以 长度 = 临界位置
//将imgJoy对象的anchoredPosition属性赋值为imgJoy对象的anchoredPosition属性的normalized属性乘以170,表示将摇杆图标拉回到摇杆背景圆形边缘
imgJoy.anchoredPosition = imgJoy.anchoredPosition.normalized * 170;
}
//让玩家移动
//调用player对象的Move方法,传入imgJoy对象的anchoredPosition属性,表示让玩家根据摇杆图标相对于锚点的位置进行移动
player.Move(imgJoy.anchoredPosition);
}
21.4 练习题代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class GamePanel : MonoBehaviour
{
public Light light;
public static GamePanel panel;
public Button btnAtk;
//音效开关
public Toggle togOn;
public Toggle togOff;
public ToggleGroup tg;
//音效大小
public Slider sliderSound;
public Text txtName;
public Button btnChangeName;
public PlayerObject player;
//背包按钮
public Button btnBag;
//白天黑夜的切换
public Dropdown ddChange;
//关联长按功能按钮
public LongPress longPress;
//进度条跟对象 用于控制显隐
public GameObject imgRoot;
//进度条对象 用于控制进度
public RectTransform imgBk;
//是否按下
private bool isDown = false;
//计时
private float nowTime = 0;
//增加速度
public float addSpeed = 10;
//当前血量
private int hp = 10;
//摇杆的位置
public RectTransform imgJoy;
//摇杆上的事件相关
public EventTrigger et;
private void Awake()
{
panel = this;
}
void Start()
{
btnAtk.onClick.AddListener(() =>
{
//得到玩家对象 进行开火
player.Fire();
});
btnChangeName.onClick.AddListener(()=> {
//显示改名面板
ChangeNamePanel.panel.gameObject.SetActive(true);
});
togOn.onValueChanged.AddListener(TogChangeValue);
togOff.onValueChanged.AddListener(TogChangeValue);
//初始化 我们滑动条的值 通过数据初始化
sliderSound.value = MusicData.SoundValue;
//监听滑动条改变的事件
sliderSound.onValueChanged.AddListener((v) =>
{
//处理音效的大小
MusicData.SoundValue = v;
});
btnBag.onClick.AddListener(() => {
//打开背包面板
BagPanel.panel.gameObject.SetActive(true);
});
ddChange.onValueChanged.AddListener((index) => {
switch (index)
{
case 0:
light.intensity = 1;
break;
case 1:
light.intensity = 0.3f;
break;
}
});
longPress.downEvent += BtnDown;
longPress.upEvent += BtnUp;
//一开始隐藏蓄能条
imgRoot.gameObject.SetActive(false);
//为摇杆注册事件
//拖动中
EventTrigger.Entry en = new EventTrigger.Entry();
en.eventID = EventTriggerType.Drag;
en.callback.AddListener(JoyDrag);
et.triggers.Add(en);
//结束拖动
en = new EventTrigger.Entry();
en.eventID = EventTriggerType.EndDrag;
en.callback.AddListener(EndJoyDrag);
et.triggers.Add(en);
}
//定义一个私有方法JoyDrag,在摇杆被拖动时执行,接受一个BaseEventData类型的参数data,表示拖动事件的数据
private void JoyDrag(BaseEventData data)
{
//将data强制转换为PointerEventData类型,并赋值给eventData变量,表示拖动事件的指针数据
PointerEventData eventData = data as PointerEventData;
//以前的知识 是通过加上 鼠标偏移位置 让图标动起来
//imgJoy.position += new Vector3(eventData.delta.x, eventData.delta.y, 0);
//用新知识点来制作
//定义一个Vector2类型的变量nowPos,表示当前位置
Vector2 nowPos;
//调用RectTransformUtility类中的ScreenPointToLocalPointInRectangle静态方法,将屏幕坐标转换为矩形变换中的本地坐标,并将结果赋值给nowPos变量
RectTransformUtility.ScreenPointToLocalPointInRectangle(
//传入imgJoy对象的parent属性强制转换为RectTransform类型,表示摇杆图标的父对象的矩形变换组件
imgJoy.parent as RectTransform,
//传入eventData对象的position属性,表示拖动事件的屏幕坐标
eventData.position,
//传入eventData对象的enterEventCamera属性,表示拖动事件的相机
eventData.enterEventCamera,
//传出nowPos变量,表示当前位置
out nowPos);
//将imgJoy对象的localPosition属性赋值为nowPos变量,表示摇杆图标的本地位置
imgJoy.localPosition = nowPos;
//我们有专门的参数 得到相对于锚点的点
//如果imgJoy对象的anchoredPosition属性的magnitude属性大于170,表示摇杆图标超出了摇杆背景圆形范围
if (imgJoy.anchoredPosition.magnitude > 170)
{
//拉回来
//单位向量 乘以 长度 = 临界位置
//将imgJoy对象的anchoredPosition属性赋值为imgJoy对象的anchoredPosition属性的normalized属性乘以170,表示将摇杆图标拉回到摇杆背景圆形边缘
imgJoy.anchoredPosition = imgJoy.anchoredPosition.normalized * 170;
}
//让玩家移动
//调用player对象的Move方法,传入imgJoy对象的anchoredPosition属性,表示让玩家根据摇杆图标相对于锚点的位置进行移动
player.Move(imgJoy.anchoredPosition);
}
private void EndJoyDrag(BaseEventData data)
{
//回归中心点
imgJoy.anchoredPosition = Vector2.zero;
//停止移动 传0向量进去 即可
player.Move(Vector2.zero);
}
private void BtnDown()
{
isDown = true;
nowTime = 0;
//蓄能条清空
imgBk.sizeDelta = new Vector2(0, 40);
}
private void BtnUp()
{
isDown = false;
imgRoot.gameObject.SetActive(false);
}
private void Update()
{
if(isDown)
{
//计时
nowTime += Time.deltaTime;
if( nowTime >= 0.2f )
{
imgRoot.gameObject.SetActive(true);
//蓄能条增加
imgBk.sizeDelta += new Vector2(addSpeed * Time.deltaTime, 0);
if( imgBk.sizeDelta.x >= 800 )
{
//HP增加 条清空
hp += 10;
print("当前hp" + hp);
imgBk.sizeDelta = new Vector2(0, 40);
}
}
}
}
private void TogChangeValue(bool v)
{
//得到当前激活的Toggle
foreach (Toggle item in tg.ActiveToggles())
{
if(item == togOn)
{
MusicData.SoundIsOpen = true;
}
else if(item == togOff)
{
MusicData.SoundIsOpen = false;
}
}
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com