在塔防游戏中,防守单位都是动态创建的,通常游戏中将提供若干个按钮,当选中其中一个按钮后,这个按钮将保持激活状态,这时在场景中选择位置按下鼠标,即可创建一个防守单位,同时也会扣除一些用于创建防守单位的资金或点数。
接下来我们将创建一个自定义的按钮,虽然使用OnGUI创建按钮更容易,但OnGUI的效率较低,也不利于制作布局复杂或有特殊需求的UI,更难为它制作动画。
1)创建角本GUIButton.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
using
UnityEngine; using
System.Collections; public
class GUIButton : MonoBehaviour { //
按钮状态 protected
enum StateID { NORMAL=0, //
正常 FOCUS, //
高亮 ACTIV, //
选中 } protected
StateID m_state = StateID. NORMAL; //
按钮的贴图 public
Texture[] m_ButtonSkin; //
按钮的ID public
int m_ID = 0; //
按钮是否处于激活状态 protected
bool m_isOnActiv = false ; //
按钮的缩放 public
float m_scale = 1.0f; //
按钮的屏幕位置 Vector2
m_screenPosition; //
按钮的当前贴图 public
GUITexture m_texture; //
初始化按钮 void
Awake() { //
获得贴图 m_texture
= this .guiTexture; //
获得位置 m_screenPosition
= new Vector3(m_texture.pixelInset.x,
m_texture.pixelInset.y, 0); //
设置默认状态 SetState(StateID.NORMAL); } //更新按钮状态,选中按钮,返回它的ID public
int UpdateState(bool mouse,Vector3 mousepos) { int
result = -1; if (m_texture.HitTest(mousepos))
{ if (mouse)
{ SetState(StateID.ACTIV); return m_ID;
} else SetState(StateID.FOCUS); } else { if (m_isOnActiv)
SetState(StateID.ACTIV); else SetState(StateID.NORMAL); } return result;
} //
设置按钮状态 protected
virtual void SetState(StateID state) { if (m_state
== state) return ; m_state
= state; m_texture.texture
= m_ButtonSkin[(int)m_state]; float
w = m_ButtonSkin[(int)m_state].width * m_scale; float
h = m_ButtonSkin[(int)m_state].height * m_scale; m_texture.pixelInset
= new Rect( this .m_screenPosition.x,
m_screenPosition.y, w, h); } //
设置按钮缩放 public
virtual void SetScale(float scale) { m_scale
= scale; float
w = m_ButtonSkin[0].width * scale; float
h = m_ButtonSkin[0].height * scale; m_screenPosition.x
*= scale; m_screenPosition.y
*= scale; m_texture.pixelInset
= new Rect(m_screenPosition.x,
m_screenPosition.y, w, h); } //
设置激活状态 public
virtual void SetOnActiv(bool isactiv) { if (isactiv)
SetState(StateID.ACTIV); else if
(m_isOnActiv) SetState(StateID.NORMAL); m_isOnActiv
= isactiv; } } |
在这个脚本中,Awake函数初始化了按钮的状态,按钮一共有三种状态,包括正常、高亮和激活。
在UpdateState函数中,判断是否选中按钮,如果选中,则返回按钮的ID。
SetState函数用来设置按钮的状态,实际上是在更新按钮的贴图。
SetScale函数用来设置按钮的缩放,在手机平台,因为机器设备的分辨率不统一,所以在不同平台对按钮进行相应缩放是必要的。
SetOnActiv函数会将按钮设为激活状态,当按钮处于这种状态,即使鼠标从按钮上移开,按钮的状态也不会改变。
2)在Project窗口的GUI文件夹中找到ui_turret_n.png,确定它处于选择状态,在菜单栏选择【GameObject】→【Create Other】→【GUI Texture】创建一个显示有UI贴图的游戏体,然后为它指定角本GUIButton.cs,在Button Skin中设置对应按钮三种状态的贴图,将按钮的ID设为1,如图4-27所示。
3)我们将不使用3d坐标改变按钮的位置,将按钮的Position设为0,然后将Pixel Inset的X和Y设为5,如图4-27所示,按钮将出现在屏幕坐标(5,5)的位置,如图4-28所示。
4)将按钮命名为button_0,并设为GameManager的子物体,如图4-29所示。
5)打开GameManager.cs,加入按钮等相关属性如下,然后将前面创建的防守单位与m_guardPrefab关联。新建一个名为ground的Layer,将m_groundlayer与其关联。
(此处省略××××××字,包括源代码)
8)将地面的Layer设为ground,使射线可以与地面碰撞。
运行游戏,按一下屏幕上的按钮,然后在地面上点一下,即可创建一个防守单位。
这个塔防游戏到这里就结束了,它还非常简陋,但具备了塔防游戏的基本要素,如果添加更多的细节和更好的画面,相信它可以变成一款不错的游戏。