怎么用NGUI做ngui 虚拟摇杆杆

NGUI版虚拟摇杆 - 推酷
NGUI版虚拟摇杆
下面是我用nui实现的一个虚拟摇杆。
2、代码如下,都有比较详细的注释,就不说明了。
using UnityE
using System.C
using System.Collections.G
[ExecuteInEditMode]
public class Joystick : MonoBehaviour
#region Delegate & Event
public delegate void JoystickEventHandler(Joystick joystick);
/// &summary&
/// &/summary&
public static event JoystickEventHandler On_JoystickMoveS
/// &summary&
/// Occurs when the joystick move.
/// &/summary&
public static event JoystickEventHandler On_JoystickM
/// &summary&
/// thumb偏离中心位置,并牌按住时,每帧的回调
/// &/summary&
public static event JoystickEventHandler On_JoystickH
/// &summary&
/// Occurs when the joystick stops move
/// &/summary&
public static event JoystickEventHandler On_JoystickMoveE
#endregion
[SerializeField] bool isRunInEditor =
[SerializeField]private string joystickName = &NguiJoystick&;
public string JoystickName { get { return this.joystickN } }
[HideInInspector]private bool isLimitInCircle =
public bool IsLimitInCircle { get { return this.isLimitInC } }
[SerializeField]private int radius = 100;
public int Radius { get{ return this. } }
[SerializeField]
private float minAlpha = 0.3f;
public float MinAlpha { get { return this.minA } }
private Vector2 joystickAxis = Vector2.
/// &summary&
/// Gets the joystick axis value between -1 & 1...
/// &/summary&
/// &value&
/// The joystick axis.
/// &/value&
public Vector2 JoystickAxis { get { return this.joystickA } }
private Vector2 lastJoystickAxis = Vector2.
public Vector2 LastJoystickAxis { get { return this.lastJoystickA } }
bool isForBid =
/// &summary&
/// 判断joystick是否被禁用
/// &/summary&
public bool IsForBid { get { return this.isForB } }
bool isHolding =
public bool IsHolding { get { return this.isH } }
#endregion
[SerializeField]UIS
[SerializeField]UIS
void Awake()
this.name = this.JoystickN
root = this.GetComponent&UIWidget&();
// Update is called once per frame
void Update ()
if (isRunInEditor && Application.isEditor && !Application.isPlaying)
SetJoystickSize(radius);
if (!isForBid && isHolding)
Debug.Log(&111111&);
if (On_JoystickHolding != null)
On_JoystickHolding(this);
void Init()
bg.transform.localPosition = Vector3.
thumb.transform.localPosition = Vector3.
SetJoystickSize(radius);
Lighting(minAlpha);
#region ngui event
///// &summary&
///// test
///// &/summary&
//void OnClick ()
// Debug.Log(&mouse pos :& + Input.mousePosition + & -- touch pos :& + ScreenPos_to_NGUIPos(Input.mousePosition));
// thumb.transform.localPosition = ScreenPos_to_NGUIPos(Input.mousePosition);
void OnPress (bool isPressed)
if (isForBid)
Debug.Log(&joystick is forbid!&);
Debug.Log(&OnPress:& + isPressed.ToString());
if(isPressed)
Lighting(1f);
CalculateJoystickAxis();
if (On_JoystickMoveStart != null)
On_JoystickMoveStart(this);
isHolding =
CalculateJoystickAxis();
if (On_JoystickMoveStart != null)
On_JoystickMoveStart(this);
thumb.transform.localPosition = Vector3.
FadeOut(1f, minAlpha);
isHolding =
//void OnDragStart ()
// if (isForBid)
Debug.Log(&joystick is forbid!&);
// Debug.Log(&OnDragStart&);
// Lighting(1f);
// CalculateJoystickAxis();
// if(On_JoystickMoveStart!=null)
On_JoystickMoveStart(this);
// isHolding =
// Debug.Log(string.Format(&time:{0} - axis:{1}&, Time.time, joystickAxis));
void OnDrag(Vector2 delta)
if (isForBid)
//Debug.Log(&OnDrag:&+delta.ToString());
CalculateJoystickAxis();
if (On_JoystickMoveStart != null)
On_JoystickMoveStart(this);
//void OnDragEnd ()
// if (isForBid)
// Debug.Log(&OnDragEnd&);
// CalculateJoystickAxis();
// if (On_JoystickMoveStart != null)
On_JoystickMoveStart(this);
// thumb.transform.localPosition = Vector3.
// FadeOut(1f, minAlpha);
// isHolding =
#endregion
#region utile
/// &summary&
/// 计算JoystickAxis
/// &/summary&
/// &returns&&/returns&
void CalculateJoystickAxis()
Vector3 offset = ScreenPos_to_NGUIPos(UICamera.currentTouch.pos);
offset -= transform.localP
if (isLimitInCircle)
if (offset.magnitude & radius)
offset = offset.normalized *
thumb.transform.localPosition =
lastJoystickAxis = joystickA
joystickAxis = new Vector2(offset.x / radius, offset.y / radius);
/// &summary&
/// Axis2s the angle.
/// &/summary&
/// &returns&
/// The angle.
/// &/returns&
public float Axis2Angle(bool inDegree = true)
float angle = Mathf.Atan2(joystickAxis.x, joystickAxis.y);
if (inDegree)
return angle * Mathf.Rad2D
/// &summary&
/// Axis2s the angle.
/// &/summary&
/// &returns&
/// The angle.
/// &/returns&
public float Axis2Angle(Vector2 axis, bool inDegree = true)
float angle = Mathf.Atan2(axis.x, axis.y);
if (inDegree)
return angle * Mathf.Rad2D
/// &summary&
/// 屏幕坐标--&ui坐标
/// &/summary&
/// ¶m name=&screenPos&&&/param&
/// &returns&&/returns&
Vector3 ScreenPos_to_NGUIPos(Vector3 screenPos)
Vector3 uiPos = UICamera.currentCamera.ScreenToWorldPoint(screenPos);
uiPos = UICamera.currentCamera.transform.InverseTransformPoint(uiPos);
return uiP
/// &summary&
/// 屏幕坐标--&ngui坐标
/// &/summary&
/// ¶m name=&screenPos&&&/param&
/// &returns&&/returns&
Vector3 ScreenPos_to_NGUIPos(Vector2 screenPos)
return ScreenPos_to_NGUIPos(new Vector3(screenPos.x, screenPos.y, 0f));
/// &summary&
/// 设置摇杆的大小
/// &/summary&
/// ¶m name=&radius&&&/param&
void SetJoystickSize(int radius)
root.width = 2 *
root.height = 2 *
thumb.width = (int)(40f / 100f * root.width);
thumb.height = (int)(40f / 100f * root.height);
/// &summary&
/// 点亮摇杆
/// &/summary&
void Lighting(float alpha)
iTween.Stop(this.gameObject, &value&);
root.alpha =
/// &summary&
/// 渐变摇杆的透明度
/// &/summary&
void FadeOut(float fromAlpha, float toAlpha)
Hashtable itweenArgs = new Hashtable();
itweenArgs.Add(&easetype&, iTween.EaseType.linear);
itweenArgs.Add(&from&, fromAlpha);
itweenArgs.Add(&to&, toAlpha);
itweenArgs.Add(&time&, 0.5f);
itweenArgs.Add(&onupdate&, &OnFadeOutTween&);
iTween.ValueTo(this.gameObject, itweenArgs);
void OnFadeOutTween(float value)
root.alpha =
#endregion
#region 激活、禁用的控制
List&string& keys = new List&string&();
/// &summary&
/// &/summary&
/// &returns&返回值是,取消这个禁用要用到的key&/returns&
public string ForbidJosystick()
string key = System.Guid.NewGuid().ToString();
keys.Add(key);
isForBid =
/// &summary&
/// &/summary&
/// ¶m name=&key&&&/param&
public void ActivizeJosystick(string key)
if(keys.Contains(key))
keys.Remove(key);
isForBid =
if(keys.Count==0)
isForBid =
#endregion
3、demo包,有兴趣的,也可以看看。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致4148人阅读
特此声明!对不起各位读者了,这是小生刚接触NGUI的做法,这些日子来才想起还写过了这篇博客,现在看来这篇博客的做法实在是SB,各位看到标题的读者也就不必看下去了,估计也没有时间去更新了,抱歉
首先呢,先声明一下哈,这个脚本从头到尾都是我自己设计和编写的哈,再加上今年就大四啦,所以要也开始镀一点金啦,所以呢,各位朋友也帮一下忙哈,能赞一个就赞一个哈,多多交流,共同进步哈,而且在您转载、修改、优化、使用的话,如果这几行字没碍着您的眼的话,留着也行哈。在代码中就是这几行哈。
* note 此代码原创为谭俊孟编写 note
* note 如果对此代码有什么好的意见或者建议 note
* note 请联系QQ: note
* note 或者发邮箱: note
* note 大家共同交流和进步 note
* note 现由XXX转载修改,优化并使用 note
因为我也刚接触Unity不久,自适应效果的框架还没来得急写,所以下面说一下这段代码需要的前期准备哈,不然数值不对就很容易出异常哈:
(1)NGUI的最基本操作要会哈,我也就刚刚学NGUI了几小时,也只是会创建一下控件而已哈,要用也得查查API哈。
(2)建一个摇杆移动范围的贴图(Texture),像这样那个半透明的圆形区域,,当然弄也行,这个就是好看一些哈,如果弄的话步骤是:准备一张你自己觉得好看的贴图,然后直接用NGUI建个Texture就行了,如果你的图片显示不是图片原有的效果,那可以尝试选择一下着色器(shader)的模式。
(3)准备你觉得合适的图片,然后用它创建一个图文集(Atlas);如果不会的话,那我就不教你啦,如果这个自己百度了还不会,那还是转行快点哈;话多了,不好意思。然后用这个图文集创建一个Button。
(4)这个需要修改的几个地方,1、这些Button自带代码的属性,JoyControl.cs就是我编写的代码,等会再细说哈。2、Button的碰撞器要改,把Box
Collider修改成这个。3、Button的Background的Scale设置一下,。
(5)代码的话应该有没有什么吧,我写了很多注释哈,如果实在看不懂,你们再留言,然后我再说哈。
using UnityE
using System.C
* note 此代码原创为谭俊孟编写 note
* note 如果对此代码有什么好的意见或者建议 note
* note 请联系QQ: note
* note 或者发邮箱: note
* note 大家共同交流和进步 note
* note 现由XXX转载修改,优化并使用 note
public class JoyControl : MonoBehaviour
public GameObject playerT
private float joyInitX;
//note 摇杆的圆心初始坐标X note
private float joyInitY;
//note 摇杆的圆心初始坐标Y note
private float joyMoveD //note 摇杆最大可移动的距离 note
private float currentD //note 单签摇杆圆心离初始圆心的距离 note
private float joyControlD //note 摇杆开始控制坦克移动的最小距离 note
private float mousePositionX; //note 鼠标相对NGUI坐标系的坐标X note
private float mousePositionY; //note 鼠标相对NGUI坐标系的坐标X note
private float parallelMoveLeftX; //note 摇杆控制坦克平行移动左边界X note
private float parallelMoveRightX; //note 摇杆控制坦克平行移动右边界X note
private float parallelMoveLeftY; //note 摇杆控制坦克平行移动左边界Y note
private float parallelMoveRightY; //note 摇杆控制坦克平行移动右边界X note
private bool isTankM
//note 摇杆是否能控制坦克移动 note
void Start ()
joyInitX = this.transform.localPosition.x;
joyInitY = this.transform.localPosition.y;
joyMoveDistance = 22.5f;
joyControlDistance = 5.0f;
mousePositionX = this.transform.localPosition.x;
mousePositionY = this.transform.localPosition.y;
parallelMoveLeftX = this.transform.localPosition.x - 5.0f;
parallelMoveRightX = this.transform.localPosition.x + 5.0f;
parallelMoveLeftY = this.transform.localPosition.y + 5.0f;
parallelMoveRightY = this.transform.localPosition.y - 5.0f;
void Update()
if(isTankMove)
//note 判断坦克是否在前后平行活动距离内 note
if(this.transform.localPosition.x & parallelMoveLeftX && this.transform.localPosition.x & parallelMoveRightX)
// note 坦克移动 note
if(this.transform.localPosition.y & joyInitY)
playerTank.transform.Translate(Vector3.forward * Time.deltaTime * getAbs(this.transform.localPosition.y, joyInitY) * playerTank.GetComponent&Tank&().tankMoveSpeed);
playerTank.transform.Translate(Vector3.back * Time.deltaTime * getAbs(this.transform.localPosition.y, joyInitY) * playerTank.GetComponent&Tank&().tankMoveSpeed);
else if(this.transform.localPosition.y & parallelMoveLeftY && this.transform.localPosition.y & parallelMoveRightY)
//note 横向拖动摇杆不做任何操作 note
//note 坦克移动和旋转 note
if(this.transform.localPosition.y & joyInitY)
playerTank.transform.Translate(Vector3.forward * Time.deltaTime * getAbs(this.transform.localPosition.y, joyInitY) * playerTank.GetComponent&Tank&().tankMoveSpeed);
if(this.transform.localPosition.x & joyInitX)
playerTank.transform.Rotate(Vector3.down * Time.deltaTime * getAbs(this.transform.localPosition.x, joyInitX) * playerTank.GetComponent&Tank&().tankRotateSpeed);
playerTank.transform.Rotate(Vector3.up * Time.deltaTime * getAbs(this.transform.localPosition.x, joyInitX) * playerTank.GetComponent&Tank&().tankRotateSpeed);
playerTank.transform.Translate(Vector3.back * Time.deltaTime * getAbs(this.transform.localPosition.y, joyInitY) * playerTank.GetComponent&Tank&().tankMoveSpeed);
if(this.transform.localPosition.x & joyInitX)
playerTank.transform.Rotate(Vector3.up * Time.deltaTime * getAbs(this.transform.localPosition.x, joyInitX) * playerTank.GetComponent&Tank&().tankRotateSpeed);
playerTank.transform.Rotate(Vector3.down * Time.deltaTime * getAbs(this.transform.localPosition.x, joyInitX) * playerTank.GetComponent&Tank&().tankRotateSpeed);
void OnDrag (Vector2 delta)
if(GameObject.Find(&Main Camera&).GetComponent&MyCamera&().cameraState == 1)
//note 摇杆随鼠标移动 note
mousePositionX = Input.mousePosition.x - (float)Screen.width / 2;
mousePositionY = Input.mousePosition.y - (float)Screen.height / 2;
this.transform.localPosition = new Vector3(mousePositionX, mousePositionY, 0);
// note 获得单签摇杆圆心离初始圆心的距离 note
currentDistance = Mathf.Sqrt(getAbs(this.transform.localPosition.x, joyInitX) * getAbs(this.transform.localPosition.x, joyInitX)
+ getAbs(this.transform.localPosition.y, joyInitY) * getAbs(this.transform.localPosition.y, joyInitY));
//note 判断摇杆移动距离是否超过最大距离,超过则设为最边沿的点 note
if(currentDistance & joyControlDistance)
isTankMove =
else if(currentDistance & joyMoveDistance)
setJoyMoveMaxPosition();
isTankMove =
isTankMove =
else if(GameObject.Find(&Main Camera&).GetComponent&MyCamera&().cameraState == 2)
* note 计算两个值的绝对值之差的绝对值 note
float getAbs(float a, float b)
return Mathf.Abs(Mathf.Abs(a)-Mathf.Abs(b));
* note 求摇杆可移动最大边界点的坐标 note
void setJoyMoveMaxPosition()
* note 移动鼠标控制摇杆超过规定距离,则摇杆保持以摇杆为圆心的当前两点的原斜率,长度为最大长度 note
* note 其中x,y为(joyInitX, joyInitY),而(x1,y1)为当前摇杆坐标,R为和joyMoveDistance note
* note (x2, y2)为最后要求的结果坐标,并且赋给当前的摇杆 note
* ntoe 算法: note
* note 由直线公式:y = kx + 推出k 和 b note
* note k = (y1 - y) / (x1 - x);
b = y - k * note
* note 再由园的公式(x2 - x)^2 + (y2 - y)^2 = R^2; note
* note 进行带入运算得出关于x2的一元二次方程: (x2 - x)^2 + (k * x2 + b - y)^2 = R^2; note
* note 整理后得出:(1 + k^2) * x2^2 + 2 * (k*b - k*y - x)x2 + x^2 + b^2 + y^2 - 2*b*y - R^2 = 0; note
* note 再根据求根公式:x=[-b±√(b^2-4ac)]/2a 和 当前摇杆坐标X与初始坐标X的比较可得出x2的值,继而得出相应的y2 note
//note 直线的参数 note
float a1, b1, c1;
//note 一元二次方程的参数 note
float tempX1,tempX2; //note 最后得出的两个X坐标 note
k = (this.transform.localPosition.y - joyInitY) / (this.transform.localPosition.x - joyInitX);
b = joyInitY - k * joyInitX;
a1 = 1 + k*k;
b1 = 2 * (k*b -k*joyInitY - joyInitX);
c1 = joyInitX*joyInitX + b*b + joyInitY*joyInitY - 2*b*joyInitY - joyMoveDistance*joyMoveD
tempX1 = (-b1 + Mathf.Sqrt(b1*b1 - 4*a1*c1)) / (2 * a1);
tempX2 = (-b1 - Mathf.Sqrt(b1*b1 - 4*a1*c1)) / (2 * a1);
if(this.transform.localPosition.x & joyInitX)
if(tempX1 & joyInitX)
this.transform.localPosition = new Vector3 (tempX1, k*tempX1 + b, 0);
this.transform.localPosition = new Vector3 (tempX2, k*tempX2 + b, 0);
if(tempX1 & joyInitX)
this.transform.localPosition = new Vector3 (tempX1, k*tempX1 + b, 0);
this.transform.localPosition = new Vector3 (tempX2, k*tempX2 + b, 0);
最后呢,总结一下吧,因为接触Unity时间不长,更加不说NGUI了,所以自适应效果没有做,还有一些异常处理液没有做,如果代码里面的某些东西给大家带来误导,那我先抱歉一下哈,哦,对了,最重要的,因为爪机太过落后,没能上真机调试,真能用电脑来调,所以就不是Touch时间了,而是mouse事件,不过应该改一下就行了,思想都是一样的哈,有什么好的意见或者建议请留言或者QQ或者邮箱联系哈。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:11127次
排名:千里之外
(1)(2)(1)(3)114网址导航&&&&NGUI 虚拟摇杆
NGUI 虚拟摇杆
NGUI虚拟摇杆 避免了EasyTouch存在的问题 需要的下载看看了
若举报审核通过,可奖励20下载分
被举报人:
举报的资源分:
请选择类型
资源无法下载
资源无法使用
标题与实际内容不符
含有危害国家安全内容
含有反动***等内容
含广告内容
版权问题,侵犯个人或公司的版权
*详细原因:
VIP下载&&免积分60元/年(1200次)
您可能还需要
移动开发下载排行程序写累了,就来玩玩酷跑小游戏吧,嘿嘿。
雨松MOMO送你一首歌曲,嘿嘿。
NGUI研究院之与EasyTouch结合使用(十五)
NGUI研究院之与EasyTouch结合使用(十五)
围观29843次
编辑日期: 字体:
用了EasyTouch插件一段时间了,小问题还是有一些,总体来说用起来还行。这篇文章我就来说说EasyTouch和NGUI的结合。
总体来说触摸屏幕也就三种情况。
1.触摸事件只响应NGUI部分,不响应3D部分。
2.触摸事件只响应3D部分,不响应NGUI部分。
3.触摸事件同时响应。
举个例子,在战斗场景我们希望通过手指滑动来控制摄像机的旋转。但是这时屏幕上可能还有一些UI的按钮,但是我们不希望用户点击UI按钮也影响到了摄像机的旋转。所以此时我们只希望触摸事件在3D部分响应。
1. 如下图所示,这里我增加了一个UISprite,我希望我的手指触摸事件只在UI上响应,不在3D上响应
1234567891011121314151617181920212223242526272829303132333435363738394041
using UnityEngine;using System.Collections;&public class UImomo : MonoBehaviour { //头像 GameObject icon; void Start ()
icon = transform.Find("icon").gameObject;
//添加一个手指滑动的事件。
EasyTouch.On_SwipeEnd += EasyTouch_On_SwipeEnd; }& void OnDestroy() {
//施放一个手指滑动的事件。
EasyTouch.On_SwipeEnd -= EasyTouch_On_SwipeEnd; }& //当手指滑动结束时在这里 void EasyTouch_On_SwipeEnd(Gesture gesture) {
//判断手指是否触摸在NGUI的头像中
if(gesture.IsStartInRect(NGUIObjectToRect(icon)))
//输出手指滑动的方向
Debug.Log(gesture.swipe);
} }& //计算出NGUI某个UISprite或者UITexture或者 UILabel 在屏幕中占的矩形位置。 private&&Rect NGUIObjectToRect(GameObject go) {
Camera camera = NGUITools.FindCameraForLayer(go.layer);
Bounds bounds = NGUIMath.CalculateAbsoluteWidgetBounds(go.transform);
Vector3 min = camera.WorldToScreenPoint(bounds.min);
Vector3 max = camera.WorldToScreenPoint(bounds.max);
return new Rect(min.x, min.y, max.x - min.x, max.y - min.y); }&}
2.我希望手指触摸只响应3D,不响应NGUI 。这里其实更多的运用于游戏的战斗界面,战斗界面的UI一般都集中在屏幕的四个角, 比如头像 小地图 技能 摇杆等等。EasyTouch提供了NGUI模式,可以很方便的解决这个问题,不过它原理也是用射线来判断,所以你要确保需要略过的UI空间有BoxCollider组件。
我们把所有NGUI做的界面放在UI层上面。代码简单的改改,这样EasyTouch就不会在UI层上响应了。
//添加一个手指滑动的事件。
EasyTouch.On_SwipeEnd += EasyTouch_On_SwipeEnd;
//得到UI摄像机
Camera uiCamera = GameObject.Find("UI Root/Camera").GetComponent&Camera&();
if(uiCamera != null)
//启动NGUI模式
EasyTouch.instance.enabledNGuiMode = true;
//把NGUI摄像机加入过滤队列
if(!EasyTouch.instance.nGUICameras.Contains(uiCamera))
EasyTouch.instance.nGUICameras.Add(uiCamera);
//设置需要过滤的UI层
EasyTouch.instance.nGUILayers = (1 && LayerMask.NameToLayer("UI"));
} }& void OnDestroy() {
//施放一个手指滑动的事件。
EasyTouch.On_SwipeEnd -= EasyTouch_On_SwipeEnd;
EasyTouch.instance.enabledNGuiMode = false;
EasyTouch.instance.nGUILayers =0;
EasyTouch.instance.nGUICameras.Clear(); }
最后,我现在用的EasyTouch可能版本比较老,我用的版本是v3.1.1 因为目前项目也比较稳定,所以也不敢升级。EasyTouch这个版本里有一个BUG。就是超过10只手指在屏幕中滑动会出现空指针的错误,后来我看了一下代码,在UpdateTouches 里面做一下判断就好了。
EasyTouch有很强大的事件回调方法,大家可以去它的官网上查一下。不知道现在还有没有更好用的触屏插件,如果你觉得比EasyTouch还好用的话,希望你在下面给我留言,谢谢。
本文固定链接:
转载请注明:
雨松MOMO提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。
您可能还会对这些文章感兴趣!

参考资料

 

随机推荐