unity虚拟摇杆

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity虚拟摇杆相关的知识,希望对你有一定的参考价值。

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

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

Unity插件研究-EasyTouch V5

抽空研究了下Easy Touch 5插件,发现确实很好用,下面是相应的用法:

1. Easy Touch Controls:实现虚拟摇杆的组件

        在项目的"Hierarchy"窗口下,创建摇杆操作点击GameObject=>EasyTouchControls=>Joystick,创建完之后会在Hierarchy面板出现摇杆物体,Game视图也会出现一个摇杆,这个插件应该是基于UGUI写的,它的物体出现方式和创建Canvas下的控件一样(所以自定义事件和UGUI添加事件的方法基本是类似的),也会出现Canvas和EventSystem,而Joystick也会成为Canvas的子物体。添加完摇杆,还会出现一个"InputManager"的游戏物体,这个应该是EasyTouch用来实现用户输入的控制的,如果删除这个游戏物体,游戏运行时就会动态生成这个游戏物体,下面是一些配置:

           技术图片    名字、启动时是否可见,是否激活,如果有物理引擎,是需要使用FixedUpdate的

           技术图片  摇杆显示的位置,偏移量、尺寸大小

             技术图片 摇杆的轴配置,这是水平轴的,比如控制物体旋转,Speed设置为200,给它控制的物体(也可以使用Auto link on tag,使用标签方式),Action使用"Rotate Local",基于“Y"轴

            技术图片 摇杆的轴配置,这是垂直轴的,用来配置延”Z"轴进行前后移动

           技术图片   实现第三人称游戏时,经常需要相机跟随,可以“Enable tracking",使用”MainCamera",链接好要跟随的游戏物体,相机跟随使用“Smooth Follow",可以控制相机跟随的高度、距离、

            技术图片   这个用来配置虚拟摇杆的图片

            如果不用自动配置,想使用自己的代码来控制物体移动,代码中是使用:

ETCInput.GetAxis("Vertical")
ETCInput.GetAxis("Horizontal")

            唯一不好的是这个插件导入后,给了一大堆示例和文档,如果是项目开发会增加不少的size,做了相应的精减,只有200多K了https://files-cdn.cnblogs.com/files/bearhb/EasyTouchControls-min.rar

 2. Easy Touch:实现手势控制的组件

      (1)Hierarchy窗口中必须右键,生成"EasyTouch" ->"EasyTouch"物体;

      (2)QuickGesture:这个实在是太猛了, 如果想给某个游戏物体添加手势的一些事件,直接添加下面某个组件就可以了:

                 技术图片 例如一个cube如果想被拖动,直接添加“Quick Drag"组件,这个Cube就可以实现拖动了,而且拖动的事件和UGUI完全一致;

      (3)如果需要在程序中进行手势判断,是需要下面的脚本:

using HedgehogTeam.EasyTouch;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TouchManager : MonoBehaviour

    private Renderer ren;
    private void Start()
    
        ren = GetComponent<Renderer>();
    
    void Update()
    
        
        // 获取当前玩家输入的手势
        Gesture currentGesture = EasyTouch.current;
        //如果有手势
        if (currentGesture != null)
        
            //区分手势进行检测
            switch (currentGesture.type)
            
                //开始触摸
                case EasyTouch.EvtType.On_TouchStart:
                    Debug.Log("OnTouchStart");
                    Debug.Log("startPosition" + currentGesture.startPosition);
                    OnTouchStart(currentGesture);
                    break;
                //结束触摸
                case EasyTouch.EvtType.On_TouchUp:
                    OnTouchEnd(currentGesture);
                    break;
                //开始滑动
                case EasyTouch.EvtType.On_Swipe:
                    OnSwipe(currentGesture);
                    break;
                //简单点击下
                case EasyTouch.EvtType.On_SimpleTap:
                    Debug.Log("点击下");
                    break;
                //长按
                case EasyTouch.EvtType.On_LongTap:
                    Debug.Log("长按");
                    break;
                  
        
    
    void OnTouchEnd(Gesture gesture)
    
        Debug.Log("OnTouchEnd");
        Debug.Log("actionTime" + gesture.actionTime);
    

    void OnSwipe(Gesture gesture)
    
        Debug.Log("OnSwipe");
        //滑动的枚举(上、下、左、右、其他)
        Debug.Log("swipe" + gesture.swipe);
    

    void OnTouchStart(Gesture gesture)
    
        if (gesture.pickedObject == gameObject)
        
            ren.material.color = new Color(Random.Range(0, 1.0f), Random.Range(0, 1.0f), Random.Range(0, 1.0f));
        
    

 

 

             

 

以上是关于unity虚拟摇杆的主要内容,如果未能解决你的问题,请参考以下文章

unity中虚拟摇杆的实现

unity 第一人称角色控制器手机虚拟双摇杆

unity easytouch怎么用?unity easytouch摇杆怎么做?

简单的虚拟摇杆控制移动(NGUI)

NGUI版虚拟摇杆

用代码写一个虚拟摇杆