市面上最常见的就是EasyTouch,不过现在下不到了而且也没学会,所以自己研究出来一套方式来应对手机端操作UGUI,应该和EasyTouch类似(没怎么用过EasyTouch)
实现了点击事件,拖拽功能,松开事件,放在固定点的事件,四个最常用的功能
应用这篇文章里的内容用上了前面获取手机端操作的代码:https://blog.csdn.net/qq_39332021/article/details/106625199
首先是大脚本TakeEvent
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public abstract class TakeEvent: MonoBehaviour
{
public List<MovePos> movepos = new List<MovePos>();
protected bool move , movetopos;
protected Vector3 oldpos , handoldpos,way;
protected RectTransform moverect;
protected GameObject g;
//制作的时候设定的屏幕长宽,子类可以改,和Canvas上的属性一起动
protected Vector2 screensetsize = new Vector2(1080.0f,1920.0f);
public void Setmove(RectTransform moveobject)
{
move = true;
moverect = moveobject;
oldpos = moveobject.anchoredPosition;
handoldpos = GameManager.Main.GetPos();
}
public void SetmoveToPos(RectTransform moveobject)
{
Setmove(moveobject);
movetopos = true;
}
protected GameObject GetMovePos(Vector2 v)
{
if ((float)Screen.width / Screen.height < screensetsize.x / screensetsize.y)
{
//竖屏
v.x = v.x/screensetsize.x*Screen.width + Screen.width / 2.0f;
v.y = v.y/(screensetsize.x/Screen.width*Screen.height)*Screen.height + Screen.height / 2.0f;
}
else
{
//横屏
v.x = v.x/(screensetsize.y*Screen.width/Screen.height)*Screen.width + Screen.width / 2.0f;
v.y = v.y/screensetsize.y*Screen.height + Screen.height / 2.0f;
}
foreach (MovePos m in movepos)
{
g = m.GetIsPos(v);
if (g)
{
return g;
}
}
return null;
}
public abstract void SetClick(GameObject click);
public abstract void SetClickOver(GameObject click);
public abstract void MoveEnd(RectTransform click);
public abstract void FatherUpdate();
private void Update()
{
Move();
FatherUpdate();
}
protected virtual void Move()
{
if (move)
{
way = GameManager.Main.GetPos() - handoldpos;
moverect.anchoredPosition = oldpos + way;
if (GameManager.Main.GetClickUp())
{
move = false;
if (movetopos)
{
MoveEnd(moverect);
movetopos = false;
}
}
}
}
}
一个抽象类,自己写一个脚本继承TakeEvent放到场景里,然后抽象方法里随便写点啥就可以用了,里面的四个抽象方法分别是点击触发事件,点击结束事件,拖拽结束事件,跟Update,继承了就不要写Update了不然会把父类的Update替换掉。前面三个抽象方法的参数都是被点击的物体,拖拽结束事件是被拖拽的物体。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public abstract class GetHand : MonoBehaviour
{
protected RectTransform rect;
protected TakeEvent takeEvent;
// Start is called before the first frame update
void Start()
{
rect = gameObject.GetComponent<RectTransform>();
takeEvent = GameObject.FindObjectOfType<TakeEvent>();
start();
}
protected abstract void start();
protected bool GetTouch()
{
PointerEventData pointerEventData = new PointerEventData(EventSystem.current);
if (SystemInfo.deviceType == DeviceType.Desktop)
{
pointerEventData.position = GameManager.Main.GetMousePos();
}
else
{
pointerEventData.position = GameManager.Main.GetHandPos();
}
GraphicRaycaster gr = gameObject.transform.parent.GetComponent<GraphicRaycaster>();
List<RaycastResult> results = new List<RaycastResult>();
gr.Raycast(pointerEventData, results);
if (results.Count != 0)
{
if (results[0].gameObject.name == gameObject.name)
{
return true;
}
}
return false;
}
protected bool GetTouch(Vector2 v)
{
PointerEventData pointerEventData = new PointerEventData(EventSystem.current);
pointerEventData.position = v;
GraphicRaycaster gr = gameObject.transform.parent.GetComponent<GraphicRaycaster>();
List<RaycastResult> results = new List<RaycastResult>();
gr.Raycast(pointerEventData, results);
if (results.Count != 0)
{
if (results[0].gameObject.name == gameObject.name)
{
return true;
}
}
return false;
}
}
又是一个抽象类,但是这个不用管,这个是用来别的工具类需要继承的,主要实现了判断手指鼠标或者某个点在不在自己的身上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class GetClick : GetHand
{
protected override void start()
{
}
// Update is called once per frame
void Update()
{
if (GameManager.Main.GetClick())
{
if (GetTouch())
{
takeEvent.SetClick(gameObject);
}
}
}
}
直接把这个脚本挂在场景中的物体上,如果挂载的物体被点击了直接调用TakeEvent里面的抽象事件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class GetClickOver : GetHand
{
protected override void start()
{
}
// Update is called once per frame
void Update()
{
if (GameManager.Main.GetClickUp())
{
if (GetTouch())
{
takeEvent.SetClickOver(gameObject);
}
}
}
}
和上一个一样,这个获取的是抬起
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class GetMove : GetHand
{
protected override void start()
{
}
// Update is called once per frame
void Update()
{
if (GameManager.Main.GetClick())
{
if (GetTouch())
{
takeEvent.Setmove(rect);
}
}
}
}
这个脚本挂在场景上被挂载的物体可以被鼠标或者手直接拖动,不过仅仅只是能拖动,没别的功能
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class GetMoveToPos : GetHand
{
protected override void start()
{
}
// Update is called once per frame
void Update()
{
if (GameManager.Main.GetClick())
{
if (GetTouch())
{
takeEvent.SetmoveToPos(rect);
}
}
}
}
这个和上面功能一样,但是不同的是拖动结束后会调用一次TakeEvent里面的MoveEnd方法,可以用来判断是否将物体拖到了某个位置上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class MovePos : GetHand
{
protected override void start()
{
takeEvent.movepos.Add(this);
}
public GameObject GetIsPos(Vector2 v)
{
if (GetTouch(v))
{
return gameObject;
}
else
{
return null;
}
}
}
挂在被拖到的位置上,这个要和拖拽的物体分别放在两个画布上,不然会重叠不能判断,继承TakeEvent的代码在MoveEnd直接调用GetMovePos()参数传click.anchoredPosotion就能返回物体被拖拽到了哪个物体上
就这么几个功能,记住不动的背景,动的物体,尽量分开放到多个Canvas上 动的物体和被拖到的位置 必须分开放
功能是通过物体的名字判断的,尽量让场景能点的能拖得都不要重名,不然会出BUG