http://www.winig.cc/archives/348

好久没有写文章了,最近在做项目是用的unity最新的ui系统UGUI,项目需要做一个摇杆,网上大部分都是用的插件和NGUI做的摇杆,unity自带的摇杆也不怎么好用,而最新的unity4.6.x来了,加入了最新的UI系统“UGUI”,那我们怎么用UGUI来制作摇杆呢~大神勿喷,本人是技术渣渣。

比较出色的摇杆插件《Easy Touch》(很强大)

还是主要讲讲我们自己怎么做。

  1. 首先在unity场景里面新建一个空物体和两个Image,把空物体放在创建Image自动生成的Canvas里面,再把两个Image放在空物体里

    Image建立方式:GameObject->UI->Image   或者直接在“Hierarchy”右键然后UI->Image,看喜好。

    空物体和两个Image的命名看个人喜好。

    威恩的节点是这样的:

    节点中的joystack是刚刚建立的空节点。

    Backgound是摇杆的背景。

    JoystackControl是真实的可以拖动的摇杆。

  2. 把Backgound和JoystackControl的SourceImage替换成自己喜欢的图片,并且把JoystackControl的图片缩小点,这里我就用系统自带的图片了,威恩这两个节点的inspector如下(我修改过得地方用红框标注了,其他都没改):

    最终样子如下:

  3. 那么样子有了就需要让他动起来,需要三个类“EventTriggerListener”、“JoystackCc”、“PlayerMoveControl”。

    EventTriggerListener:在NGUI开发的时候处理事件都会用到UIEventListener,我们已经用的习惯的不得了,而UGUI则不是这种机制,

    并且我觉得这种是最合理的方式,所以自己写一套类似的。

    只是一个帮助类,不需要挂在任何的游戏对象上。

    JoystackCc:这是主要来控制摇杆的。

    挂在JoystackControl节点上

    PlayerMoveControl:这是主要来通过摇杆来控制角色的。

    挂在你想控制的物体上

    直接上代码,写了注释,就不哔哔了。

    EventTriggerListener.cs

  4. 
    
    using UnityEngine;
    
    using System.Collections;
    
    using UnityEngine.EventSystems;
    
    using System.Collections.Generic;
    
    /// <summary>
    
    /// UGUI事件监听类
    
    /// </summary>
    
    public class EventTriggerListener : UnityEngine.EventSystems.EventTrigger{
    
    	publicdelegate void VoidDelegate (GameObject go);
    
    	publicdelegate void VectorDelegate(GameObject go, Vector2 delta);
    
    	publicVoidDelegate onClick;
    
    	publicVoidDelegate onDown;
    
    	publicVoidDelegate onEnter;
    
    	publicVoidDelegate onExit;
    
    	publicVoidDelegate onUp;
    
    	publicVoidDelegate onSelect;
    
    	publicVoidDelegate onUpdateSelect;
    
    	publicVectorDelegate onDrag;
    
    	publicVoidDelegate onDragOut;
    
    	staticpublic EventTriggerListener Get (GameObject go)
    
    	{
    
    		if(go==null){
    
    			Debug.LogError("EventTriggerListener_go_is_NULL");
    
    			return null;
    
    		}
    
    		else{
    
    			EventTriggerListener listener = go.GetComponent<EventTriggerListener>();
    
    			if (listener == null) listener = go.AddComponent<EventTriggerListener>();
    
    			return listener;
    
    		}
    
    	}
    
    	publicoverride void OnDrag(PointerEventData eventData)
    
    	{
    
    		if(onDrag != null) onDrag(gameObject, eventData.delta);
    
    	}
    
    	publicoverride void OnEndDrag(PointerEventData eventData)
    
    	{
    
    		if(onDragOut != null) onDragOut(gameObject);
    
    	}
    
    	publicoverride void OnPointerClick(PointerEventData eventData)
    
    	{
    
    		if(onClick !=null)  onClick(gameObject);
    
    	}
    
    	publicoverride void OnPointerDown (PointerEventData eventData){
    
    		if(onDown !=null) onDown(gameObject);
    
    	}
    
    	publicoverride void OnPointerEnter (PointerEventData eventData){
    
    		if(onEnter !=null) onEnter(gameObject);
    
    	}
    
    	publicoverride void OnPointerExit (PointerEventData eventData){
    
    		if(onExit !=null) onExit(gameObject);
    
    	}
    
    	publicoverride void OnPointerUp (PointerEventData eventData){
    
    		if(onUp !=null) onUp(gameObject);
    
    	}
    
    	publicoverride void OnSelect (BaseEventData eventData){
    
    		if(onSelect !=null) onSelect(gameObject);
    
    	}
    
    	publicoverride void OnUpdateSelected (BaseEventData eventData){
    
    		if(onUpdateSelect !=null) onUpdateSelect(gameObject);
    
    	}
    
    } 
     
     
  5. JoystackCc.cs

  6. using UnityEngine;
    
    using System.Collections;
    
    public class JoystackCc : MonoBehaviour {
    
    	privateVector3 Origin;
    
    	Transform mTrans;
    
    	privateVector3 _deltaPos;
    
    	privatebool _drag = false;
    
    	privateVector3 deltaPosition;
    
    	floatdis;
    
    	[SerializeField]
    
    	privatefloat MoveMaxDistance = 80;            //最大拖动距离
    
    	[HideInInspector]
    
    	publicVector3 FiexdMovePosiNorm; //固定8个角度移动的距离
    
    	[HideInInspector]
    
    	publicVector3 MovePosiNorm;  //标准化移动的距离
    
    	[SerializeField]
    
    	privatefloat ActiveMoveDistance = 1;              //激活移动的最低距离
    
    	voidAwake()
    
    	{
    
    		EventTriggerListener.Get(gameObject).onDrag = OnDrag;
    
    		EventTriggerListener.Get(gameObject).onDragOut = OnDragOut;
    
    		EventTriggerListener.Get(gameObject).onDown = OnMoveStart;
    
    	}
    
    	// Use this for initialization
    
    	voidStart () {
    
    		Origin = transform.localPosition;//设置原点
    
    		mTrans = transform;
    
    	}
    
    	// Update is called once per frame
    
    	voidUpdate()
    
    	{
    
    		dis = Vector3.Distance(transform.localPosition, Origin);//拖动距离,这不是最大的拖动距离,是根据触摸位置算出来的
    
    		if(dis >= MoveMaxDistance)       //如果大于可拖动的最大距离
    
    		{
    
    			Vector3 vec = Origin + (transform.localPosition - Origin) * MoveMaxDistance / dis;  //求圆上的一点:(目标点-原点) * 半径/原点到目标点的距离
    
    			transform.localPosition = vec;
    
    		}
    
    		if(Vector3.Distance(transform.localPosition, Origin) > ActiveMoveDistance) //距离大于激活移动的距离
    
    		{
    
    			MovePosiNorm = (transform.localPosition - Origin).normalized;
    
    			MovePosiNorm = new Vector3(MovePosiNorm.x, 0, MovePosiNorm.y);
    
    		}
    
    		else
    
    			MovePosiNorm = Vector3.zero;
    
    	}
    
    	voidMiouseDown()
    
    	{
    
    		if((Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved))
    
    		{
    
    		}
    
    		else
    
    			mTrans.localPosition = Origin;
    
    	}
    
    	Vector3 result;
    
    	privateVector3 _checkPosition(Vector3 movePos, Vector3 _offsetPos)
    
    	{
    
    		result = movePos + _offsetPos;
    
    		returnresult;
    
    	}
    
    	voidOnDrag(GameObject go, Vector2 delta)
    
    	{
    
    		if(!_drag)
    
    		{
    
    			_drag = true;
    
    		}
    
    		_deltaPos = delta;
    
    		mTrans.localPosition +=new Vector3(_deltaPos.x, _deltaPos.y, 0);
    
    	}
    
    	voidOnDragOut(GameObject go)
    
    	{
    
    		_drag =false;
    
    		mTrans.localPosition = Origin;
    
    		if(PlayerMoveControl.moveEnd != null) PlayerMoveControl.moveEnd();
    
    	}
    
    	voidOnMoveStart(GameObject go)
    
    	{
    
    		if(PlayerMoveControl.moveStart != null) PlayerMoveControl.moveStart();
    
    	}
    
    }
  7.  
     

    PlayerMoveControl.cs

  8. using UnityEngine;
    
    using System.Collections;
    
    public class PlayerMoveControl : MonoBehaviour {
    
    	privateTransform _mTransform;
    
    	publicJoystackCc _mJoystackCc;
    
    	publicfloat moveSpeed = 50;
    
    	publicdelegate void MoveDelegate();
    
    	publicstatic MoveDelegate moveEnd;
    
    	publicstatic MoveDelegate moveStart;
    
    	publicstatic PlayerMoveControl Instance;
    
    	// Use this for initialization
    
    	voidAwake()
    
    	{
    
    		Instance =this;
    
    		_mTransform = transform;
    
    		moveEnd = OnMoveEnd;
    
    		moveStart = OnMoveStart;
    
    	}
    
    	voidStart () {
    
    	}
    
    	voidOnMoveEnd()
    
    	{
    
    		_turnBase =false;
    
    	}
    
    	voidOnMoveStart()
    
    	{
    
    		_turnBase =true;
    
    	}
    
    	// Update is called once per frame
    
    	privatefloat angle;
    
    	privatebool _turnBase = false;
    
    	voidUpdate()
    
    	{
    
    		if(_turnBase) 
    
    		{
    
    			Vector3 vecMove = _mJoystackCc.MovePosiNorm*Time.deltaTime*moveSpeed/10;
    
    			_mTransform.localPosition+=vecMove;
    
    			angle = Mathf.Atan2 (_mJoystackCc.MovePosiNorm.x, _mJoystackCc.MovePosiNorm.z) * Mathf.Rad2Deg - 10;
    
    			_mTransform.localRotation = Quaternion.Euler(Vector3.up*angle);
    
    		}
    
    	}
    
    }
     
     

    建好这三个类之后,把他们绑定到相应的节点上。都挂在哪,代码上面有写

  9. 测试一下,威恩新建了一个cube来作为测试对象,加了个plane作为“伪”地面,太黑了再打个灯….

    下面是测试效果:

如果有任何问题直接留言~尽自己所能帮忙解决~

最新文章

  1. 给linode 替换操作系统核心
  2. 一起来花5分钟写一个PHP入门Demo
  3. Gradle构建Java项目
  4. Linux上部署Tomcat(包括JAVA环境的配置)
  5. Java如何将控制台上的结果保存到文件
  6. 《JS原型》
  7. Xamarin.Forms DataGrid
  8. (step7.2.1)hdu 1395(2^x mod n = 1——简单数论)
  9. 每个Javascript开发者都应当知道的那些事
  10. x64内核HOOK技术之拦截进程.拦截线程.拦截模块
  11. npm install 之前做的事
  12. 肺结节CT影像特征提取(三)——肺结节CT影像特征提取系统软件设计
  13. SPOJ 1812 LCS2 - Longest Common Substring II
  14. JSF action actionListner 详解
  15. Spring+SpringMVC+MyBatis的整合
  16. 读vue-0.6-utils.js源码
  17. Pandas 常见的基本方法
  18. JAVA基础知识总结:十一
  19. js之面向对象
  20. 大数据:Spark Core(二)Driver上的Task的生成、分配、调度

热门文章

  1. httpurlconnection模拟post提交form表单(普通文本和上传文件) (
  2. (转)c#(wince)中使用多线程访问winform中控件的问题
  3. SpringBoot-(6)-日志SLF4j
  4. Python多线程模块
  5. Python对象拷贝——深拷贝与浅拷贝
  6. css中IE判断语句 if !IE
  7. postNotificationName 消息传递详解
  8. html5--4-2 video元素的属性
  9. CISCO-从路由器上下载IOS
  10. TX2上yolov3精度和速度优化方向