在塔防游戏中,防守单位都是动态创建的,通常游戏中将提供若干个按钮,当选中其中一个按钮后,这个按钮将保持激活状态,这时在场景中选择位置按下鼠标,即可创建一个防守单位,同时也会扣除一些用于创建防守单位的资金或点数。
接下来我们将创建一个自定义的按钮,虽然使用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,使射线可以与地面碰撞。
运行游戏,按一下屏幕上的按钮,然后在地面上点一下,即可创建一个防守单位。
这个塔防游戏到这里就结束了,它还非常简陋,但具备了塔防游戏的基本要素,如果添加更多的细节和更好的画面,相信它可以变成一款不错的游戏。