unity虚拟摇杆

在手机游戏中,虚拟摇杆游戏中的虚拟遥感很常见,先根据自己已经会虚拟摇杆来制作,虚拟摇杆醉主要的核心是

C#部分

2D虚拟摇杆

先弄个自定义的触发事件,然后给每一个需要触发的事件按钮添加,EventTrigget,需要注意的是这个事件要继承unity的接口,

制作unity的摇杆的话,需要继承unity的的UI接口 IBeginDragHandler, IDragHandler, IEndDragHandler,IPointerClickHandler

第一先定义四个委托

    public Action<GameObject, PointerEventData> onBeginDrag;

    public Action<GameObject, PointerEventData> onDrag;

    public Action<GameObject, PointerEventData> onEndDrag;

    public Action<GameObject, PointerEventData> onClick;

其次是重写unity继承的四个接口,把每个委托的回调放进去这些接口函数里面,一但满足条件,委托会执行函数回调方法

public void OnBeginDrag(PointerEventData eventData)   {

        if (onBeginDrag != null)

        {

            onBeginDrag(gameObject, eventData);

        }

    }

    public void OnDrag(PointerEventData eventData) {

        if (onDrag != null)

        {

            onDrag(gameObject, eventData);

        }

    }

    public void OnEndDrag(PointerEventData eventData) {

        if (onEndDrag != null)

        {

            onEndDrag(gameObject, eventData);

        }

    }

    public void OnPointerClick(PointerEventData eventData){

        if (onClick != null)

        {

            onClick(gameObject, eventData);

        }

    }

有了这些委托方法之后,如何使用,这个调用方法,会在初始化注册事件,

public static EventTrigger GetEventCallBack(GameObject obj)

    {

        Event trigger = obj.GetComponent<EventTrigger>();

        if (trigger == null)

        {

            trigger = obj.AddComponent<EventTrigger>();

        }

        return trigger;

}

创建以一个控制虚拟摇杆StickJoyUI脚本,注册委托事件

        TriggerEvent.Get(bgObj).onBeginDrag = OnDragBegin;

        TriggerEvent.Get(bgObj).onDrag = OnDrag;

        TriggerEvent.Get(bgObj).onEndDrag = OnDragEnd;

        TriggerEvent.Get(transform.Find(“changeAttack”).gameObject).onClick = OnChangeAttack;

        TriggerEvent.Get(transform.Find(“AttackBtn”).gameObject).onClick = OnAttackBtn;

再来看看虚拟摇杆部分OnDragBegin OnDrag  OnDragEnd 这个三个方法控制虚拟摇杆,

private void OnDragBegin(GameObject obj, PointerEventData evetData)

    {

    }

    private void OnDrag(GameObject obj, PointerEventData evetData)

{        Vector2 point;

        //ScreenPointToLocalPointInRectangle(“需要转换的对象的父级的RectTrasform”,”鼠标的位置”,”当前的摄像机”,”转换后的ui的相对坐标”)

       bg为要拖拽的对象的父级对象,里面还有一个小圆PointTf,鼠标的位置取拖拽事件的的position,鼠标的位置取拖拽事件的的摄像机,转

        if (RectTransformUtility.ScreenPointToLocalPointInRectangle(bgTf, evetData.position, evetData.pressEventCamera, out point))    {

            //拖动的方向

            Vector2 v = (point – Vector2.zero).normalized;

            x = v.x;

            y = v.y;

            if (Vector2.Distance(point, Vector2.zero) <= R)   

            {

                pointTf.anchoredPosition = point;

            }

            else     //超出移动的半径

            {

                //位置 = 初始位置 + 方向 * 距离

                pointTf.anchoredPosition = Vector2.zero + v * R;

            }

        }

    }

    private void OnDragEnd(GameObject obj, PointerEventData evetData)

    {

        pointTf.anchoredPosition = Vector2.zero;

        x = 0;

        y = 0; 

    }

Ps:2D角色还需要注意人物朝向问题

只需要把里面的的X值和Y值赋予给他实时更新,然后在写一个Flip方法判断朝向问题,本质是修改一下缩放的X改成相反的值就好了

//朝向

    void Flip()

    {

        if (x > 0)

        {

            transform.localScale = new Vector3(1, 1, 1);

        }

        else if (x < 0)

        {

            transform.localScale = new Vector3(-1, 1, 1);

        }

    }

3D模式:把把X值和Y赋予个移动函数的x值和z值即可

接下用JS实现虚拟摇杆(思路跟上面差不多,但是数据的处理稍有差别而已)

第一引入玩家模块

var Player = require(“player”);

属性定义

cc.Class({

    extends: cc.Component,

    properties: {

        stickNode:{

            default:null,

            type:cc.Node

        },

        fillNode:{

            default:null,

            type:cc.Node

        },

        skillBtn:{

            default:null,

            type:cc.Node

        },

        player:{

            default:null,

            type:Player

        },

        R:50,

        stick_x:0,

        stick_y:0

    },

在初始化函数Onlade中注册事件

  onLoad () {

        this.stickNode = cc.find(“Stick”,this.node);

        this.fillNode = cc.find(“Stick/fill”,this.node);

        this.skillBtn = cc.find(“skillBtn”,this.node);

    //注册开始拖拽,拖拽事件,拖拽结束事件,和点击事件,这个更上面的四个接口类似

        this.stickNode.on(cc.Node.EventType.TOUCH_START,this.onTouchStart,this); 

        this.stickNode.on(cc.Node.EventType.TOUCH_MOVE,this.onTouchMove,this);

        this.stickNode.on(cc.Node.EventType.TOUCH_END,this.onTouchEnd,this);

        this.stickNode.on(cc.Node.EventType.TOUCH_CANCEL,this.onTouchCancel,this);

        this.skillBtn.on(“click”,this.onClickSkillBtn,this);

    },

  onTouchStart(event)

    {

    },

    onTouchMove(event)

    {

        var pos = event.getLocation();//v2类型 坐标系

        //当前这个鼠标的世界坐标转换成当前节点的相对坐标  

        pos = this.stickNode.convertToNodeSpaceAR(pos);

        if(pos.magSqr()<=this.R*this.R)

        {

            this.fillNode.setPosition(pos);

        }

        else

        {

            this.fillNode.x = pos.normalizeSelf().x*this.R;

            this.fillNode.y = pos.normalizeSelf().y*this.R;

        }  

       this.stick_x = pos.normalizeSelf().x;

        this.stick_y = pos.normalizeSelf().y;

    },

    onTouchEnd(event)

    {

        this.fillNode.x = 0;

        this.fillNode.y = 0;

        this.stick_x = 0;

        this.stick_y = 0;

    },

    onTouchCancel(event)

    {

        this.fillNode.x = 0;

        this.fillNode.y = 0;

        this.stick_x = 0;

        this.stick_y = 0;

    },

    onClickSkillBtn()

    {

        //执行玩家脚本使用技能的方法

        this.player.playSkill();

    }

PS:计算上面的pos的方向,  上面为啥半径平方而不是把开方呢??,开方消耗性能,给半径平方两者比较也能比较,相对与前者开方,后者半径平方更加节省性能,采用迂回思路,感觉这种思想有许多地方都用到,就列如前面的浮点数处理,既然有误差,那么我可以放大倍数,然后要使用时候,我再缩小倍数。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容