unity虚拟摇杆

unity虚拟摇杆,第1张

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

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

新建一个unity3d项目“EasyTouch_test”。

通过“Assets”--“Import Package”--“Custom  Package”导入easytouch.unitypackage,我这里用的3.1的版本,d出的窗口直接“Import”,出现兼容问题直接“I Make a Backup. Go Ahead”。

在场景中新建一个“Cube”,加上“Rigidbody”。

通过菜单中的”Tools“--”Hedgehog Team“--”EasyTouch“--”Extensions“--”Adding a new joystick“。

选择创建的”xxxxJoystick“,

把其中的 ”Joystick name“ 重新命名为 ”MoveJoystick“,

把下面的”Interaction type“设置为”Direct And Event“。

新建一个”Script“文件夹并新建一个”Easymove“的C#脚本,在其中添加如下的代码:

using UnityEngine

using System.Collections

public class Easymove : MonoBehaviour {

// Subscribe to events  

void OnEnable(){  

EasyTouch.On_TouchStart += On_TouchStart 

EasyJoystick.On_JoystickMove += OnJoystickMove 

EasyJoystick.On_JoystickMoveEnd += OnJoystickMoveEnd 

}  

// Unsubscribe  

void OnDisable(){  

EasyTouch.On_TouchStart -= On_TouchStart 

}  

// Unsubscribe  

void OnDestroy(){  

EasyTouch.On_TouchStart -= On_TouchStart 

}  

// Touch start event  

public void On_TouchStart(Gesture gesture){  

Debug.Log( "Touch in " + gesture.position) 

}

//摇杆结束  

void OnJoystickMoveEnd(MovingJoystick move)  

{   

if (move.joystickName == "MoveJoystick")  

{  

}  

}  

//移动摇杆中  

void OnJoystickMove(MovingJoystick move)  

{  

if (move.joystickName != "MoveJoystick")  

{  

return 

}  

//摇杆偏移坐标 

float joyPositionX = move.joystickAxis.x 

float joyPositionY = move.joystickAxis.y 

if (joyPositionY != 0 || joyPositionX != 0)  

{  

//设置人物朝向

transform.LookAt(new Vector3(transform.position.x + joyPositionX, transform.position.y, transform.position.z + joyPositionY)) 

//移动

transform.Translate(Vector3.forward * Time.deltaTime * 10) 

}  

}  

}

编辑完成后把”Easymove“脚本拖拽添加到”Cube“中,然后运行就完成了,很简单吧。

虚拟摇杆由3部分组成

虚拟摇杆GameObject的层级

触屏控制

VirtualJoystick.cs

监听触屏、滑屏相关事件,发出自己的事件

VirtualJoystickAppearance.cs

虚拟摇杆的显示(包括设置其位置等)。

InputMgr.cs

监听虚拟摇杆的事件(SetDirEvent、StopSetDirEvent),控制Player移动。

Player.cs

外界(InputMgr)调用其Move方法控制其移动。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/bake/11738042.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-18
下一篇 2023-05-18

发表评论

登录后才能评论

评论列表(0条)

保存