Unity3D 虚拟摇杆 NGUI实现方法

特此声明!对不起各位读者了,这是小生刚接触NGUI的做法,这些日子来才想起还写过了这篇博客,现在看来这篇博客的做法实在是SB,各位看到标题的读者也就不必看下去了,估计也没有时间去更新了,抱歉


首先呢,先声明一下哈,这个脚本从头到尾都是我自己设计和编写的哈,再加上今年就大四啦,所以要也开始镀一点金啦,所以呢,各位朋友也帮一下忙哈,能赞一个就赞一个哈,多多交流,共同进步哈,而且在您转载、修改、优化、使用的话,如果这几行字没碍着您的眼的话,留着也行哈。在代码中就是这几行哈。

/**
 * note 此代码原创为谭俊孟编写 note
 * note 如果对此代码有什么好的意见或者建议 note
 * note 请联系QQ:408333990 note
 * note 或者发邮箱:[email protected] note
 * note 大家共同交流和进步 note
 * note 现由XXX转载修改,优化并使用 note
 */

因为我也刚接触Unity不久,自适应效果的框架还没来得急写,所以下面说一下这段代码需要的前期准备哈,不然数值不对就很容易出异常哈:

(1)NGUI的最基本操作要会哈,我也就刚刚学NGUI了几小时,也只是会创建一下控件而已哈,要用也得查查API哈。

(2)建一个摇杆移动范围的贴图(Texture),像这样那个半透明的圆形区域,Unity3D 虚拟摇杆 NGUI实现方法_第1张图片,当然弄也行,这个就是好看一些哈,如果弄的话步骤是:准备一张你自己觉得好看的贴图,然后直接用NGUI建个Texture就行了,如果你的图片显示不是图片原有的效果,那可以尝试选择一下着色器(shader)的模式。

(3)准备你觉得合适的图片,然后用它创建一个图文集(Atlas);如果不会的话,那我就不教你啦,如果这个自己百度了还不会,那还是转行快点哈;话多了,不好意思。然后用这个图文集创建一个Button。

(4)这个需要修改的几个地方,1、这些Button自带代码的属性Unity3D 虚拟摇杆 NGUI实现方法_第2张图片,JoyControl.cs就是我编写的代码,等会再细说哈。2、Button的碰撞器要改,把Box Collider修改成这个Unity3D 虚拟摇杆 NGUI实现方法_第3张图片。3、Button的Background的Scale设置一下,

(5)代码的话应该有没有什么吧,我写了很多注释哈,如果实在看不懂,你们再留言,然后我再说哈。

 

 

using UnityEngine;
using System.Collections;

/**
 * note 此代码原创为谭俊孟编写 note
 * note 如果对此代码有什么好的意见或者建议 note
 * note 请联系QQ:408333990 note
 * note 或者发邮箱:[email protected] note
 * note 大家共同交流和进步 note
 * note 现由XXX转载修改,优化并使用 note
 */

public class JoyControl : MonoBehaviour
{	
	public GameObject playerTank;
	private float joyInitX;			//note 摇杆的圆心初始坐标X note
	private float joyInitY;			//note 摇杆的圆心初始坐标Y note
	private float joyMoveDistance;	//note 摇杆最大可移动的距离 note
	private float currentDistance;	//note 单签摇杆圆心离初始圆心的距离 note
	private float joyControlDistance;	//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 isTankMove;			//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().tankMoveSpeed);
				}
				else
				{
					playerTank.transform.Translate(Vector3.back * Time.deltaTime * getAbs(this.transform.localPosition.y, joyInitY) * playerTank.GetComponent().tankMoveSpeed);
				}
			}
			else if(this.transform.localPosition.y < parallelMoveLeftY && this.transform.localPosition.y > parallelMoveRightY)
			{
				//note 横向拖动摇杆不做任何操作 note
			}
			else
			{
				//note 坦克移动和旋转 note
				if(this.transform.localPosition.y > joyInitY)
				{
					playerTank.transform.Translate(Vector3.forward * Time.deltaTime * getAbs(this.transform.localPosition.y, joyInitY) * playerTank.GetComponent().tankMoveSpeed);
					if(this.transform.localPosition.x < joyInitX)
					{
						playerTank.transform.Rotate(Vector3.down * Time.deltaTime * getAbs(this.transform.localPosition.x, joyInitX) * playerTank.GetComponent().tankRotateSpeed);
					}
					else
					{
						playerTank.transform.Rotate(Vector3.up * Time.deltaTime * getAbs(this.transform.localPosition.x, joyInitX) * playerTank.GetComponent().tankRotateSpeed);
					}
				}
				else
				{
					playerTank.transform.Translate(Vector3.back * Time.deltaTime * getAbs(this.transform.localPosition.y, joyInitY) * playerTank.GetComponent().tankMoveSpeed);
					if(this.transform.localPosition.x < joyInitX)
					{
						playerTank.transform.Rotate(Vector3.up * Time.deltaTime * getAbs(this.transform.localPosition.x, joyInitX) * playerTank.GetComponent().tankRotateSpeed);
					}
					else
					{
						playerTank.transform.Rotate(Vector3.down * Time.deltaTime * getAbs(this.transform.localPosition.x, joyInitX) * playerTank.GetComponent().tankRotateSpeed);
					}
				}
			}
		}
	}
	
    void OnDrag (Vector2 delta) 
	{
		if(GameObject.Find("Main Camera").GetComponent().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 = false;
			}
			else if(currentDistance > joyMoveDistance)
			{
				setJoyMoveMaxPosition();
				isTankMove = true;
			}
			else
			{
				isTankMove = true;
			}
		}
		else if(GameObject.Find("Main Camera").GetComponent().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 + b; 推出k 和 b note
		 * note k = (y1 - y) / (x1 - x);   b = y - k * x; 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
		 */
		
		float k, b;				//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*joyMoveDistance;
		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);
			}
			else
			{
				this.transform.localPosition = new Vector3 (tempX2, k*tempX2 + b, 0);
			}
		}
		else
		{
			if(tempX1 < joyInitX)
			{
				this.transform.localPosition = new Vector3 (tempX1, k*tempX1 + b, 0);
			}
			else
			{
				this.transform.localPosition = new Vector3 (tempX2, k*tempX2 + b, 0);
			}
		}
	}
}


最后呢,总结一下吧,因为接触Unity时间不长,更加不说NGUI了,所以自适应效果没有做,还有一些异常处理液没有做,如果代码里面的某些东西给大家带来误导,那我先抱歉一下哈,哦,对了,最重要的,因为爪机太过落后,没能上真机调试,真能用电脑来调,所以就不是Touch时间了,而是mouse事件,不过应该改一下就行了,思想都是一样的哈,有什么好的意见或者建议请留言或者QQ或者邮箱联系哈。

你可能感兴趣的:(Unity3D 虚拟摇杆 NGUI实现方法)