看好多人做虚拟摇杆都用的easytouch,一个大盘一个小盘一直摆在左下角,感觉丑爆了有木有{:86:}
正好最近在做u2d,就自己弄了一个,特点是平时不显示,触摸屏幕后大盘出现在屏幕触摸位置,滑动时小盘跟随移动,但限制在大盘内,我看好多安卓游戏都用的这种方式,比如现代战争等
要做出这种效果,我们要先知道Input.GetTouch(N).position可以获取第N个触摸位置的坐标
Input.GetTouch(0).phase == TouchPhase.Began 判断是否为手指触摸的第一帧,也就是刚触摸上去注意Canvas的RenderMode要设置为ScreenSpace-Camera,因为这个模式下UI物体是有坐标的;不要设置为Overlay,OverLay模式下是无法移动底盘的
首先,start里把两个盘子GameObject的active设为false
在Update里判断Input.touchCount,也就是触摸数,是否大于,0,如果大于0,判断Input.GetTouch(0).position.x是否小于Screen.width/2(因为我做的是只有左半边屏幕控制移动)
如果小于,而且Input.GetTouch(0).phase == TouchPhase.Began就可以把两个盘子setactive(true)显示出来了,
接下来先不考虑滑动的情况,先来想一想什么情况下可以把盘子设为不显示状态
如果继续上面的想法,判断touchcount,x<screen.width/2 ,phase==Ended的话就错了,因为可能你的手从左边滑到右边去了,这时手已经不在左边操控区,盘子应该设为不显示
我的做法是声明一个bool=false,在Update最后判断bool是否为true,是的话改为false,不是的话,就让两个盘子消失
同时在检测到touchcount,x<screen.width/2时使bool=true,同时改变小盘位置
代码如下
[mw_shl_code=csharp,true]StillTouch = true;
Vector3 JPos=Camera.main.ScreenToWorldPoint(Pos);
if(Mathf.Pow(JPos.x-BackGrounds.position.x,2)+Mathf.Pow(JPos.y-BackGrounds.position.y,2)>9)
{
Vector2 PosTemp = new Vector2(JPos.x-BackGrounds.position.x,JPos.y-BackGrounds.position.y).normalized;
Joystick.position = new Vector3(BackGrounds.position.x+PosTemp.x*3f,BackGrounds.position.y+PosTemp.y*3f,Joystick.position.z);
}
else
{
Joystick.position = new Vector3(JPos.x,JPos.y,Joystick.position.z);
}[/mw_shl_code]
Camera.main.ScreenToWorldPoint屏幕坐标转为世界坐标
Mathf.Pow(M,N)计算M的N次方
此时注意,我normalized的变量是一个Vector2,这是因为Z轴是不确定的,可能JPos-BackGrounds.position=(1,0,1000),这样normalized后得到的是(0,0,1)
而我们希望得到的是(1,0,0)!
完整代码↓
[mw_shl_code=csharp,true]public class InputManager : MonoBehaviour {
public Transform Joystick;
public Transform BackGrounds;
private bool StillTouch = false;
private int HalfWidth;
private Vector2 LPos;
private Vector2 LOldPos;
private Vector2 RPos;
private Vector2 ROldPos;
private Vector2 MoveVector;
// Use this for initialization
void Awake()
{
Joystick = GameObject.Find("Joystick").transform;
BackGrounds = GameObject.Find("Backgrounds").transform;
}
void Start () {
Joystick.gameObject.SetActive(false);
BackGrounds.gameObject.SetActive(false);
HalfWidth=Screen.width/2;
}
// Update is called once per frame
void Update () {
if(Input.touchCount == 1)
{
OneTouchUpdate();
}
if(StillTouch)
{
StillTouch = false;
}
else
{
Joystick.gameObject.SetActive(false);
BackGrounds.gameObject.SetActive(false);
}
}
private void OneTouchUpdate()
{
if(Input.GetTouch(0).phase==TouchPhase.Began)
{
SetOldPos(Input.GetTouch(0).position);
}
SetPos(Input.GetTouch(0).position);
if(Input.GetTouch(0).phase==TouchPhase.Ended)
{
EndPos(Input.GetTouch(0).position,Input.GetTouch(0).phase==TouchPhase.Moved);
}
}
private void SetOldPos(Vector2 Pos)
{
if(Pos.x>HalfWidth)
{
ROldPos = Pos;
}
else
{
LOldPos = Pos;
Vector2 JPos=Camera.main.ScreenToWorldPoint(Pos);
Joystick.gameObject.SetActive(true);
BackGrounds.gameObject.SetActive(true);
StillTouch = true;
Joystick.position = new Vector3(JPos.x,JPos.y,Joystick.position.z);
BackGrounds.position = new Vector3(JPos.x,JPos.y,BackGrounds.position.z);
}
}
private void SetPos(Vector2 Pos)
{
if(Pos.x>HalfWidth)
{
RPos = Pos;
}
else
{
LPos = Pos;
MoveVector = LPos - LOldPos;
//localEventManager.Move(MoveVector.x,MoveVector.y);移动
StillTouch = true;
Vector3 JPos=Camera.main.ScreenToWorldPoint(Pos);
if(Mathf.Pow(JPos.x-BackGrounds.position.x,2)+Mathf.Pow(JPos.y-BackGrounds.position.y,2)>9)
{
Vector2 PosTemp = new Vector2(JPos.x-BackGrounds.position.x,JPos.y-BackGrounds.position.y).normalized;
Joystick.position = new Vector3(BackGrounds.position.x+PosTemp.x*3f,BackGrounds.position.y+PosTemp.y*3f,Joystick.position.z);
}
else
{
Joystick.position = new Vector3(JPos.x,JPos.y,Joystick.position.z);
}
}
}
}
[/mw_shl_code]