抄袭参考文章: 学长博客
Unity hub文件:Assets文件夹
简答题传输门:简答题部分
本次作业基本是看着学长的博客实现的,不过我太菜了,照着抄都跑不动,初次使用unity做游戏,踩了很多坑。代码跟传送门都在上面,在此我就跟大家聊一聊坑点和我的改进。
我主要是在给井字棋多加了弹跳的效果,通过添加模型的材质,增添预设来实现,下面是效果图。
首先,是预设的设置。学长在文章中只说了可以往预设中添加立方体,实际上我们还可以通过给预设中的立方体添加各种组件来让其拥有各种各样的效果。这次我主要加了三种组件:
1.material(材质),在Assets的Resources中创建,然后拖动到预设的立方体中。它可以让你的预设的颜色与花纹花里胡哨起来
2.Rigidbody(刚体),给物体添加质量等物理性质,使其能够下落。在预设组件中点击add Component后,直接搜索即可。
这里额外提一点,不同的物体间要加上碰撞体的组件才可进碰撞,不过组件一开始都会自动创建好碰撞体,也可以根据个人需要调整碰撞体模型和参数。
3.physic material(物理材质),创建方式跟添加方式跟materail一样 ,通过将摩擦力设为0,弹力设为1,可实现完全弹性碰撞,这里我把弹力设为0.7,蹦几下就会停下。
最后你的组件应该是这样的,其中物理性质好像没有具体组件,但不要忘记拖进去。
接下来,就是在游戏运行中添加预设,下面是学长的添加方式,给你要用的棋子模型添加提供游戏对象。不过我一直没搞懂Shader.Find是什么东西,所以用了上面那种提前添加组件的方法,免去了材质的修改。
chess[counter] = Instantiate(Resources.Load("Chess"), grid.transform.position, Quaternion.identity) as GameObject;
//同时我们还可以利用counter来判断回合
chess[counter].GetComponent<Renderer>().material = new Material(Shader.Find(counter%2?material1:material2));
最后,是如何使点击屏幕生成具体的棋子,依旧先看学长的表现方式。
void OnMouseUp(){
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RayCastHit hit;
//判断是否检测到了
if(Physics.RayCast(ray, out hit)){
//画条线看的更清楚
Debug.DrawLine(ray.origin, hit.point);
//既然是射线,那我们获得的肯定是碰撞体了,所以没有碰撞体这个组件的是检测不到的!
GameObject grid = hit.collider.gameObject;
//用一个一维数组保存即可,因为我们不需要知道位置在哪,只需要方便我们销毁就行,用一个counter来记录数量
chess[counter] = Instantiate(Resources.Load("Chess"), grid.transform.position, Quaternion.identity) as GameObject;
//同时我们还可以利用counter来判断回合
chess[counter].GetComponent<Renderer>().material = new Material(Shader.Find(counter%2?material1:material2));
}
}
这里有两个坑点:
1.直接按照学长的方式放置棋子,棋子会直接嵌进棋盘,所以我们要拔高棋子生成的高度。(但不知道为什么,我其中一个位置的数据一直有问题,进行了特判。各位如果位置数据没问题,可删掉)
2.我的脚本是直接放进自然光或摄像头运行的,这样根本没有物体给你进行OnMouseUp,无法调用该函数。所以我把函数放入update中,并使用 if(Input.GetMouseButtonDown(0)) 进行判断。
以下是我的脚本,需要完整的 Assets文件夹可在上方传送门跳转到github
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class cc : MonoBehaviour
{
private GameObject[,] ChessTable = new GameObject[3,3];
private GameObject[,] chess= new GameObject[3,3];
private int[,] state = new int[3,3];
private int counter;
void Start(){
string m1 = "grid1",m2 = "grid2";
for(int i = 0;i < 3;i++){
for(int j = 0;j <3;j++){
ChessTable[i,j] = Instantiate(Resources.Load((i+j)%2==1?m1:m2), new Vector3(i, 0, j), Quaternion.identity) as GameObject;
ChessTable[i,j].transform.parent = this.transform;
}
}
Restart();
}
//
void Restart(){
counter = 0;
for(int i = 0;i < 3;i++)
for(int j = 0;j <3;j++){
state[i,j] = 0;
GameObject.Destroy(chess[i,j]);
}
}
void createchess(){
string m1 = "chess1",m2 = "chess2";
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
//判断是否检测到了
if(Physics.Raycast(ray, out hit)){
//画条线看的更清楚
Debug.DrawLine(ray.origin, hit.point);
//既然是射线,那我们获得的肯定是碰撞体了,所以没有碰撞体这个组件的是检测不到的!
GameObject grid = hit.collider.gameObject;
int x = (int)grid.transform.position.x,y = (int)grid.transform.position.z;
if(grid.transform.position.x>0.9&&grid.transform.position.x<1.1)x = 1;
if(state[x,y]==0){
chess[x,y] = Instantiate(Resources.Load(counter%2==1?m1:m2), new Vector3(x,1,y), Quaternion.identity) as GameObject;
//同时我们还可以利用counter来判断回合
chess[x,y].transform.parent = this.transform;
state[x,y] = counter%2==0?1:-1;
counter += 1;
}
}
}
int judge(){
int win = 0,t;
//主对角线
t = state[0,0];
for(int i = 1;i<=2;i++){
win = t;
if(t != state[i,i]){
win = 0;break;
}
}
if(win==1||win==-1)return win;
//斜对角线
t = state[0,2];
for(int i = 1;i<=2;i++){
win = t;
if(t != state[i,2-i]){
win = 0;break;
}
}
if(win==1||win==-1)return win;
//竖线
for(int j = 0;j<=2;j++){
t = state[0,j];
for(int i = 1;i<=2;i++){
win = t;
if(t != state[i,j]){
win = 0;break;
}
}
if(win==1||win==-1)return win;
}
//横线
for(int j = 0;j<=2;j++){
t = state[j,0];
for(int i = 1;i<=2;i++){
win = t;
if(t != state[j,i]){
win = 0;break;
}
}
if(win==1||win==-1)return win;
}
if(counter==9)return 2;
return 0;
}
void OnGUI(){
//生成一个菜单栏
GUI.Box (new Rect (10, 10, 100, 90), "菜单");
if (GUI.Button (new Rect (20, 40, 80, 20), "新游戏")) {
this.Restart();
}
int r = judge();
if(r==1||r==-1||r==2){//win
string m;
if(r==1)m="你赢了";
else if(r==-1)m = "你输了";
else m = "平局";
GUI.Box (new Rect (Screen.width / 2 - 100, Screen.height / 2 + 50, 200, 100), m);
if (GUI.Button (new Rect (Screen.width / 2 - 80, Screen.height / 2, 160, 20), "重开"))
this.Restart ();
}
}
// Update is called once per frame
void Update()
{
if(Input.GetMouseButtonDown(0))createchess();
}
}