41.FGUI基础-Unity中的使用必备-拖拽相关
41.1 知识点
现有知识实现拖拽
利用OnTouchBegin、OnTouchEnd、OnTouchMove事件可以完成拖拽功能
FGUI中的自由拖拽功能
获取对象设置 draggable属性为true 即可拖拽
注意:拖动只能在元件父组件内移动
TeachPanel panel = UIManager.Instance.ShowPanel<TeachPanel>("Teach");
panel.m_btnTest.draggable = true;
// 自由拖拽事件相关
// 开始拖
panel.m_btnTest.onDragStart.Add(()=> {
print("开始拖");
});
// 拖动中
panel.m_btnTest.onDragMove.Add(() => {
print("拖动中");
});
// 结束拖
panel.m_btnTest.onDragEnd.Add(() => {
print("结束拖动");
});
设置拖动范围
注意,范围是舞台上的坐标 不是元件的本地坐标
传入起始位置的xy和宽高为限制矩形
// 代码示例
panel.m_btnTest.dragBounds = new Rect(500, 0, 1000, 200);
确认按钮可以被拖拽了 但是被限制在以500,0为原点的1000x200矩形中
41.2 知识点代码
using System.Collections;
using System.Collections.Generic;
using Teach;
using UnityEngine;
public class Lesson41_FGUI基础_Unity中的使用必备_拖拽相关 : MonoBehaviour
{
void Start()
{
#region 知识点一 现有知识实现拖拽
//利用OnTouchBegin、OnTouchEnd、OnTouchMove事件可以完成拖拽功能
#endregion
#region 知识点二 FGUI中的自由拖拽功能
//获取对象设置 draggable属性为true 即可拖拽
//注意:拖动只能在元件父组件内移动
TeachPanel panel = UIManager.Instance.ShowPanel<TeachPanel>("Teach");
panel.m_btnTest.draggable = true;
//自由拖拽事件相关
//开始拖
panel.m_btnTest.onDragStart.Add(()=> {
print("开始拖");
});
//拖动中
panel.m_btnTest.onDragMove.Add(() => {
print("拖动中");
});
//结束拖
panel.m_btnTest.onDragEnd.Add(() => {
print("结束拖动");
});
#endregion
#region 知识点三 设置拖动范围
//注意,范围是舞台上的坐标 不是元件的本地坐标
//传入起始位置的xy和宽高为限制矩形
panel.m_btnTest.dragBounds = new Rect(500, 0, 1000, 200);
#endregion
}
}
41.3 练习题
在上节课的练习题基础上,请用现在所学知识,制作一个摇杆功能
创建摇杆的背景底图和摇杆装载器,设置好关联系统
创建摇杆变量和初始化位置变量,初始化赋值
public GLoader m_btnController;
//摇杆一开始所在的位置
private Vector2 initPos;
m_btnController = GetChild("btnController").asLoader;
initPos = m_btnController.position;
让摇杆能被拖拽。拖拽结束时还原位置。通过矩形判限制置不合适。在移动事件记录位移向量并限制范围。
//让摇杆小按钮能够被拖动
m_btnController.draggable = true;
//结束拖动时 让它的位置还原
m_btnController.onDragEnd.Add(() =>
{
m_btnController.position = initPos;
});
//可以通过矩形范围来判断 但是不建议 因为摇杆往往是圆形范围
//GObject bk = this.GetChild("n31");
//m_btnController.dragBounds = new Rect(bk.x, bk.y, bk.width, bk.height);
m_btnController.onDragMove.Add(() =>
{
//记录位移向量
Vector2 vec = m_btnController.xy - initPos;
//超过圆形半径 限制死范围
if (vec.magnitude >= 100)
{
m_btnController.xy = initPos + vec.normalized * 100;
}
});
41.4 练习题代码
/** This is an automatically generated class by FairyGUI. Please do not modify it. **/
using FairyGUI;
using FairyGUI.Utils;
using UnityEngine;
namespace Teach
{
public partial class ExercisesPanel : GComponent
{
//在上节课的练习题基础上
//请用现在所学知识,制作一个摇杆功能
public Controller m_RadioGroup;
public GRichTextField m_richTxt1;
public GRichTextField m_richTxt2;
public GTextInput m_inputTxt;
public GTextField m_txtInfo;
public GTextField m_txtName;
public GButton m_btnFire;
public GButton m_checkBoxMusic;
public GButton m_radioBoxOpen;
public GButton m_radioBoxClose;
public GSlider m_soundSlider;
public GButton m_btnBag;
public GImage m_imgF;
public GLoader m_imgA;
public GLoader m_imgB;
public GLoader m_btnController;
public const string URL = "ui://wrs19joehkfz2s";
private Player player;
//当前选中的图片替身 C
private GLoader tempImg;
//当前选中的图片对象
private GLoader nowSelImg;
//当前进入的图片对象
private GLoader nowInImg;
//摇杆一开始所在的位置
private Vector2 initPos;
public static ExercisesPanel CreateInstance()
{
return (ExercisesPanel)UIPackage.CreateObject("Teach", "ExercisesPanel");
}
public override void ConstructFromXML(XML xml)
{
base.ConstructFromXML(xml);
m_RadioGroup = GetControllerAt(0);
m_richTxt1 = (GRichTextField)GetChildAt(0);
m_richTxt2 = (GRichTextField)GetChildAt(1);
m_inputTxt = (GTextInput)GetChildAt(3);
m_txtInfo = (GTextField)GetChildAt(4);
m_txtName = (GTextField)GetChildAt(7);
m_btnFire = (GButton)GetChildAt(15);
m_checkBoxMusic = (GButton)GetChildAt(16);
m_radioBoxOpen = (GButton)GetChildAt(17);
m_radioBoxClose = (GButton)GetChildAt(18);
m_soundSlider = (GSlider)GetChildAt(19);
m_btnBag = (GButton)GetChildAt(20);
m_imgF = GetChild("imgF").asImage;
m_imgA = GetChild("imgA").asLoader;
m_imgB = GetChild("imgB").asLoader;
m_btnController = GetChild("btnController").asLoader;
initPos = m_btnController.position;
m_richTxt1.onClickLink.Add(Exercises.ClickLinkOpenPanel);
m_richTxt2.onClickLink.Add(Exercises.ClickLinkOpenPanel);
//输入文本练习题相关
m_inputTxt.onChanged.Add(() =>
{
//让文本控件的内容和输入的内容一致
m_txtInfo.text = m_inputTxt.text;
});
m_btnFire.onClick.Add(() =>
{
player.Fire();
});
m_checkBoxMusic.onChanged.Add(() =>
{
if (m_checkBoxMusic.selected)
GRoot.inst.EnableSound();
else
GRoot.inst.DisableSound();
});
Controller c = this.GetController("RadioGroup");
c.onChanged.Add(() =>
{
if (c.selectedIndex == 0)
GRoot.inst.EnableSound();
else
GRoot.inst.DisableSound();
});
m_soundSlider.onChanged.Add(() => {
GRoot.inst.soundVolume = (float)m_soundSlider.value;
});
m_btnBag.onClick.Add(() =>
{
//ExercisesBagPanel bagPanel = ExercisesBagPanel.CreateInstance();
//GRoot.inst.AddChild(bagPanel);
//显示背包面板
UIManager.Instance.ShowPanel<ExercisesBagPanel>("Teach");
});
m_imgA.onTouchBegin.Add(TouchBegin);
m_imgA.onTouchMove.Add(TouchMove);
m_imgA.onTouchEnd.Add(TouchEnd);
m_imgA.onRollOver.Add(InImg);
m_imgA.onRollOut.Add(OutImg);
m_imgB.onTouchBegin.Add(TouchBegin);
m_imgB.onTouchMove.Add(TouchMove);
m_imgB.onTouchEnd.Add(TouchEnd);
m_imgB.onRollOver.Add(InImg);
m_imgB.onRollOut.Add(OutImg);
//让摇杆小按钮能够被拖动
m_btnController.draggable = true;
//结束拖动时 让它的位置还原
m_btnController.onDragEnd.Add(() =>
{
m_btnController.position = initPos;
});
//可以通过矩形范围来判断 但是不建议 因为摇杆往往是圆形范围
//GObject bk = this.GetChild("n31");
//m_btnController.dragBounds = new Rect(bk.x, bk.y, bk.width, bk.height);
m_btnController.onDragMove.Add(() =>
{
//记录位移向量
Vector2 vec = m_btnController.xy - initPos;
//超过圆形半径 限制死范围
if( vec.magnitude >= 100 )
{
m_btnController.xy = initPos + vec.normalized * 100;
}
});
}
private void TouchBegin(EventContext eventData)
{
//如果希望之后的抬起 在对象外部也能够响应 那么需要添加一句代码
eventData.CaptureTouch();
//记录选择了谁
nowSelImg = eventData.sender as GLoader;
GLoader target = eventData.sender as GLoader;
tempImg = new GLoader();
//自动大小
tempImg.autoSize = true;
//设置图片路径
tempImg.url = target.url;
//改为半透明
tempImg.alpha = 0.5f;
//不能触摸 就不会挡住事件监听
tempImg.touchable = false;
//为了移动时和创建时 是中央和鼠标重合 那么我们可以通过锚点来改变
tempImg.SetPivot(0.5f, 0.5f, true);
//把物理坐标转为UI坐标
Vector2 nowPos = GRoot.inst.GlobalToLocal(new Vector2(eventData.inputEvent.x, eventData.inputEvent.y));
tempImg.SetPosition(nowPos.x, nowPos.y, 0);
this.AddChild(tempImg);
}
private void TouchMove(EventContext eventData)
{
//不停的在内部设置位置即可
Vector2 nowPos = GRoot.inst.GlobalToLocal(new Vector2(eventData.inputEvent.x, eventData.inputEvent.y));
tempImg.SetPosition(nowPos.x, nowPos.y, 0);
}
private void TouchEnd()
{
//松手时 就是真正产生交换的位置
if( nowInImg != null && nowSelImg != null &&
nowInImg != nowSelImg )
{
//只有有选中的和需要进入交换的 就可以执行交换逻辑了
string tmp = nowSelImg.url;
nowSelImg.url = nowInImg.url;
nowInImg.url = tmp;
}
//删除图片
if (tempImg != null)
tempImg.Dispose();
tempImg = null;
//不管你交换是否完成 都应该置空
nowSelImg = null;
nowInImg = null;
}
private void InImg(EventContext eventData)
{
//记录进入了谁
nowInImg = eventData.sender as GLoader;
}
private void OutImg(EventContext eventData)
{
//记录离开了谁
nowInImg = null;
}
/// <summary>
/// 更新图片位置
/// </summary>
/// <param name="inputPos">鼠标位置</param>
public void UpdateImgPos(Vector3 inputPos)
{
//要把屏幕坐标(鼠标位置)转换成UI坐标 不停的赋值给跟随移动的图片
//相对于FGUI坐标系的 物理坐标
inputPos.y = Screen.height - inputPos.y;
//物理坐标 转 逻辑坐标(UI坐标)
m_imgF.position = GRoot.inst.GlobalToLocal(inputPos);
}
public void SetPlayer(Player player)
{
this.player = player;
}
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com