经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 游戏设计 » 查看文章
Unity基于NGUI的简单并可直接使用的虚拟摇杆实现(一)
来源:cnblogs  作者:落叶0  时间:2019/8/5 9:38:48  对本文有异议

可能大家都听说过大名鼎鼎的easytouch,然而easytouch是基于UGUI的,两种不同的UI混用,可能会造成项目管理的混乱,并且可能会出现各种幺蛾子,比如事件传递互相扰乱的问题。

于是就想找一种基于NGUI的摇杆,搜索网上的文章,都有很多问题,总结来说三个问题很突出。

一:代码本事存在缺陷或者BUG,或者想得太简单,比如没有考虑手指相对按钮的偏移,造成实际并不实用,只能用来学习。

二:号称是NGUI的摇杆,但是有些实现却用了UGUI的东西。

三:未考虑通用性,参数都是固定值,什么43啊73啊,都不知道这些值怎么来的。

于是自己写吧,NGUI怎么用就不教了。

①首先,创建两个Sprite(我这里偷懒用了2DSprite,因为不用打包图片)和一个Texture。

 

NGuiJoystick是摇杆的底盘,Thumb是摇杆的按钮,NGuiJoystickArea用于Dynamic模式的显示区域。

Dynamic模式:类似于EasyTouch插件的Dynamic模式,平时不显示摇杆,手指按下在手指处显示摇杆,放开手指摇杆消失。

注意:三个UI对象名字随意,但是层级关系不能错。

②修改NGuiJoystick和Thumb的纹理图片并调整到你想要的合适大小(这里最好长宽相等,因为不等我没有试过行不行),给NGuiJoystick和Thumb都Attack上Collider。设置NGuiJoystick的depth为100,Thumb的depth为101(尽可能处于最上层,当然也可根据需求来改)。

③修改NGuiJoystickArea的大小(根据Dynamic模式下你想显示的区域,我这里铺满了全屏),Attack上Collider,修改NGuiJoystickArea的纹理(我这里用了一张白色方向纹理),设置NGuiJoystickArea的color hint的值为(255,,255,255,50),修改depth为1(如果UIRoot和UICamera都是默认值0的话)。

④接下来就是代码部分。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5. public class JoyStickControl : MonoBehaviour
  6. {
  7. public enum ShowType{Static,Dynamic}; //显示模式
  8. public ShowType showType= ShowType.Static;
  9. public float radiusOffset = 0.0F; //半径偏移值、用于图片问题造成的偏差进行微调
  10. public GameObject area = null; //Dynamic模式下的显示区域
  11. private float radius; //底盘半径
  12. private float ratio=1.0F; //缩放值
  13. private bool isPress = false; //是否是按下状态
  14. private bool isFirstPress = false; //是否第一次按下
  15. private Vector2 offset; //手指相对于按钮的偏移值
  16.  
  17. private void Awake()
  18. {
  19. //获取底盘半径
  20. UI2DSprite parentSpirite = transform.parent.GetComponent<UI2DSprite>();
  21. float parentWidth = parentSpirite.width;
  22. radius = parentWidth / 2.0F+ radiusOffset;
  23.  
  24. //获取缩放值
  25. UIRoot root = GameObject.FindObjectOfType<UIRoot>();
  26. if (root != null)
  27. {
  28. // 实际尺寸和设计尺寸比例
  29. ratio = (float)root.activeHeight / Screen.height;
  30. }
  31.  
  32. //如果是Dynamic模式、一开始隐藏摇杆、并将Area设置到近乎透明
  33. if (showType == ShowType.Dynamic)
  34. {
  35. transform.parent.gameObject.SetActive(false);
  36. if (area != null)
  37. {
  38. UITexture areaTexture = area.GetComponent<UITexture>();
  39. areaTexture.color = new Color(1.0F, 1.0F, 1.0F, 1.0F/255.0F);
  40. }
  41. }
  42. else
  43. {
  44. if (area != null)
  45. {
  46. area.SetActive(false);
  47. }
  48. }
  49. }
  50.  
  51. // Update is called once per frame
  52. private void Update()
  53. {
  54. // 触摸按下
  55. if (isPress)
  56. {
  57. //最后一次触摸位置、基于屏幕坐标
  58. Vector2 touchpos = UICamera.lastEventPosition;
  59. //获取摇杆按钮的屏幕坐标
  60. Vector2 childCenterPos = UICamera.currentCamera.WorldToScreenPoint(transform.position);
  61. //第一次触摸的时候获取手指相对于按钮的偏移值
  62. if (!isFirstPress)
  63. {
  64. offset = touchpos - childCenterPos;
  65. isFirstPress = true;
  66. }
  67. //获取摇杆底盘的屏幕坐标
  68. Vector2 centerPos = UICamera.currentCamera.WorldToScreenPoint(transform.parent.position);
  69.  
  70. //获取touchpos - offset和centerPos之间的距离值
  71. //凡是用到touchpos - offset的地方绝对不能用childCenterPos替代、可以考虑下为什么
  72. float distance = Vector2.Distance(touchpos - offset, centerPos);
  73.  
  74. //如果距离小于半径,则将按钮位置移动到touchpos - offset位置
  75. //distance算到的相对距离,需要乘以缩放值
  76. if (distance * ratio < radius)// 距离在父精灵背景中圆内,radius为其半径
  77. {
  78. Vector3 worldTouchPos = UICamera.currentCamera.ScreenToWorldPoint(touchpos - offset);
  79. transform.position = worldTouchPos;
  80. }
  81. //距离超过半径、则把按钮的位置设置在底盘的圆上
  82. else
  83. {
  84. transform.localPosition = (touchpos - offset - centerPos).normalized * radius;
  85. childCenterPos = UICamera.currentCamera.WorldToScreenPoint(transform.position);
  86. }
  87.  
  88. }
  89. // 触摸抬起、那么把按钮位置恢复到原点、 将isFirstPress置否,如果是Dynamic模式、还要隐藏摇杆
  90. else
  91. {
  92. if (showType == ShowType.Dynamic)
  93. {
  94. transform.parent.gameObject.SetActive(false);
  95. }
  96. transform.localPosition = Vector2.zero;
  97. isFirstPress = false;
  98. }
  99. }
  100.  
  101. // 触摸按下、isPress为true、抬起为false
  102. public void OnPress(bool isPress)
  103. {
  104. this.isPress = isPress;
  105. }
  106.  
  107. //用于Dynamic模式press事件的响应
  108. public void startTouch()
  109. {
  110. if (showType == ShowType.Dynamic)
  111. {
  112. transform.parent.gameObject.SetActive(true);
  113. Vector2 startTouchPos = UICamera.lastEventPosition;
  114. Vector2 startTouchWorldPos = UICamera.currentCamera.ScreenToWorldPoint(startTouchPos);
  115. transform.parent.position = startTouchWorldPos;
  116. this.isPress = true;
  117. }
  118. }
  119.  
  120. //用于Dynamic模式release事件的响应
  121. public void endTouch()
  122. {
  123. if (showType == ShowType.Dynamic)
  124. {
  125. transform.parent.gameObject.SetActive(false);
  126. }
  127. transform.localPosition = Vector2.zero;
  128. isFirstPress = false;
  129. }
  130. }

⑤把脚本拖到thumb对象上,并且把NGuiJoystickArea拖到脚本的public成员上。

 

⑥增加一个事件触发器,NGuiJoystickArea->Add Component->NGUI->Interaction->Event Trigger。

⑦将Thumb拖到触发器press事件上,并设置响应函数为startTouch();将Thumb拖到触发器release事件上,并设置响应函数为endTouch()。

 

【预览】

 

过几天再上传和人物的关联文章,实现EasyTouch的allow turn and move,已经DeadValue等一些配置参数。

【本文为原创文章,CSDN博客发布作者和博客园作者为同一作者,特此说明】

原文链接:http://www.cnblogs.com/lionlion/p/11297108.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号