NGUI下增加一个Empty对象,重命名为Joystick。在它本身上加载UIAnchor脚本,设置好它的大小。Joystick的子集中增加俩个新的Empty,命名为Background,Thumb。所有设置如下所示。

Unity3D NGUI屏幕摇杆_NGUI

Unity3D NGUI屏幕摇杆_NGUI_02

Unity3D NGUI屏幕摇杆_摇杆_03

Unity3D NGUI屏幕摇杆_NGUI_04

Thumb上增加box collier,为后期屏幕射线能够打在Background的区域。然后加上NGUIJoystick脚本。拖拽Thumb产生OnDrag,如下代码所示。

void OnDrag (Vector2 delta) {
if (enabled && gameObject.activeInHierarchy) {//当前对象被启用且对下在层次视图中处于激活状态
UICamera.currentTouch.clickNotification = UICamera.ClickNotification.BasedOnDelta;//得到UICamera脚本组件中的BasedDelta变量

Ray ray = UICamera.currentCamera.ScreenPointToRay (UICamera.currentTouch.pos);//得到从UI摄像机发出的到触摸点的一条射线
float dist = 0f;//定义射线长度变量

if (mPlane.Raycast (ray, out dist)) {//如果射线发生碰撞
Vector3 currentPos = ray.GetPoint (dist);//得到射线上距离dist远处的一个点
Vector3 offset = currentPos - mLastPos;//计算当前位置和上一次位置的偏移量
mLastPos = currentPos;//赋值

if (offset.x != 0f || offset.y != 0f) {//当偏移量的x或y分量不为零时
offset = transform.InverseTransformDirection (offset);//对偏移量进行世界坐标系到本地坐标系的转换
offset.Scale (scale);//对偏移量进行缩放
offset = transform.TransformDirection (offset);//对偏移量进行本地坐标系到世界坐标系的转换
}

offset.z = 0;//赋值
transform.position += offset;//改变对象位置

float length = transform.localPosition.magnitude;//得到当前对象本地位置向量的模

if (length > radius) {//当长度大于虚拟摇杆的背景半径时
transform.localPosition = Vector3.ClampMagnitude (transform.localPosition, radius);//计算当前对象的本地位置
}

position = new Vector2((transform.localPosition.x-center.x)/radius,(transform.localPosition.y-center.y)/radius);//将二维向量转换成z默认为0的三维向量
}
}
}

主要流程如下所示

Unity3D NGUI屏幕摇杆_当前对象_05

下面代码主角控制器调用,得到joystick的位置,计算出移动向量。

if (Input.GetAxis("Horizontal") == 0 && Input.GetAxis("Vertical") == 0)
{//当不是用键盘控制时(在手机屏幕上通过触控控制时)
directionVector = new Vector3(joystick.position.x, 0, joystick.position.y);//计算角色通过虚拟操纵杆来控制时的移动方向
}
if (directionVector != Vector3.zero)
{
float directionLength = directionVector.magnitude;//计算移动方向向量的长度
directionVector = directionVector / directionLength;//计算单位向量,这两句相当于directionVector.normalized,但这两句计算单位向量比向量的规格化更快

directionLength = Mathf.Min(0.4f, directionLength);//确保向量长度不超过1
//使向量到达边界值更敏感,到达中间值时更迟钝,这样使得使用操纵杆时更容易控制减速
directionLength = directionLength * directionLength;
//计算移动方向向量
directionVector = directionVector * directionLength;
}
directionVector.y = 0;
m_charCon.Move(m_trans.TransformDirection(directionVector));//计算移动方向