使用UGUI制作底盘不固定的虚拟摇杆

看好多人做虚拟摇杆都用的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]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值