【Unity3D游戏开发实战】Unity3D实现休闲类游戏《

家电修理 2023-07-16 19:17www.caominkang.com电器维修

推荐阅读

  • CSDN主页
  • GitHub开源地址
  • Unity3D插件分享
  • 简书地址
  • 我的个人博客
  • QQ群1040082875

大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。

一、前言

写今天这篇文章的缘由,其实是来自于前段时间和粉丝的一个聊天,最近他打算参加游戏创作大赛,问我需要准备学习什么知识,以及参加比赛的注意事项一类

我相信因为热爱游戏而前来投身于U3D学习的粉丝想来不是少数,兴趣可以驱动学习,在完善自己心爱游戏的过程中,要不断的去学习,不断的提高自己。

而参与游戏设计比赛,更是提高自身技术实力、增长眼界见识的优秀途径,在此途中也能遇见不少志同道合的好朋友。

那今天就借此简单的聊一下,制作一个简单游戏需要具备哪些技术栈,以及参加这类比赛需要的知识基础。

并且,还有休闲类游戏《2048》的实战开发内容。

二、游戏开发知识储备

接下来就聊一下做一个游戏需要具备哪些技术栈, 因为只是面对“做出游戏”这个特定需求,所以有些技术没有列举出来,在开发中遇到可以再学习。

2-1、技术栈

Unity3D安装

,学习Unity3D你要安装Unity3D编辑器吧,激活Unity Hub许可证。

分享 几个下载链接
Unity3D中国版官网
Unity3D国际版官网
Unity3D下载链接

,比较推荐是用Unity Hub下载安装

安装后激活许可证,这个网上教程比较多,这里就不赘述了


Unity3D编辑器布局学习

学习Unity3D编辑器,要先熟悉Unity编辑器的布局,比如菜单栏,工具栏在什么位置

Unity入门组件学习

Unity的特色就是面向组件编程,所以对于组件的熟悉是基本的要求。

比较常用的组件有

  • Audio组
    • AudioSource
    • AudioListener
  • Effects组
    • ParticleSystem
    • LineRenderer
    • TrailRenderer
  • Event组
    • EventSystem
    • EventTrigger
    • GraphicRaycaster
  • Layout组
    • RectTransform
    • Canvas
    • CanvasGroup
    • CanvasScaler
    • AspectRatioFitter
    • ContentSizeFitter
    • GridLayoutGroup
    • HorizontalLayoutGroup
    • VerticleLayoutGroup
    • LayoutElement
  • Mesh组
    • MeshFilter
    • MeshRenderer
    • SkinnedMeshRenderer
    • TextMeshPro-Text
  • Miscellaneous组
    • Animator
    • Animation
  • Nevigation组
    • NavMeshAgent
    • NavMeshObstacle
  • Physics2D组
    • Rigidbody2D
    • BoxCollider2D
    • CapsuleCollider2D
    • CircleCollider2D
    • CompositeCollider2D
    • EdgeCollider2D
  • Physics组
    • Rigidbody
    • BoxCollider
    • CapsuleCollider
    • SphereCollider
    • CharacterController
    • TerrainCollider
  • Rendering组
    • Camera
    • CanvasRenderer
    • SpriteRenderer
    • Skybox
    • SortingGroup
    • Light

组件比较多,不需要全部学习,只需要在用到的时候查看一下Unity3D手册即可

Unity3D中文手册https://docs.unity.//current/Manual/index.html

C#语言基础

Unity3D的脚本语言是C#,随意要做好Unity3D开发,C#编程语言肯定要学的。

最基本的面向对象思想,数据类型、流程控制、数组、函数都要有一定的了解。

Unity3D-UGUI

UGUI是Unity3D的UI系统,可以用UGUi搭建界面,然后很多的用户交互逻辑都是在UI上完成的,所以学好UGUI是很有必要的,下面就来看一下UGUI的基本组件

  • Text
  • Image
  • RaImage
  • Button
  • Toggle
  • Slider
  • Scrollbar
  • Dropdon
  • InputField
  • Canvas
  • Panel
  • ScrollVie

数据结构

数据结构是一种具有一定逻辑关系,在计算机中应用某种存储结构,并且封装了相应操作的数据元素的集合。

简单点说就是专门用于数据存储和检索的类。

因为做游戏开发或者其他项目都会用到对数据的操作,而数据结构就是专门用于数据存储和检索的类。

常见的数据结构有

  • 列表List
  • 数组Array
  • 字典Dictionary
  • 栈Stack
  • 队列Queue

的技术栈看着字没有那么多,内容还是很多的,比如说Unity3D的组件、C#脚本语言、UGUI系统,每一块拿出来都是很多的内容,那有没有比较推荐的书籍学习呢?

2-2、推荐学习书籍

《Unity 2017从入门到精通》

,比较推荐的就是官方的《Unity 2017从入门到精通》,这本书是对Unity3D编辑器的知识讲解比较全面,各个方面都会涉及,比如说粒子系统、地形系统、AssetBundle都会涉及。

内容上比较通俗易懂,看这本书可以对Unity的基本操作会有一些了解,还可以查漏补缺,看还有那些方面不够的。

《21天学通C#》

这本书的特点就是,简单易懂,没有那么多深奥的东西,且里面的每一个例子都非常精华,直扑主题。

《图解C#》

这本书利用图文的形式详细的讲述了程序运行时内存的分配状况,这便能让你最一些底层的东西有了一定的了解,这便扩展了你的编程思维。

《C#数据结构》

这本书对于数据结构讲解的非常详细,可以根据书籍和视频配合学习,毕竟难度还是有的。

2-3、比赛规则及个人分析建议

既然本期的主题还是应对比赛,那么我们对于比赛本身也要有相应的了解和针对(也就是所谓的审题),就以粉丝这次要参加的B站游戏设计大赛为例(活动网址https://game.bilibili./aards2022/)

个人分析下来,此次赛事,是通过比赛的方式激发对游戏创作的激情,发掘游戏相关人才、作品、创意,给真正喜欢游戏的人提供平台。

就算是暂时缺少技术能力,有游戏独到创意的人,也有参赛机会,分别以游戏包体、概念演示视频方式参赛,分区评比。

,赛事设有创意人气类奖项,评选交由玩家投票、互动决定。

可以看出,比赛更多着重的是鼓励好创意,也为好创意谋求更多曝光机会。好的创意、作品会得到资源支持,签约发行,作品推广等。

,例如比赛日程和参赛规则之类的也需要注意一下,以适配自己的项目进度和方向。

在规划好日程和作品方向后,下面就实现一个休闲类游戏《2048》,抛砖引玉一下。

三、休闲类游戏《2048》开发实战 3-1、玩法概述

开局是一个4X4棋盘,棋盘中随机出现两个数字,出现的数字为2或4。

玩家通过选择上下左右四个反向,若玩家选择的方向上有相同的数字则合并,若选择的反向上没有相同的数字有空位则移动,可以移动的合并,不可以连续合并。

若棋盘被数字填满,无法进行移动或合并,则游戏失败。

如果棋盘出现2048,则游戏胜利

3-2、实现分析

根据规则,来分析一下游戏的实现。

以向左移动为例

可以看到移动后的规则

  • 相邻的元素值相同则合并,然后末尾补上空元素
  • 开头或中间有空元素就移动到末尾
  • 只合并一次,不会多次合并
3-3、搭建场景

(1)新建项目我用的Unity 2019.4.7f1版本,模板选择2D,设置项目名称和位置

(2)将图片另存为,然后导入到项目中

(3)在Inspector视图中导入设置

(4)分割图片,点击Sprite Editor后,会出现分割窗口,然后点击Slice,选择Grid By Cell Count,点击Apply

分割后

(5)切完后,把图集放到Resources文件夹中,没有就新建一个,Resources文件夹在Unity中有特殊作用,可以通过脚本Resources类进行访问。

PS注意图集的名字2048,稍后代码会用到。

接着将2048_0拖入场景中,重命名为BG,设置排序层Order inLayer为-1,这样背景就总是显示在最下面了

将BG拖入Project视图,做成预制体

同样的操作,将2048_1拖入场景,然后重命名为Card,设置排序层为0,然后做成预制体

将场景中的BG和Card对象删除,我们将在后面使用实例化新建出来。

至此,我们的场景就搭建完成了,下面进行代码的编写。

3-4、实现代码

(1),我们需要创建16个小方格作为背景,新建脚本GameManager.cs,双击打开脚本,编写代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour
{
 public GameObject bgSprite;//背景卡片
 private Vector2 BeginPos = ne Vector2(-1.5f, 1.5f);//差不多在屏幕中间
 private float OffsetX = 1.1f;//xy 加个0.1 有个间隙
 private float OffsetY = 1.1f;

 void Start()
 {
  CreateBG();
 }

 void CreateBG()
 {
  GameObject BG = ne GameObject("BG");//创建空游戏对象作为背景预制体
  for (int i = 0; i < 4; i++)
  {
   for (int j = 0; j < 4; j++)
   {
    Vector2 nePos = ne Vector2(BeginPos.x + j  OffsetX, BeginPos.y - i  OffsetY);
    Instantiate(bgSprite, nePos, Quaternion.identity, BG.transform);
   }
  }
 }
}

将脚本附给Main Camera对象,然后将预制体BG拖到Card脚本组件的BgSprite卡槽中

运行程序

(2)接下来创建一个Card.cs脚本,主要用来管理创建的Card对象,找到Project视图中的Card对象,将Card.cs脚本附加上去

修改Card.cs脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Card : MonoBehaviour
{
 public Sprite[] CardSprites;//读取图集中所有切片
 private string fileName = "2048";//图集的名字
 public int _currentIndex = 0;//当前卡片的显示编号

 void Aake()
 {
  CardSprites = Resources.LoadAll(fileName);
 }


 //根据卡片编号修改SpriteRendere,从而改变卡片的数值
 public void Generate(int index)
 {
  _currentIndex = index;
  GetComponent().sprite = CardSprites[_currentIndex];
 }

 //合并卡片的逻辑
 public void Merge()
 {
  _currentIndex++;
  GetComponent().sprite = CardSprites[_currentIndex];
 }
}

(3)接下来修改GameManager.cs脚本,双击打开脚本,修改代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour
{
 public GameObject card;//卡片对象
 private GameObject[,] cardList = ne GameObject[4, 4];//卡片游戏对象对应的棋盘格子
 private int CardNum = 0;//棋盘格子的卡片计数,用于满格后重新开始游戏

 void Start()
 {
  CreateBG();
  CreateCard();
 }


 void Update()
 {
  if (Input.GetKeyDon(KeyCode.W))//上
  {
   MoveUp();
   CreateCard();
  }
  if (Input.GetKeyDon(KeyCode.S))//下
  {
   MoveUp();
   MoveDon();
  }
  if (Input.GetKeyDon(KeyCode.A))//左
  {
   MoveLeft();
   CreateCard();
  }
  if (Input.GetKeyDon(KeyCode.D))//右
  {
   MoveRight();
   CreateCard();
  }
 }
 
	void CreateBG()
 {
  GameObject BG = ne GameObject("BG");//创建空游戏对象作为背景预制体
  for (int i = 0; i < 4; i++)
  {
   for (int j = 0; j < 4; j++)
   {
    Vector2 nePos = ne Vector2(BeginPos.x + j  OffsetX, BeginPos.y - i  OffsetY);
    Instantiate(bgSprite, nePos, Quaternion.identity, BG.transform);
   }
  }
 }

 void CreateCard()
 {

 }

 void MoveUp()
 {

 }

 void MoveDon()
 {

 }

 void MoveLeft()
 {

 }

 void MoveRight()
 {

 }
}

CreateCard函数的主要实现思路是

  • 每次申城一个卡片时计算当前数组中的卡牌数,如果大于16则游戏重置
  • 否则随机生成坐标点,判断当前当前坐标是否有卡片,直到找到空余位置,实例化卡片
  • 生成对应数字的卡片
	void CreateCard()
 {
  CardNum = 0;
  foreach (var item in cardList)
  {
   if (item)
   {
    CardNum++;
   }
  }
  if (CardNum >= 16)
  {
   ResetGame();
   return;
  }

  int X_index, Y_index = 0;
  do
  {
   X_index = Random.Range(0, 4);
   Y_index = Random.Range(0, 4);
  } hile (cardList[X_index, Y_index]);
  Vector2 nePos = GetPosVector2(X_index, Y_index);

  cardList[X_index, Y_index] = Instantiate(_card, nePos, Quaternion.identity);
  if (Random.Range(0.0f,1.0f)>0.5f)
  {
   cardList[X_index, Y_index].GetComponent().Generate(1);
  }
  else
  {
   cardList[X_index, Y_index].GetComponent().Generate(2);
  }
 }

 public Vector2 GetPosVector2(int x, int y)
 {
  return ne Vector2(BeginPos.x + y  OffsetX, BeginPos.y - x  OffsetY);
 }


 void ResetGame()
 {
  foreach (var card in cardList)
  {
   if (card != null)
   {
    Destroy(card);
   }
   cardList = ne GameObject[4, 4];
  }
 }

(3)接下来就是响应鼠标输入,然后移动卡片了,以向上移动为例,主要逻辑思路如下

  • 遍历卡片数组,寻找存在的卡片
  • 寻找到一个存在的卡片,沿着移动方向上每一个格子做判断,看前面是否有卡片,找到离自己最近的卡片做判断
  • 如果与本身卡片数值一直,则进行Card类中的Merge方法进行合并
  • 否则,将卡片移动到该格子的临近格子

向上移动代码实现如下

	void MoveUp()
 {
  for (int i = 0; i < 4; i++)
  {
   for (int j = 0; j < 4; j++)
   {
    if (cardList[i, j] != null)//当找到其中的卡片后
    {
     GameObject temp = cardList[i, j];//保留该卡片的引用
     int x = i;
     int y = j;
     bool isFind = false;//设置查找标识
     hile (!isFind)
     {
      x--;//根据方向的不同  x--是向上 x++是向下
      if (x < 0 || cardList[x, y])//达到边界或找到卡片后
      {
       isFind = true;
       //判断值是否相同,相同的话合并操作
       if (x >= 0 && cardList[x, y].GetComponent()._currentIndex == cardList[i, j].GetComponent()._currentIndex)
       {
        cardList[x, y].GetComponent().Merge();
        Destroy(cardList[i, j]);
        cardList[i, j] = null;
       }
       else//否则移动即可
       {
        cardList[i, j] = null;
        cardList[x + 1, y] = temp;
        cardList[x + 1, y].transform.position = GetPosVector2(x + 1, y);
       }
      }
     }
    }
   }
  }
 }

向下移动

	void MoveDon()
 {
  for (int i = 0; i < 4; i++)
  {
   for (int j = 0; j < 4; j++)
   {
    if (cardList[i, j] != null)//当找到其中的卡片后
    {
     GameObject temp = cardList[i, j];//保留该卡片的引用
     int x = i;
     int y = j;
     bool isFind = false;//设置查找标识
     hile (!isFind)
     {
      x++;//根据方向的不同  x--是向上 x++是向下
      if (x > 3 || cardList[x, y])//达到边界或找到卡片后
      {
       isFind = true;
       //判断值是否相同,相同的话合并操作
       if (x <= 3 && cardList[x, y].GetComponent()._currentIndex == cardList[i, j].GetComponent()._currentIndex)
       {
        cardList[x, y].GetComponent().Merge();
        Destroy(cardList[i, j]);
        cardList[i, j] = null;
       }
       else//否则移动即可
       {
        cardList[i, j] = null;
        cardList[x - 1, y] = temp;
        cardList[x - 1, y].transform.position = GetPosVector2(x - 1, y);
       }
      }
     }
    }
   }
  }
 }

向左移动

	void MoveLeft()
 {
  for (int i = 0; i < 4; i++)
  {
   for (int j = 0; j < 4; j++)
   {
    if (cardList[i, j] != null)//当找到其中的卡片后
    {
     GameObject temp = cardList[i, j];//保留该卡片的引用
     int x = i;
     int y = j;
     bool isFind = false;//设置查找标识
     hile (!isFind)
     {
      y--;//根据方向的不同  x--是向上 x++是向下
      if (y < 0 || cardList[x, y])//达到边界或找到卡片后
      {
       isFind = true;
       //判断值是否相同,相同的话合并操作
       if (y >= 0 && cardList[x, y].GetComponent()._currentIndex == cardList[i, j].GetComponent()._currentIndex)
       {
        cardList[x, y].GetComponent().Merge();
        Destroy(cardList[i, j]);
        cardList[i, j] = null;
       }
       else//否则移动即可
       {
        cardList[i, j] = null;
        cardList[x, y + 1] = temp;
        cardList[x, y + 1].transform.position = GetPosVector2(x, y + 1);
       }
      }
     }
    }
   }
  }
 }

向右移动

	void MoveRight()
 {
  for (int i = 0; i < 4; i++)
  {
   for (int j = 0; j < 4; j++)
   {
    if (cardList[i, j] != null)//当找到其中的卡片后
    {
     GameObject temp = cardList[i, j];//保留该卡片的引用
     int x = i;
     int y = j;
     bool isFind = false;//设置查找标识
     hile (!isFind)
     {
      y++;//根据方向的不同  x--是向上 x++是向下
      if (y > 3 || cardList[x, y])//达到边界或找到卡片后
      {
       isFind = true;
       //判断值是否相同,相同的话合并操作
       if (y <= 3 && cardList[x, y].GetComponent()._currentIndex == cardList[i, j].GetComponent()._currentIndex)
       {
        cardList[x, y].GetComponent().Merge();
        Destroy(cardList[i, j]);
        cardList[i, j] = null;
       }
       else//否则移动即可
       {
        cardList[i, j] = null;
        cardList[x, y - 1] = temp;
        cardList[x, y - 1].transform.position = GetPosVector2(x, y - 1);
       }
      }
     }
    }
   }
  }
 }

运行游戏,就可以愉快的玩耍了

到这一步,我们就完成了《2048》游戏的核心代码实现,我们的代码只有满格后重新开始游戏的判断,没有游戏完成的判断,下面加一个游戏成功的代码,继续修改GameManager.cs脚本

	void CreateCard()
 {
  CardNum = 0;
  foreach (var item in cardList)
  {
   if (item)
   {
    CardNum++;
   }
  }
  if (CardNum >= 16)
  {
   ResetGame();
   return;
  }

  int X_index, Y_index = 0;
  do
  {
   X_index = Random.Range(0, 4);
   Y_index = Random.Range(0, 4);
  } hile (cardList[X_index, Y_index]);
  Vector2 nePos = GetPosVector2(X_index, Y_index);

  cardList[X_index, Y_index] = Instantiate(_card, nePos, Quaternion.identity);
  if (Random.Range(0.0f,1.0f)>0.5f)
  {
   cardList[X_index, Y_index].GetComponent().Generate(1);
  }
  else
  {
   cardList[X_index, Y_index].GetComponent().Generate(2);
  }
  SueedGame();
 }
	void SueedGame()
 {
  foreach (var item in cardList)
  {
   if (item.GetComponent()._currentIndex >= 11)
   {
    Debug.Log("游戏成功");
    break;
   }
  }
  ResetGame();
 }

整体GameManager.cs脚本代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour
{
 public GameObject bgSprite;//背景卡片
 private Vector2 BeginPos = ne Vector2(-1.5f, 1.5f);//差不多在屏幕中间
 private float OffsetX = 1.1f;//xy 加个0.1 有个间隙
 private float OffsetY = 1.1f;

 public GameObject _card;//卡片对象
 private GameObject[,] cardList = ne GameObject[4, 4];//卡片游戏对象对应的棋盘格子
 private int CardNum = 0;//棋盘格子的卡片计数,用于满格后重新开始游戏

 void Start()
 {
  CreateBG();
  CreateCard();
  CreateCard();
 }

 void Update()
 {
  if (Input.GetKeyDon(KeyCode.W))//上
  {
   MoveUp();
   CreateCard();
  }
  if (Input.GetKeyDon(KeyCode.S))//下
  {
   MoveDon();
   CreateCard();
  }
  if (Input.GetKeyDon(KeyCode.A))//左
  {
   MoveLeft();
   CreateCard();
  }
  if (Input.GetKeyDon(KeyCode.D))//右
  {
   MoveRight();
   CreateCard();
  }
 }

 void CreateBG()
 {
  GameObject BG = ne GameObject("BG");//创建空游戏对象作为背景预制体
  for (int i = 0; i < 4; i++)
  {
   for (int j = 0; j < 4; j++)
   {
    Vector2 nePos = ne Vector2(BeginPos.x + j  OffsetX, BeginPos.y - i  OffsetY);
    Instantiate(bgSprite, nePos, Quaternion.identity, BG.transform);
   }
  }
 }

 void CreateCard()
 {
  CardNum = 0;
  foreach (var item in cardList)
  {
   if (item)
   {
    CardNum++;
   }
  }
  if (CardNum >= 16)
  {
   ResetGame();
   return;
  }

  int X_index, Y_index = 0;
  do
  {
   X_index = Random.Range(0, 4);
   Y_index = Random.Range(0, 4);
  } hile (cardList[X_index, Y_index]);
  Vector2 nePos = GetPosVector2(X_index, Y_index);

  cardList[X_index, Y_index] = Instantiate(_card, nePos, Quaternion.identity);
  if (Random.Range(0.0f,1.0f)>0.5f)
  {
   cardList[X_index, Y_index].GetComponent().Generate(1);
  }
  else
  {
   cardList[X_index, Y_index].GetComponent().Generate(2);
  }
  SueedGame();
 }

 public Vector2 GetPosVector2(int x, int y)
 {
  return ne Vector2(BeginPos.x + y  OffsetX, BeginPos.y - x  OffsetY);
 }


 void ResetGame()
 {
  foreach (var item in cardList)
  {
   if (item != null)
   {
    Destroy(item);
   }
   cardList = ne GameObject[4, 4];
  }
 }

 void SueedGame()
 {
  foreach (var item in cardList)
  {
   if (item.GetComponent()._currentIndex >= 11)
   {
    Debug.Log("游戏成功");
    break;
   }
  }
  ResetGame();
 }

 void MoveUp()
 {
  for (int i = 0; i < 4; i++)
  {
   for (int j = 0; j < 4; j++)
   {
    if (cardList[i, j] != null)//当找到其中的卡片后
    {
     GameObject temp = cardList[i, j];//保留该卡片的引用
     int x = i;
     int y = j;
     bool isFind = false;//设置查找标识
     hile (!isFind)
     {
      x--;//根据方向的不同  x--是向上 x++是向下
      if (x < 0 || cardList[x, y])//达到边界或找到卡片后
      {
       isFind = true;
       //判断值是否相同,相同的话合并操作
       if (x >= 0 && cardList[x, y].GetComponent()._currentIndex == cardList[i, j].GetComponent()._currentIndex)
       {
        cardList[x, y].GetComponent().Merge();
        Destroy(cardList[i, j]);
        cardList[i, j] = null;
       }
       else//否则移动即可
       {
        cardList[i, j] = null;
        cardList[x + 1, y] = temp;
        cardList[x + 1, y].transform.position = GetPosVector2(x + 1, y);
       }
      }
     }
    }
   }
  }
 }

 void MoveDon()
 {
  for (int i = 0; i < 4; i++)
  {
   for (int j = 0; j < 4; j++)
   {
    if (cardList[i, j] != null)//当找到其中的卡片后
    {
     GameObject temp = cardList[i, j];//保留该卡片的引用
     int x = i;
     int y = j;
     bool isFind = false;//设置查找标识
     hile (!isFind)
     {
      x++;//根据方向的不同  x--是向上 x++是向下
      if (x > 3 || cardList[x, y])//达到边界或找到卡片后
      {
       isFind = true;
       //判断值是否相同,相同的话合并操作
       if (x <= 3 && cardList[x, y].GetComponent()._currentIndex == cardList[i, j].GetComponent()._currentIndex)
       {
        cardList[x, y].GetComponent().Merge();
        Destroy(cardList[i, j]);
        cardList[i, j] = null;
       }
       else//否则移动即可
       {
        cardList[i, j] = null;
        cardList[x - 1, y] = temp;
        cardList[x - 1, y].transform.position = GetPosVector2(x - 1, y);
       }
      }
     }
    }
   }
  }
 }

 void MoveLeft()
 {
  for (int i = 0; i < 4; i++)
  {
   for (int j = 0; j < 4; j++)
   {
    if (cardList[i, j] != null)//当找到其中的卡片后
    {
     GameObject temp = cardList[i, j];//保留该卡片的引用
     int x = i;
     int y = j;
     bool isFind = false;//设置查找标识
     hile (!isFind)
     {
      y--;//根据方向的不同  x--是向上 x++是向下
      if (y < 0 || cardList[x, y])//达到边界或找到卡片后
      {
       isFind = true;
       //判断值是否相同,相同的话合并操作
       if (y >= 0 && cardList[x, y].GetComponent()._currentIndex == cardList[i, j].GetComponent()._currentIndex)
       {
        cardList[x, y].GetComponent().Merge();
        Destroy(cardList[i, j]);
        cardList[i, j] = null;
       }
       else//否则移动即可
       {
        cardList[i, j] = null;
        cardList[x, y + 1] = temp;
        cardList[x, y + 1].transform.position = GetPosVector2(x, y + 1);
       }
      }
     }
    }
   }
  }
 }

 void MoveRight()
 {
  for (int i = 0; i < 4; i++)
  {
   for (int j = 0; j < 4; j++)
   {
    if (cardList[i, j] != null)//当找到其中的卡片后
    {
     GameObject temp = cardList[i, j];//保留该卡片的引用
     int x = i;
     int y = j;
     bool isFind = false;//设置查找标识
     hile (!isFind)
     {
      y++;//根据方向的不同  x--是向上 x++是向下
      if (y > 3 || cardList[x, y])//达到边界或找到卡片后
      {
       isFind = true;
       //判断值是否相同,相同的话合并操作
       if (y <= 3 && cardList[x, y].GetComponent()._currentIndex == cardList[i, j].GetComponent()._currentIndex)
       {
        cardList[x, y].GetComponent().Merge();
        Destroy(cardList[i, j]);
        cardList[i, j] = null;
       }
       else//否则移动即可
       {
        cardList[i, j] = null;
        cardList[x, y - 1] = temp;
        cardList[x, y - 1].transform.position = GetPosVector2(x, y - 1);
       }
      }
     }
    }
   }
  }
 }
}

至此,我们的《2048》游戏就已经完成了,愉快的玩耍吧。

3-5、源代码下载

https://donload.csdn./donload/q764424567/85013848

四、

这篇文章,讲解了制作游戏的技术栈,以及推荐的学习书籍。

并且介绍了游戏创作大赛的比赛规则,在实现了《2048》游戏。

总体来说,实现这个游戏的难度不大,主要是对数组的操作,以及对于SpriteRenderer组件切换sprite的操作。

所以对于游戏开发不要觉得太难就停滞不前,试着去做,只有在路上,才会距离目标越来越近。


你的点赞就是对博主的支持,有问题记得留言

博主还有跟多宝藏文章等待你的发掘哦

专栏方向简介Unity3D开发小游戏小游戏开发教程分享一些使用Unity3D引擎开发的小游戏,分享一些制作小游戏的教程。Unity3D从入门到进阶入门从自学Unity中获取灵感,从零开始学习Unity的路线,有C#和Unity的知识。Unity3D之UGUIUGUIUnity的UI系统UGUI全解析,从UGUI的基础控件开始讲起,然后将UGUI的原理,UGUI的使用全面教学。Unity3D之读取数据文件读取使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。Unity3D之数据集合数据集合数组集合数组、List、字典、堆栈、链表等数据集合知识分享。Unity3D之VR/AR(虚拟仿真)开发虚拟仿真博主工作常见的虚拟仿真需求进行案例讲解。Unity3D之插件插件主要分享在Unity开发中用到的一些插件使用方法,插件介绍等Unity3D之日常开发日常记录主要是博主日常开发中用到的,用到的方法技巧,开发思路,代码分享等Unity3D之日常BUG日常记录记录在使用Unity3D编辑器开发项目过程中,遇到的BUG和坑,让后来人可以有些参考。

Copyright © 2016-2025 www.caominkang.com 曹敏电脑维修网 版权所有 Power by