前言
首先这是我学习Unity的第一篇博客,所以好多东西都不太懂,写的不好请见谅
分享一下我用Unity制作第一款小游戏-井字棋的过程与心得吧
步骤
- 这是Unity的主界面,进去之后在下面的Assets框里右键新建一个C#脚本(不会用JS…)
然后我们主要做的就是编写这个脚本里面代码的工作了(因为做的不是3D游戏,而且只是刚接触,也没有添加特殊的游戏对象),双击C#文件会弹出一个Unity自带的代码编辑器,当然装了VS或者其他C#编辑器也可以用自己熟悉的工具打开
- 其实除了Start() 和 Update() 还有其他的一些常用事件
(1)当一个脚本实例被载入时Awake被调用。
(3)当MonoBehaviour启用时,其Update在每一帧被调用。
(4)渲染和处理GUI事件时调用OnGUI。
(5)当MonoBehaviour启用时,其 FixedUpdate 在每一帧被调用。
(6)当Behaviour启用时,其LateUpdate在每一帧被调用。
(7)Reset,重置为默认值。
(8)当对象变为不可用或非激活状态时OnDisable函数被调用。
(9)当MonoBehaviour将被销毁时,OnDestory函数被调用。
这里我们省去写代码的步骤,毕竟也很简单,后面会附上代码以及简单的分析
因为没有加任何游戏对象,所以就直接把这个脚本文件拖到左边框里的Main Camera里面就行了,添加之后可以点击Main Camera 能看到右边Inspector窗口出现了这个脚本文件, 然后点击中间的运行按钮就能玩这个小游戏了
下面展示一下运行的截图
开始界面
甲方获胜
乙方获胜
和棋
点击提示按钮之后
点击帮助按钮之后
哈哈,那两个按钮只是缓解一些游戏氛围的,但重来和退出按钮都是正常有用的
代码
- 数据结构分析
主要的思路呢,是把九个按钮框都编号1~9,然后用数组的所以存储,用1表示已经被点击,用0表示还没有被点击
这里是表示两个玩家各自点击了哪些按钮,用于判断最后哪一方胜利
int[] player1 = new int[10]{0,0,0,0,0,0,0,0,0,0} ;
int[] player2 = new int[10]{0,0,0,0,0,0,0,0,0,0} ;
这里是表示哪些按钮已经被点击过了,而不用管是哪一个玩家点击的,用于判断重复点击某个按钮的情况
int[] selected = new int[10]{0,0,0,0,0,0,0,0,0,0};
这里是表示两个玩家各自已经下了多少步棋子,因为其实是一个人模拟两个玩家在玩,所以通过这个判断轮到哪个玩家
int count1 = 0;
int count2 = 0;
这是每个按钮被创建的时候绑定的字符串,因为不知道是哪一方点击了这个按钮,所以开始设置为空,后来根据需要再改变它的值
另外底下的一个string是绑定到提示框的信息
public string string1 = "";
public string string2 = "";
public string string3 = "";
public string string4 = "";
public string string5 = "";
public string string6 = "";
public string string7 = "";
public string string8 = "";
public string string9 = "";
public string message = "轮到甲方";
对了,还有一个判断游戏结束的bool变量
bool gameover = false;
- 界面创建
我用了一个Group更加方便的给另外几个按钮布局
(这样设置让Group绝对居中)
GUI.BeginGroup (new Rect (Screen.width / 2 - 150, Screen.height / 2 - 210, 300, 420));
这是几个按钮以及顶部的游戏程序名称Box的布局设置
if (GUI.Button (new Rect (0, 300, 300, 80), message)) { //提示框
string temp = message;
message = temp + "\n(玩游戏要专心,不要乱点啊!)";
}
if(GUI.Button (new Rect (0, 380, 100, 30), "帮助")) { //帮助按钮
string temp = message;
message = temp + "\n(还没有写这个,请自己百度!)";
}
if(GUI.Button (new Rect (200, 380, 100, 30), "退出")) { //退出按钮
Application.Quit ();
}
if(GUI.Button (new Rect (100, 380, 100, 30), "重来")) //重来按钮
GUI.Box (new Rect (0,0,300,300), "井字棋"); //游戏名称
if (GUI.Button (new Rect (20,20,80,80), string1)) //第一个游戏按钮
...
- 逻辑判断
这是第一个按钮里面的函数,别的按钮逻辑也一样,只是按钮名字不一样
if (gameover) // 因为游戏结束之后程序不退出,所以这是为了防止已经分出胜负空白按钮还能继续点
return;
if (selected [1] == 0) {
if (count1 <= count2) { //判断哪一方落子
string1 = "甲方";
player1 [1] = 1;
count1++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";gameover = true; //和棋的情况(之前还没考虑到)
}
else
message = "轮到乙方\n";
}
else {
string1 = "乙方";
player2 [1] = 1;
count2++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";gameover = true;
}
else
message = "轮到甲方\n";
}
selected [1] = 1;
//判断胜负
if (Adjust (player1)) {
message = "游戏结束:\n甲方获胜!";
GUI.backgroundColor = Color.red;gameover = true;
}
if (Adjust (player2)) {
message = "游戏结束:\n乙方获胜!";gameover = true;
GUI.backgroundColor = Color.red;
}
} else {
message = "操作失败:\n这个地方已经有棋子了!";
}
判断胜负的函数(英语是真的差,之前还以为adjust有判断的意思……)
bool Adjust(int[] player){
if (player [1] == 1 && player [2] == 1 && player [3] == 1)
return true;
if (player [4] == 1 && player [5] == 1 && player [6] == 1)
return true;
if (player [7] == 1 && player [8] == 1 && player [9] == 1)
return true;
if (player [1] == 1 && player [4] == 1 && player [7] == 1)
return true;
if (player [2] == 1 && player [5] == 1 && player [8] == 1)
return true;
if (player [3] == 1 && player [6] == 1 && player [9] == 1)
return true;
if (player [1] == 1 && player [5] == 1 && player [9] == 1)
return true;
if (player [3] == 1 && player [5] == 1 && player [7] == 1)
return true;
return false;
}
这是重来按钮的事件
if(GUI.Button (new Rect (100, 380, 100, 30), "重来")) {
string1 = "";
string2 = "";
string3 = "";
string4 = "";
string5 = "";
string6 = "";
string7 = "";
string8 = "";
string9 = "";
message = "轮到甲方";
count1 = 0;
count2 = 0;
gameover = false;
for (int i = 0; i < 10; i++) {
player1 [i] = 0;
player2 [i] = 0;
selected [i] = 0;
}
}
- 说明
- 点击退出按钮之后的函数我是用Application.Quit ()实现的,不知道为什么在Unity调试里面点击退出按钮没有反应,但是我把这个游戏发布为exe或者apk安装之后是有用的
- 完整代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class main : MonoBehaviour {
public GUISkin Player1;
public GUISkin Player2;
public GUISkin Customer;
public string message = "轮到甲方";
public string string1 = "";
public string string2 = "";
public string string3 = "";
public string string4 = "";
public string string5 = "";
public string string6 = "";
public string string7 = "";
public string string8 = "";
public string string9 = "";
int[] player1 = new int[10]{0,0,0,0,0,0,0,0,0,0} ;
int[] player2 = new int[10]{0,0,0,0,0,0,0,0,0,0} ;
int count1 = 0;
int count2 = 0;
bool gameover = false;
int[] selected = new int[10]{0,0,0,0,0,0,0,0,0,0};
//public GUISkin mySkin;
bool Adjust(int[] player){
if (player [1] == 1 && player [2] == 1 && player [3] == 1)
return true;
if (player [4] == 1 && player [5] == 1 && player [6] == 1)
return true;
if (player [7] == 1 && player [8] == 1 && player [9] == 1)
return true;
if (player [1] == 1 && player [4] == 1 && player [7] == 1)
return true;
if (player [2] == 1 && player [5] == 1 && player [8] == 1)
return true;
if (player [3] == 1 && player [6] == 1 && player [9] == 1)
return true;
if (player [1] == 1 && player [5] == 1 && player [9] == 1)
return true;
if (player [3] == 1 && player [5] == 1 && player [7] == 1)
return true;
return false;
}
void Start(){
Debug.Log ("游戏开始!\n");
}
void Update(){
Debug.Log ("游戏正在进行中!\n");
}
void OnGUI () {
GUI.skin = Customer;
GUI.BeginGroup (new Rect (Screen.width / 2 - 150, Screen.height / 2 - 210, 300, 420));
if (GUI.Button (new Rect (0, 300, 300, 80), message)) {
string temp = message;
message = temp + "\n(玩游戏要专心,不要乱点啊!)";
}
if(GUI.Button (new Rect (0, 380, 100, 30), "帮助")) {
string temp = message;
message = temp + "\n(还没有写这个,请自己百度!)";
}
if(GUI.Button (new Rect (200, 380, 100, 30), "退出")) {
Application.Quit ();
}
if(GUI.Button (new Rect (100, 380, 100, 30), "重来")) {
string1 = "";
string2 = "";
string3 = "";
string4 = "";
string5 = "";
string6 = "";
string7 = "";
string8 = "";
string9 = "";
message = "轮到甲方";
count1 = 0;
count2 = 0;
gameover = false;
for (int i = 0; i < 10; i++) {
player1 [i] = 0;
player2 [i] = 0;
selected [i] = 0;
}
}
GUI.Box (new Rect (0,0,300,300), "井字棋");
if (GUI.Button (new Rect (20,20,80,80), string1)) {
if (gameover)
return;
if (selected [1] == 0) {
if (count1 <= count2) {
string1 = "甲方";
player1 [1] = 1;
count1++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";gameover = true;
}
else
message = "轮到乙方\n";
}
else {
string1 = "乙方";
player2 [1] = 1;
count2++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";gameover = true;
}
else
message = "轮到甲方\n";
}
selected [1] = 1;
if (Adjust (player1)) {
message = "游戏结束:\n甲方获胜!";
GUI.backgroundColor = Color.red;gameover = true;
}
if (Adjust (player2)) {
message = "游戏结束:\n乙方获胜!";gameover = true;
GUI.backgroundColor = Color.red;
}
} else {
message = "操作失败:\n这个地方已经有棋子了!";
}
// This code is executed when the Button is clicked
}
if (GUI.Button (new Rect (20,115,80,80),string4)) {
if (gameover)
return;
if (selected [4] == 0) {
if (count1 <= count2) {
string4 = "甲方";
player1 [4] = 1;
count1++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";gameover = true;
}
else
message = "轮到乙方\n";
}
else {
string4 = "乙方";
player2 [4] = 1;
count2++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";gameover = true;
}
else
message = "轮到甲方\n";
}
selected [4] = 1;
if (Adjust (player1)) {
message = "游戏结束:\n甲方获胜!";
GUI.backgroundColor = Color.red;gameover = true;
}
if (Adjust (player2)) {
message = "游戏结束:\n乙方获胜!";
GUI.backgroundColor = Color.red;gameover = true;
}
} else {
message = "操作失败:\n这个地方已经有棋子了!";
}
}
if (GUI.Button (new Rect (20,210,80,80), string7)) {
if (gameover)
return;
if (selected [7] == 0) {
if (count1 <= count2) {
string7 = "甲方";
player1 [7] = 1;
count1++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";gameover = true;
}
else
message = "轮到乙方\n";
}
else {
string7 = "乙方";
player2 [7] = 1;
count2++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";gameover = true;
}
else
message = "轮到甲方\n";
}
selected [7] = 1;
if (Adjust (player1)) {
message = "游戏结束:\n甲方获胜!";gameover = true;
GUI.backgroundColor = Color.red;
}
if (Adjust (player2)) {
message = "游戏结束:\n乙方获胜!";gameover = true;
GUI.backgroundColor = Color.red;
}
} else {
message = "操作失败:\n这个地方已经有棋子了!";
}
}
//2 column
if (GUI.Button (new Rect (110,20,80,80), string2)) {
if (gameover)
return;
if (selected [2] == 0) {
if (count1 <= count2) {
string2 = "甲方";
player1 [2] = 1;
count1++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";gameover = true;
}
else
message = "轮到乙方\n";
}
else {
string2 = "乙方";
player2 [2] = 1;
count2++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";gameover = true;
}
else
message = "轮到甲方\n";
}
selected [2] = 1;
if (Adjust (player1)) {
message = "游戏结束:\n甲方获胜!";gameover = true;
GUI.backgroundColor = Color.red;
}
if (Adjust (player2)) {
message = "游戏结束:\n乙方获胜!";
GUI.backgroundColor = Color.red;gameover = true;
}
} else {
message = "操作失败:\n这个地方已经有棋子了!";
}
}
if (GUI.Button (new Rect (110,115,80,80), string5)) {
if (gameover)
return;
if (selected [5] == 0) {
if (count1 <= count2) {
string5 = "甲方";
player1 [5] = 1;
count1++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";gameover = true;
}
else
message = "轮到乙方\n";
}
else {
string5 = "乙方";
player2 [5] = 1;
count2++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";gameover = true;
}
else
message = "轮到甲方\n";
}
selected [5] = 1;
if (Adjust (player1)) {
message = "游戏结束:\n甲方获胜!";gameover = true;
GUI.backgroundColor = Color.red;
}
if (Adjust (player2)) {
message = "游戏结束:\n乙方获胜!";gameover = true;
GUI.backgroundColor = Color.red;
}
} else {
message = "操作失败:\n这个地方已经有棋子了!";
}
}
if (GUI.Button (new Rect (110,210,80,80), string8)) {
if (gameover)
return;
if (selected [8] == 0) {
if (count1 <= count2) {
string8 = "甲方";
player1 [8] = 1;
count1++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";gameover = true;
}
else
message = "轮到乙方\n";
}
else {
string8 = "乙方";
player2 [8] = 1;
count2++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";gameover = true;
}
else
message = "轮到甲方\n";
}
selected [8] = 1;
if (Adjust (player1)) {
message = "游戏结束:\n甲方获胜!";gameover = true;
GUI.backgroundColor = Color.red;
}
if (Adjust (player2)) {
message = "游戏结束:\n乙方获胜!";gameover = true;
GUI.backgroundColor = Color.red;
}
} else {
message = "操作失败:\n这个地方已经有棋子了!";
}
}
//3column
if (GUI.Button (new Rect (200,20,80,80), string3)) {
if (gameover)
return;
if (selected [3] == 0) {
if (count1 <= count2) {
string3 = "甲方";
player1 [3] = 1;
count1++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";gameover = true;
}
else
message = "轮到乙方\n";
}
else {
string3 = "乙方";
player2 [3] = 1;
count2++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";gameover = true;
}
else
message = "轮到甲方\n";
}
selected [3] = 1;
if (Adjust (player1)) {
message = "游戏结束:\n甲方获胜!";GUI.backgroundColor = Color.red; gameover = true; }
if (Adjust (player2)) {
message = "游戏结束:\n乙方获胜!";GUI.backgroundColor = Color.red;gameover = true;
}
} else {
message = "操作失败:\n这个地方已经有棋子了!";
}
}
if (GUI.Button (new Rect (200,115,80,80), string6)) {
if (gameover)
return;
if (selected [6] == 0) {
if (count1 <= count2) {
string6 = "甲方";
player1 [6] = 1;
count1++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";gameover = true;
}
else
message = "轮到乙方\n";
}
else {
string6 = "乙方";
player2 [6] = 1;
count2++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";gameover = true;
}
else
message = "轮到甲方\n";
}
selected [6] = 1;
if (Adjust (player1)) {
message = "游戏结束:\n甲方获胜!";GUI.backgroundColor = Color.red;
gameover = true;
}
if (Adjust (player2)) {
message = "游戏结束:\n乙方获胜!";GUI.backgroundColor = Color.red;
gameover = true;
}
} else {
message = "操作失败:\n这个地方已经有棋子了!";
}
}
if (GUI.Button (new Rect (200,210,80,80), string9)) {
if (gameover)
return;
if (selected [9] == 0) {
if (count1 <= count2) {
string9 = "甲方";
player1 [9] = 1;
count1++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";
gameover = true;
}
else
message = "轮到乙方\n";
}
else {
string9 = "乙方";
player2 [9] = 1;
count2++;
if (count1 + count2 == 9 && !Adjust (player1) && !Adjust (player2)) {
message = "游戏结束:和棋!";
gameover = true;
}
else
message = "轮到甲方\n";
}
selected [9] = 1;
if (Adjust (player1)) {
message = "游戏结束:\n甲方获胜!";GUI.backgroundColor = Color.red;
gameover = true;
}
if (Adjust (player2)) {
message = "游戏结束:\n乙方获胜!";GUI.backgroundColor = Color.red;
gameover = true;
}
} else {
message = "操作失败:\n这个地方已经有棋子了!";
}
}
// End the group we started above. This is very important to remember!
GUI.EndGroup ();
}
}
别有用意
其实小游戏做到这里就可以了(当然做的确实比较简单),但是我还想把它分享给某个女生玩一玩(emmmmmmm,这女生的细节就不多说了,大家心里都有X数),毕竟也是我亲手做的
- 开始改代码
于是我就开始把提示信息做的更好一点,最起码不是甲方乙方,至于具体怎么样,截图在后面 - 发布为exe
这个很简单,进去Unity,File->Building Settings,然后直接点击Build(这个AndroidPhone的名字不用管,我是瞎**取的)
自己在电脑上玩了下,感觉很OK
- 然而没有成功
因为她没电脑…该死,竟然忘了这个事,不过想到Unity好像可以发布为apk文件,又重新尝试 与安卓斗智斗勇
要发布为安卓就麻烦了,先不说Unity刚刚发布的界面要下载好大的安卓Support程序后来才发现要安卓的SDK,这tm就麻烦了,因为官网是进不去的(要翻墙),弄了好就弄到了国内大佬的资源(搬运大法好!)(有同学需要的话可以给我留言)
然后进去SDKmanager,下载发现贼慢,几乎要下载好几天,甚至有时候直接显示连接不到谷歌……
然后找教程发现改一下Host文件就能快很多了(在这里直接搬运一手)
在官网androidsdk下载完成后,实际上我们下载下来的是一个下载器,需要我们在线下载对应的库文件,而这个下载过程由于受大墙的影响,经常会导致下载失败。在没有梯子的情况下,我们可以通过手动的修改host文件,来完成sdk的下载,找到目录C:\Windows\System32\drivers\etc下的hosts文件,增加以下配置:
127.0.0.1 localhost
203.208.46.146 www.google.com
74.125.113.121 developer.android.com
203.208.46.146 dl.google.com
203.208.46.146 dl-ssl.google.com
真的非常有用!!!
折腾了一天差不多该做的都做好了,下载了安卓6.0的SDK,应该比较通用
然后终于第一次发布为SDK成功了!!!
不过,还有很问题,在手机上显示的界面超级小,甚至按钮都没办法点,字就更看不到了,看看代码,应该是设置的像素太少了,毕竟手机ppi比较高,就把代码里所有的宽度高度都乘以四倍,在室友手机上发现大了一点点,又回调为原来的三倍,差不多能够正常玩了
然后我把修改过后的游戏发布为apk发给她之后,她却说不能安装,安装包已损坏…..
!!!
想了好久应该是她手机没有到安卓6.0,于是重新下载了5.0的SDK,在另一个室友的5.0系统的手机上完美运行
然后准备发布的时候,发现Unity却提示失败!?!
之前还弄的好好的,怎么这次就失败了,最怕这种不知道怎么搞的错误,还让我看日志…..我这英语水平也就知道它Failed了
搜了好久搜不到答案,硬着头皮读它的错误日志了,总算看到一句能看懂的话
这句话好像是说路径名有非ASCII字符的样子,自己去看了下,好像真的为了方便把文件夹名字改为中文了,抱着试试的心态改了文件夹名字甚至连项目名都改成英文的了
总算是看到了apk文件生成了
自己又用舍友手机体验了下,感觉没什么大毛病,对了我还把图标和里面按钮的skin改了下,emmmmmmm咱么在这个模块不谈技术只说故事好吧,而且也挺简单的
半夜一点半发给她之后,起床后她试了下是能用的,任务已经完成了,至于后面的事就不用提了…….
现在展示一下这个游戏在手机上运行的界面吧
安装界面
这里的图标和游戏名称是后来改过的,图标是她的QQ头像(emmmmmmmmmmmmmm)
开始玩吧
帮助按钮
消息提示框按钮