游戏展示
游戏开发
创建 2D/3D 游戏
创建 2D 游戏
(TypeGame2D.sence)。
虽然是 2D 游戏,这里也可以用 3D Object
,其中 Plane
为 3D > Plane
(Gameplay.sence)。
设置分辨率
Standalone(1024x768)
略
导入资源
略
Resources / 打字游戏文本
创建新文件夹,Resources
- Project
- Assets
- Create
- Folder:
Resources
- Folder:
- Resources
- “xxx.txt”
- Create
- Assets
BG / 背景
拖入 BG
背景
Bottom 碰撞检测
2D
- Hirearchy
- Create Empty:
Bottom
- Create Empty:
- Inspector
- Tag:
Bottom
- Rect Transform
- Position
- Y:
-5.18
- Y:
- Position
- Box Collider 2D
- Is Trigger:
True
- Size
- X:
26
- Y:
0.15
- X:
- Is Trigger:
- Tag:
3D
- Hirearchy
- Create
- 3D
- Plane
- 3D
- Create
- Inspector
- Rect Transform
- Position
- Y:
-6.54
- Y:
- Scale
- X:
2
- Y:
1
- Z:
0.1
- X:
- Position
- Rect Transform
确保能发生碰撞
Scripts
创建新文件夹,Scripts
,脚本都是 2D/3D Object
通用。
- Project
- Assets
- Create
- Folder:
Scripts
- Folder:
- Scripts
- Create
- C# Script
WordController
# word 控制器WordSwapner
# word 生成器GameController
# UI 检测碰撞
- C# Script
- Create
- Create
- Assets
WordController
1 | using UnityEngine; |
2 | |
3 | public class WordController : MonoBehaviour |
4 | { |
5 | public float mytimer = 1f; |
6 | public float gravity = -10f; |
7 | public GUISkin skin; |
8 | |
9 | private int position; |
10 | private string showString; |
11 | private string word; // "Hello" |
12 | private string preWord; // match pre "He" |
13 | private string postWord; // match post "llo" |
14 | private string hitColor = "#00ff00"; |
15 | private string hitChar; |
16 | private string defaultColor = "#ffffff"; |
17 | private Vector3 transformPos3D; |
18 | private Vector2 transformPos2D; |
19 | private Transform myTransform; |
20 | private Camera mainCamera; |
21 | private bool isBlow; |
22 | private string explain; |
23 | private int lengthChange; |
24 | private bool oncecal; |
25 | |
26 | void Start() |
27 | { |
28 | oncecal = false; |
29 | word = WordSwapner.instance.word; |
30 | explain = WordSwapner.instance.explain; |
31 | position = -1; |
32 | mainCamera = Camera.main; |
33 | myTransform = this.transform; |
34 | isBlow = false; |
35 | lengthChange = word.Length * 10; |
36 | } |
37 | |
38 | void Update() |
39 | { |
40 | Physics.gravity = new Vector3(0, gravity, 0); |
41 | |
42 | if (!isBlow) |
43 | { |
44 | if (position == -1) |
45 | { |
46 | showString = word; |
47 | } |
48 | if (Input.anyKeyDown) |
49 | { |
50 | position++; |
51 | } |
52 | if (Input.GetKeyDown(KeyCode.A)) |
53 | { |
54 | hitChar = "a"; |
55 | } |
56 | if (Input.GetKeyDown(KeyCode.B)) |
57 | { |
58 | hitChar = "b"; |
59 | } |
60 | if (Input.GetKeyDown(KeyCode.C)) |
61 | { |
62 | hitChar = "c"; |
63 | } |
64 | if (Input.GetKeyDown(KeyCode.D)) |
65 | { |
66 | hitChar = "d"; |
67 | } |
68 | if (Input.GetKeyDown(KeyCode.E)) |
69 | { |
70 | hitChar = "e"; |
71 | } |
72 | if (Input.GetKeyDown(KeyCode.F)) |
73 | { |
74 | hitChar = "f"; |
75 | } |
76 | if (Input.GetKeyDown(KeyCode.G)) |
77 | { |
78 | hitChar = "g"; |
79 | } |
80 | if (Input.GetKeyDown(KeyCode.H)) |
81 | { |
82 | hitChar = "h"; |
83 | } |
84 | if (Input.GetKeyDown(KeyCode.I)) |
85 | { |
86 | hitChar = "i"; |
87 | } |
88 | if (Input.GetKeyDown(KeyCode.J)) |
89 | { |
90 | hitChar = "j"; |
91 | } |
92 | if (Input.GetKeyDown(KeyCode.K)) |
93 | { |
94 | hitChar = "k"; |
95 | } |
96 | if (Input.GetKeyDown(KeyCode.L)) |
97 | { |
98 | hitChar = "l"; |
99 | } |
100 | if (Input.GetKeyDown(KeyCode.M)) |
101 | { |
102 | hitChar = "m"; |
103 | } |
104 | if (Input.GetKeyDown(KeyCode.N)) |
105 | { |
106 | hitChar = "n"; |
107 | } |
108 | if (Input.GetKeyDown(KeyCode.O)) |
109 | { |
110 | hitChar = "o"; |
111 | } |
112 | if (Input.GetKeyDown(KeyCode.P)) |
113 | { |
114 | hitChar = "p"; |
115 | } |
116 | if (Input.GetKeyDown(KeyCode.Q)) |
117 | { |
118 | hitChar = "q"; |
119 | } |
120 | if (Input.GetKeyDown(KeyCode.R)) |
121 | { |
122 | hitChar = "r"; |
123 | } |
124 | if (Input.GetKeyDown(KeyCode.S)) |
125 | { |
126 | hitChar = "s"; |
127 | } |
128 | if (Input.GetKeyDown(KeyCode.T)) |
129 | { |
130 | hitChar = "t"; |
131 | } |
132 | if (Input.GetKeyDown(KeyCode.U)) |
133 | { |
134 | hitChar = "u"; |
135 | } |
136 | if (Input.GetKeyDown(KeyCode.V)) |
137 | { |
138 | hitChar = "v"; |
139 | } |
140 | if (Input.GetKeyDown(KeyCode.W)) |
141 | { |
142 | hitChar = "w"; |
143 | } |
144 | if (Input.GetKeyDown(KeyCode.X)) |
145 | { |
146 | hitChar = "x"; |
147 | } |
148 | if (Input.GetKeyDown(KeyCode.Y)) |
149 | { |
150 | hitChar = "y"; |
151 | } |
152 | if (Input.GetKeyDown(KeyCode.Z)) |
153 | { |
154 | hitChar = "z"; |
155 | } |
156 | if (Input.GetKeyDown(KeyCode.Keypad0) || Input.GetKeyDown(KeyCode.Alpha0)) |
157 | { |
158 | hitChar = "0"; |
159 | } |
160 | if (Input.GetKeyDown(KeyCode.Keypad1) || Input.GetKeyDown(KeyCode.Alpha1)) |
161 | { |
162 | hitChar = "1"; |
163 | } |
164 | if (Input.GetKeyDown(KeyCode.Keypad2) || Input.GetKeyDown(KeyCode.Alpha2)) |
165 | { |
166 | hitChar = "2"; |
167 | } |
168 | if (Input.GetKeyDown(KeyCode.Keypad3) || Input.GetKeyDown(KeyCode.Alpha3)) |
169 | { |
170 | hitChar = "3"; |
171 | } |
172 | if (Input.GetKeyDown(KeyCode.Keypad4) || Input.GetKeyDown(KeyCode.Alpha4)) |
173 | { |
174 | hitChar = "4"; |
175 | } |
176 | if (Input.GetKeyDown(KeyCode.Keypad5) || Input.GetKeyDown(KeyCode.Alpha5)) |
177 | { |
178 | hitChar = "5"; |
179 | } |
180 | if (Input.GetKeyDown(KeyCode.Keypad6) || Input.GetKeyDown(KeyCode.Alpha6)) |
181 | { |
182 | hitChar = "6"; |
183 | } |
184 | if (Input.GetKeyDown(KeyCode.Keypad7) || Input.GetKeyDown(KeyCode.Alpha7)) |
185 | { |
186 | hitChar = "7"; |
187 | } |
188 | if (Input.GetKeyDown(KeyCode.Keypad8) || Input.GetKeyDown(KeyCode.Alpha8)) |
189 | { |
190 | hitChar = "8"; |
191 | } |
192 | if (Input.GetKeyDown(KeyCode.Keypad9) || Input.GetKeyDown(KeyCode.Alpha9)) |
193 | { |
194 | hitChar = "9"; |
195 | } |
196 | if (Input.GetKeyDown(KeyCode.Space)) |
197 | { |
198 | hitChar = " "; |
199 | } |
200 | if (Input.GetKeyDown(KeyCode.Minus)) |
201 | { |
202 | hitChar = "-"; |
203 | } |
204 | if (Input.GetKeyDown(KeyCode.Period)) |
205 | { |
206 | hitChar = "."; |
207 | } |
208 | if (Input.GetKeyDown(KeyCode.Return)) |
209 | { |
210 | hitChar = "Return"; |
211 | } |
212 | |
213 | if (position < WordSwapner.instance.midBreak) |
214 | { |
215 | position = -1; |
216 | return; |
217 | } |
218 | |
219 | if ((position >= 0) && (position < word.Length)) |
220 | { |
221 | preWord = word.Substring(0, position + 1); |
222 | postWord = word.Substring(position + 1); |
223 | |
224 | if (!word.Substring(position, 1).ToLower().Equals(hitChar)) |
225 | { |
226 | position = -1; |
227 | WordSwapner.instance.midBreak = -1; |
228 | } |
229 | else |
230 | { |
231 | WordSwapner.instance.midBreak = position; |
232 | |
233 | showString = "<color=" + hitColor + ">" + preWord + "</color><color=" + defaultColor + ">" + postWord + "</color>"; |
234 | } |
235 | return; |
236 | } |
237 | } |
238 | |
239 | if (position >= word.Length - 1) |
240 | { |
241 | if (hitChar.Equals("Return")) |
242 | { |
243 | WordSwapner.instance.midBreak = -1; |
244 | |
245 | if (!oncecal) |
246 | { |
247 | lengthChange = explain.Length * 15; |
248 | oncecal = true; |
249 | } |
250 | showString = "<color=white>" + explain + "</color>"; |
251 | |
252 | mytimer -= Time.deltaTime * 2; |
253 | |
254 | if (mytimer <= 0 && !isBlow) |
255 | { |
256 | isBlow = true; |
257 | GameController.instance.score += 1; |
258 | |
259 | if (GameController.instance.score > GameController.instance.highScore) |
260 | { |
261 | GameController.instance.highScore = GameController.instance.score; |
262 | } |
263 | } |
264 | } |
265 | } |
266 | } |
267 | |
268 | void OnGUI() |
269 | { |
270 | GUI.skin = skin; |
271 | transformPos3D = transform.position; |
272 | transformPos2D = mainCamera.WorldToScreenPoint(transformPos3D); |
273 | transformPos2D = new Vector2(transformPos2D.x, Screen.height - transformPos2D.y); |
274 | |
275 | if (!isBlow) |
276 | { |
277 | GUI.Box(new Rect(transformPos2D.x, transformPos2D.y, lengthChange*3, 64), showString); |
278 | } |
279 | else |
280 | { |
281 | Destroy(this.gameObject, 1); |
282 | } |
283 | } |
284 | } |
WordSwapner
1 | using System.IO; |
2 | using UnityEngine; |
3 | |
4 | public class WordSwapner : MonoBehaviour |
5 | { |
6 | public Transform wordTransform; |
7 | private Transform myTransform; |
8 | public TextAsset txt; |
9 | |
10 | public static WordSwapner instance; |
11 | private string txtLine; |
12 | public string word; |
13 | public string explain; |
14 | |
15 | private float interval; |
16 | private string[] txtData; |
17 | public int midBreak; |
18 | |
19 | void Start() |
20 | { |
21 | instance = this; |
22 | myTransform = this.transform; |
23 | |
24 | txtData = txt.text.Split('\n'); |
25 | } |
26 | |
27 | void Update() |
28 | { |
29 | interval -= Time.deltaTime; |
30 | if (interval <= 0) |
31 | { |
32 | txtLine = txtData[Random.Range(0, txtData.Length)]; |
33 | word = txtLine.Split('|')[0].TrimEnd(); |
34 | explain = txtLine.Split('|')[1].TrimStart(); |
35 | Instantiate(wordTransform, new Vector3(myTransform.position.x + Random.Range(-4, 4), myTransform.position.y, myTransform.position.z), Quaternion.identity); |
36 | interval = 3.5f; |
37 | } |
38 | } |
39 | } |
GameController
1 | using UnityEngine; |
2 | using UnityEngine.SceneManagement; |
3 | |
4 | public class GameController : MonoBehaviour |
5 | { |
6 | public int life; |
7 | public static GameController instance; |
8 | public int score; |
9 | public int highScore; |
10 | public GUISkin skin; |
11 | private bool esc; |
12 | |
13 | void Start() |
14 | { |
15 | Time.timeScale = 1; |
16 | //life = 10; |
17 | instance = this; |
18 | highScore = PlayerPrefs.GetInt("HiScore"); |
19 | } |
20 | |
21 | void Update() |
22 | { |
23 | esc |= Input.GetKeyDown(KeyCode.Escape); |
24 | } |
25 | |
26 | private void OnTriggerEnter2D(Collider2D collision) |
27 | { |
28 | Debug.Log("OnTriggerEnter2D"); |
29 | if (collision.CompareTag("Word")) |
30 | { |
31 | if (life > 0) |
32 | { |
33 | life -= 1; |
34 | WordSwapner.instance.midBreak = -1; |
35 | Destroy(collision.gameObject); |
36 | } |
37 | } |
38 | } |
39 | |
40 | void OnTriggerEnter(Collider other) |
41 | { |
42 | if (other.CompareTag("Word")) |
43 | { |
44 | if (life > 0) |
45 | { |
46 | life -= 1; |
47 | WordSwapner.instance.midBreak = -1; |
48 | Destroy(other.gameObject); |
49 | } |
50 | } |
51 | } |
52 | |
53 | void OnGUI() |
54 | { |
55 | GUI.skin = skin; |
56 | GUI.Label(new Rect(20, 20, 300, 100), "High Score: " + highScore); |
57 | GUI.Label(new Rect(Screen.width - 220, 20, 200, 100), "Score: " + score); |
58 | GUI.Label(new Rect(Screen.width - 220, Screen.height - 120, 200, 100), "Life:" + life); |
59 | |
60 | if (esc && life != 0) |
61 | { |
62 | Time.timeScale = 0; |
63 | if (GUI.Button(new Rect(Screen.width / 2 - 200, Screen.height / 2 - 50, 200, 100), "Resume")) |
64 | { |
65 | esc = false; |
66 | Time.timeScale = 1; |
67 | } |
68 | } |
69 | |
70 | if (life == 0) |
71 | { |
72 | esc = true; |
73 | Time.timeScale = 0; |
74 | |
75 | if (score > highScore) |
76 | { |
77 | PlayerPrefs.SetInt("HiScore", highScore); |
78 | GUI.Label(new Rect(Screen.width / 2 - 200, Screen.height / 2 - 300, 400, 100), "Awesome!"); |
79 | } |
80 | |
81 | if (GUI.Button(new Rect(Screen.width / 2 - 200, Screen.height / 2 - 50, 400, 100), "Restart")) |
82 | { |
83 | RestartGame(); |
84 | } |
85 | |
86 | if (GUI.Button(new Rect(Screen.width / 2 - 200, Screen.height / 2 + 100, 400, 100), "Quit")) |
87 | { |
88 | Application.Quit(); |
89 | } |
90 | } |
91 | } |
92 | |
93 | void RestartGame() |
94 | { |
95 | SceneManager.LoadScene( |
96 | SceneManager.GetActiveScene().name); |
97 | } |
98 | } |
小结
2D 游戏的制作可以参照之前的 《Box Tower / 堆箱塔》,也可以用 3D 实现 2D 效果。
下载
游戏
Release: https://github.com/GameDevLog/GameDevLogTemplete/releases