最近在做项目是用的unity最新的ui系统UGUI,项目需要做一个摇杆,网上大部分都是用的插件和NGUI做的摇杆,unity自带的摇杆也不怎么好用,而最新的unity4.6.x来了,加入了最新的UI系统“UGUI”,那我们怎么用UGUI来制作摇杆呢,比较出色的摇杆插件《Easy Touch》(很强大),还是主要讲讲我们自己怎么做。
-
首先在unity场景里面新建一个空物体和两个Image,把空物体放在创建Image自动生成的Canvas里面,再把两个Image放在空物体里Image建立方式:GameObject->UI->Image 或者直接在“Hierarchy”右键然后UI->Image,看喜好。空物体和两个Image的命名看个人喜好。威恩的节点是这样的:
节点中的joystack是刚刚建立的空节点。Backgound是摇杆的背景。JoystackControl是真实的可以拖动的摇杆。 -
把Backgound和JoystackControl的SourceImage替换成自己喜欢的图片,并且把JoystackControl的图片缩小点,这里我就用系统自带的图片了,威恩这两个节点的inspector如下(我修改过得地方用红框标注了,其他都没改):
如下:
-
那么样子有了就需要让他动起来,需要三个类“EventTriggerListener”、“JoystackCc”、“PlayerMoveControl”。EventTriggerListener:在NGUI开发的时候处理事件都会用到UIEventListener,我们已经用的习惯的不得了,而UGUI则不是这种机制,并且我觉得这种是最合理的方式,所以自己写一套类似的。只是一个帮助类,不需要挂在任何的游戏对象上。JoystackCc:这是主要来控制摇杆的。挂在JoystackControl节点上PlayerMoveControl:这是主要来通过摇杆来控制角色的。挂在你想控制的物体上直接上代码,写了注释,就不哔哔了。EventTriggerListener.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
using
UnityEngine;
using
System.Collections;
using
UnityEngine.EventSystems;
using
System.Collections.Generic;
/// <summary>
/// UGUI事件监听类
/// </summary>
public
class
EventTriggerListener : UnityEngine.EventSystems.EventTrigger{
public
delegate
void
VoidDelegate (GameObject go);
public
delegate
void
VectorDelegate(GameObject go, Vector2 delta);
public
VoidDelegate onClick;
public
VoidDelegate onDown;
public
VoidDelegate onEnter;
public
VoidDelegate onExit;
public
VoidDelegate onUp;
public
VoidDelegate onSelect;
public
VoidDelegate onUpdateSelect;
public
VectorDelegate onDrag;
public
VoidDelegate onDragOut;
static
public
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;
}
}
public
override
void
OnDrag(PointerEventData eventData)
{
if
(onDrag !=
null
) onDrag(gameObject, eventData.delta);
}
public
override
void
OnEndDrag(PointerEventData eventData)
{
if
(onDragOut !=
null
) onDragOut(gameObject);
}
public
override
void
OnPointerClick(PointerEventData eventData)
{
if
(onClick !=
null
) onClick(gameObject);
}
public
override
void
OnPointerDown (PointerEventData eventData){
if
(onDown !=
null
) onDown(gameObject);
}
public
override
void
OnPointerEnter (PointerEventData eventData){
if
(onEnter !=
null
) onEnter(gameObject);
}
public
override
void
OnPointerExit (PointerEventData eventData){
if
(onExit !=
null
) onExit(gameObject);
}
public
override
void
OnPointerUp (PointerEventData eventData){
if
(onUp !=
null
) onUp(gameObject);
}
public
override
void
OnSelect (BaseEventData eventData){
if
(onSelect !=
null
) onSelect(gameObject);
}
public
override
void
OnUpdateSelected (BaseEventData eventData){
if
(onUpdateSelect !=
null
) onUpdateSelect(gameObject);
}
}
|
JoystackCc.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
using
UnityEngine;
using
System.Collections;
public
class
JoystackCc : MonoBehaviour {
private
Vector3 Origin;
Transform mTrans;
private
Vector3 _deltaPos;
private
bool
_drag =
false
;
private
Vector3 deltaPosition;
float
dis;
[SerializeField]
private
float
MoveMaxDistance = 80;
//最大拖动距离
[HideInInspector]
public
Vector3 FiexdMovePosiNorm;
//固定8个角度移动的距离
[HideInInspector]
public
Vector3 MovePosiNorm;
//标准化移动的距离
[SerializeField]
private
float
ActiveMoveDistance = 1;
//激活移动的最低距离
void
Awake()
{
EventTriggerListener.Get(gameObject).onDrag = OnDrag;
EventTriggerListener.Get(gameObject).onDragOut = OnDragOut;
EventTriggerListener.Get(gameObject).onDown = OnMoveStart;
}
// Use this for initialization
void
Start () {
Origin = transform.localPosition;
//设置原点
mTrans = transform;
}
// Update is called once per frame
void
Update()
{
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;
}
void
MiouseDown()
{
if
((Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved))
{
}
else
mTrans.localPosition = Origin;
}
Vector3 result;
private
Vector3 _checkPosition(Vector3 movePos, Vector3 _offsetPos)
{
result = movePos + _offsetPos;
return
result;
}
void
OnDrag(GameObject go, Vector2 delta)
{
if
(!_drag)
{
_drag =
true
;
}
_deltaPos = delta;
mTrans.localPosition +=
new
Vector3(_deltaPos.x, _deltaPos.y, 0);
}
void
OnDragOut(GameObject go)
{
_drag =
false
;
mTrans.localPosition = Origin;
if
(PlayerMoveControl.moveEnd !=
null
) PlayerMoveControl.moveEnd();
}
void
OnMoveStart(GameObject go)
{
if
(PlayerMoveControl.moveStart !=
null
) PlayerMoveControl.moveStart();
}
}
|
PlayerMoveControl.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
using
UnityEngine;
using
System.Collections;
public
class
PlayerMoveControl : MonoBehaviour {
private
Transform _mTransform;
public
JoystackCc _mJoystackCc;
public
float
moveSpeed = 50;
public
delegate
void
MoveDelegate();
public
static
MoveDelegate moveEnd;
public
static
MoveDelegate moveStart;
public
static
PlayerMoveControl Instance;
// Use this for initialization
void
Awake()
{
Instance =
this
;
_mTransform = transform;
moveEnd = OnMoveEnd;
moveStart = OnMoveStart;
}
void
Start () {
}
void
OnMoveEnd()
{
_turnBase =
false
;
}
void
OnMoveStart()
{
_turnBase =
true
;
}
// Update is called once per frame
private
float
angle;
private
bool
_turnBase =
false
;
void
Update()
{
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);
}
}
}
|
-
建好这三个类之后,把他们绑定到相应的节点上。