【转】Unity3D学习日记(一)使用UGUI制作虚拟摇杆

http://blog.csdn.net/begonia__z/article/details/51170059

  如今手机游戏玩法多种多样,尤其使用虚拟摇杆进行格斗类游戏开发或者是MMORPG成为了主流的开发方式,可能不少人都会为了制作一个完善的虚拟摇杆感到烦恼,一次又不少人选择使用插件来制作虚拟摇杆。

  Momo大神在不久前才写了一篇用UGUI制作虚拟摇杆的,有兴趣的同学可以到这里看看原文,原文地址:http://www.xuanyusong.com/archives/3924

  今天刚好公司向里面需要用到这个功能,因此我也研究了一下Momo这篇文章,发现里面有一个算是bug的问题因此我就在Momo大神的代码上进行修改,修复了这个问题而且也添加一下功能方便大家去拓展和使用。

  先来看看我和我的小伙伴发现的bug吧。

  下图两张图片是Momo大神的写的UGUI虚拟摇杆的小Demo,我们来看看其效果吧:

   图片一:

   

   图片二:

   

比较一下两张图片你会发现有一个致命问题小球的偏移量出问题了,这种情况只出现在虚拟摇杆距离屏幕边距较近的时候会出现这个问题,远离边距的时候就不会出现这个问题了,来看看远离边距时候的效果吧。如下图所示:

这样的限制对于摇杆功能来说并不会有太大的影响,但是UI的设计上还是会出现一些问题和麻烦的。因此我今天就是为了修复这个问题而对UGUI虚拟摇杆进行了研究,花了一点时间进行了bug的修复,然后拓写了它的功能,方便我们来获取摇杆的偏移量来控制人物移动。

  先来看看我实现的效果吧,废话不多说上图!

  

  上面的图片可以看出来,虚拟摇杆已经贴着屏幕边框了,但是偏移量并没有减少。

  我也不说多少神马了因为实在是太简单了,我就直接上代码吧

[csharp] view plain copy
 
  1. using UnityEngine;  
  2. using System.Collections;  
  3. using UnityEngine.EventSystems;  
  4. using UnityEngine.UI;  
  5.    
  6. public class ScrollCircle :ScrollRect   
  7. {  
  8.     public float recoveryTime = 0.1f;  
  9.     protected float mRadius;  
  10.     protected bool isOnEndDrag = false;  
  11.     protected Vector3 offsetVector3 = Vector3.zero;  
  12.   
  13.     void Start()  
  14.     {  
  15.         inertia = false;  
  16.         movementType = MovementType.Unrestricted;  
  17.         //计算摇杆块的半径  
  18.         mRadius = (transform as RectTransform).sizeDelta.x * 0.5f;  
  19.     }  
  20.   
  21.     public override void OnScroll(PointerEventData data)  
  22.     {  
  23.   
  24.     }  
  25.     public override void OnDrag (PointerEventData eventData)  
  26.     {  
  27.         base.OnDrag (eventData);  
  28.         isOnEndDrag = false;  
  29.         var contentPostion = this.content.anchoredPosition;  
  30.         if (contentPostion.magnitude > mRadius){  
  31.             contentPostion = contentPostion.normalized * mRadius ;  
  32.             SetContentAnchoredPosition(contentPostion);  
  33.         }  
  34.     }  
  35.   
  36.     public override void OnEndDrag(PointerEventData eventData)  
  37.     {  
  38.         base.OnEndDrag(eventData);  
  39.         if (!isOnEndDrag)  
  40.             isOnEndDrag = true;  
  41.     }  
  42.   
  43.     void Update()  
  44.     {  
  45.         UpdateContent();  
  46.     }  
  47.   
  48.     /// <summary>  
  49.     /// 摇杆小球复位  
  50.     /// </summary>  
  51.     public void UpdateContent()  
  52.     {  
  53.         if (isOnEndDrag)  
  54.         {  
  55.             if (content.localPosition == Vector3.zero)  
  56.                 isOnEndDrag = false;  
  57.             float x = Mathf.Lerp(content.localPosition.x, 0.0f, recoveryTime);  
  58.             float y = Mathf.Lerp(content.localPosition.y, 0.0f, recoveryTime);  
  59.             content.localPosition = new Vector3(x, y, content.localPosition.z);  
  60.         }  
  61.         CalculateOffset();  
  62.     }  
  63.     /// <summary>  
  64.     /// 计算偏移量  
  65.     /// </summary>  
  66.     private void CalculateOffset()  
  67.     {  
  68.         offsetVector3 = content.localPosition / mRadius;  
  69.     }  
  70.     /// <summary>  
  71.     /// 获取偏移量大小  
  72.     /// 偏移量范围是[-1,1]  
  73.     /// </summary>  
  74.     /// <returns></returns>  
  75.     public Vector3 GetOffsetVector3()  
  76.     {  
  77.         return offsetVector3;  
  78.     }  
  79. }  

这里要注意一点,我在start函数里面修改了movementType,如果没有修改movementType参数的同学是没办法实现这个功能的~切记切记!!

最后上一张图片,红框的位置是要特别注意的地方!

今天写了两篇文章好累啊,我会尽量把自己学到研究到的东西都写出来,可能会很乱很杂大家别介意哈....哈哈哈哈~~

posted on 2017-03-10 21:54  mimime  阅读(359)  评论(0编辑  收藏  举报