<Unity UGUI><EasyTouch> 使用EasyTouch, 摇杆在Dynamic模式下,点击UI控件也会弹出的问题解决

来源:互联网 发布:php7 apache mysql环境 编辑:程序博客网 时间:2024/05/16 08:29

转载请标明出处:http://blog.csdn.net/u013015161/article/details/46495561

使用EasyTouch插件,其提供的虚拟摇杆有一个Dynamic stick属性, 勾选之后, 只有当鼠标或者手指触摸到屏幕, 才会在手指或鼠标触碰的位置出现虚拟摇杆。

当场景中存在UI控件时,会出现以下场景。


很显然 , 当玩家点击按钮的时候依然弹出虚拟摇杆是不合理的。


解决这个问题,首先得看虚拟摇杆何时会弹出, 在EasyJoystick.cs中可以找到以下代码:

if ((showZone && areaTexture!=null && !dynamicJoystick) || (showZone && dynamicJoystick && virtualJoystick && areaTexture!=null) || (dynamicJoystick && Application.isEditor && !Application.isPlaying)){if (isActivated){GUI.color = areaColor;if (Application.isPlaying && !dynamicJoystick){EasyTouch.RemoveReservedArea( areaRect );EasyTouch.AddReservedArea( areaRect );}}else{GUI.color = new Color(areaColor.r,areaColor.g,areaColor.b,0.2f);if (Application.isPlaying && !dynamicJoystick){EasyTouch.RemoveReservedArea( areaRect );}}if (showDebugRadius && Application.isEditor){GUI.Box( areaRect,"");}                GUI.DrawTexture( areaRect, areaTexture,ScaleMode.StretchToFill,true);}

可以看到,当摇杆模式为dynamic时, 要判断virtualJoystick值。 于是跟踪该变量,可以找到以下代码(起始行:1386)

void On_TouchStart(Gesture gesture){if ((!gesture.isHoverReservedArea && dynamicJoystick) || !dynamicJoystick){if (isActivated){if (!dynamicJoystick){Vector2 center = new Vector2( (anchorPosition.x+joystickCenter.x) * VirtualScreen.xRatio , (VirtualScreen.height-anchorPosition.y - joystickCenter.y) * VirtualScreen.yRatio);if ((gesture.position - center).sqrMagnitude < (zoneRadius *VirtualScreen.xRatio )*(zoneRadius *VirtualScreen.xRatio )){joystickIndex = gesture.fingerIndex;CreateEvent(MessageName.On_JoystickTouchStart);}}else{if (!virtualJoystick){#region area restriction<span style="color:#ff0000;">switch (area){// fullcase DynamicArea.FullScreen:virtualJoystick = true;;break;// bottomcase DynamicArea.Bottom:if (gesture.position.y< Screen.height/2){virtualJoystick = true;}break;// topcase DynamicArea.Top:if (gesture.position.y> Screen.height/2){virtualJoystick = true;}break;// Rightcase DynamicArea.Right:if (gesture.position.x> Screen.width/2){virtualJoystick = true;}break;// Leftcase DynamicArea.Left:if (gesture.position.x< Screen.width/2){virtualJoystick = true;}break;// top Rightcase DynamicArea.TopRight:if (gesture.position.y> Screen.height/2 && gesture.position.x> Screen.width/2){virtualJoystick = true;}break;// top Leftcase DynamicArea.TopLeft:if (gesture.position.y> Screen.height/2 && gesture.position.x< Screen.width/2){virtualJoystick = true;}break;// bottom Rightcase DynamicArea.BottomRight:if (gesture.position.y< Screen.height/2 && gesture.position.x> Screen.width/2){virtualJoystick = true;}break;// bottom leftcase DynamicArea.BottomLeft:if (gesture.position.y< Screen.height/2 && gesture.position.x< Screen.width/2){virtualJoystick = true;}break;}</span>#endregionif (virtualJoystick){joystickCenter =new Vector2(gesture.position.x/VirtualScreen.xRatio,  VirtualScreen.height - gesture.position.y/VirtualScreen.yRatio);JoyAnchor = JoystickAnchor.None;joystickIndex = gesture.fingerIndex;}}}}}}
可以看到,在touch时间发生时, 会判断触点是否在目标区域(分上、下、左、右屏等,可以在joystick的属性面板调整)来决定是否出现虚拟摇杆(即virtualJoystick的值)。

所以如果要防止开头描述的问题,只需要在virtualJoystick赋值为true之前判断以下当前是否触摸或点击在UGUI上即可。

实现该判断,常见的方法是判断EventSystem.current.IsPointerOverGameObject()的返回值。但该值在触屏设备上总是返回false。

Unity官方论坛上有人整理了一份代码(点击进入相关帖子),pc和触屏设备都可以正常检测代码,代码如下

using UnityEngine;using System.Collections;using UnityEngine.UI;using UnityEngine.EventSystems;using System.Collections.Generic;public class IPointerOverUI {         private static IPointerOverUI instance = new IPointerOverUI();        public static IPointerOverUI Instance        {                get{                        return instance;                }        }         public bool IsPointerOverUIObject(Canvas canvas, Vector2 screenPosition) {                PointerEventData eventDataCurrentPosition = new PointerEventData(EventSystem.current);                eventDataCurrentPosition.position = screenPosition;                                 GraphicRaycaster uiRaycaster = canvas.gameObject.GetComponent<GraphicRaycaster>();                List<RaycastResult> results = new List<RaycastResult>();                uiRaycaster.Raycast(eventDataCurrentPosition, results);                return results.Count > 0;        }         public bool IsPointerOverUIObject() {                PointerEventData eventDataCurrentPosition = new PointerEventData(EventSystem.current);                eventDataCurrentPosition.position = new Vector2(Input.mousePosition.x, Input.mousePosition.y);                                 List<RaycastResult> results = new List<RaycastResult>();                EventSystem.current.RaycastAll(eventDataCurrentPosition, results);                return results.Count > 0;        }}
可以看到, 2个方法虽然参数不同,但主要思路都是通过发射射线进行判断, 如果射线碰撞到了UI控件,则判定在触碰UGUI控件上。经检验和分析,第一种方法需要传入特定canvas, 而第二种是以Input.mousePosition作为触点的位置, 在多点触控时, 显然不可能每个点的位置都用该值描述(通常该值仅代表第一个触点的位置)。于是自己新增一个重载函数:

public bool IsPointerOverUIObject(float x, float y) {        PointerEventData eventDataCurrentPosition = new PointerEventData(EventSystem.current);        eventDataCurrentPosition.position = new Vector2 (x, y);                List<RaycastResult> results = new List<RaycastResult>();        EventSystem.current.RaycastAll(eventDataCurrentPosition, results);        return results.Count > 0;    }

在EasyJoystick.cs中调用如下(起始行:1386):

void On_TouchStart(Gesture gesture){        /*added by lankton  2015 6 14*/        if (IPointerOverUI.Instance.IsPointerOverUIObject (gesture.position.x, gesture.position.y))         { /*点击在UGUI上 则不处理EasyTouch的触摸事件*/            return;        }        /*end*/


这样,对EasyTouch插件进行了简单的补充, UGUI和EasyTouch的虚拟摇杆就能正常的同时使用了:



0 0
原创粉丝点击