12901人加入学习
(90人评价)
Unity2D 中级案例-甜品消消乐(Unity2017.2)

制作于2018年1月6日

价格 免费

特殊甜品的产生

如果消除到4个,可以在被消除的4个甜品的随机一个位置随机生成一个行消除或列消除的甜品

[展开全文]

public struct SweetPrefab { public SweetType type; public GameObject prefab; int num; private int x; }

//标记为public的字段才会显示在Inpector面板中

[展开全文]

行匹配列表

列匹配列表

完成匹配列表

行匹配

如果匹配的甜品有三个或者以上(if(matchRowSweet.count>3)),那么我们就应该加入行匹配列表,如果我们行匹配列表中存在三个或者以上甜品,那么我们就应该依次队每一个甜品进行列匹配。如果存在列匹配的甜品个数在2个或者以上的时候(如果没达到2个 清除列列表),我们就把这几个甜品加入到我们列匹配列表中,最后我们把全部满足条件的甜品放在我们的完成匹配列表中,如果行匹配之后,我们完成匹配列表中元素个数小于三  将三个列表清空

列匹配同理

[展开全文]

填充的本质:决定某个甜品对象往哪里移动:

目的地: 正下方?  左下方?   右下方?

优先前往正下方,其次考虑左下方与右下方。

 

[展开全文]

每一个甜品遍历左下方正下方与右下方看是否为空,以某甜品为例右下方为空,此时让空物体的下一个甜品往上遍历,如果空甜品上方物体可以移动则可以让甜品往下移动(问题)

[展开全文]

(1)新建2D项目

(2)导入素材包

(3)在Asserts下新建文件夹

其中Animation存放动画,GameResources是导入的资源文件夹。Prefabs存放预制。Scenes存放场景。Scripts存放脚本。

(4)新建 Create Empty,游戏物体用于甜品的交互,移动,特效等,在模型层上进行控制。重命名为NormalSweetPrefab。

GameManager下新建2D 的Sprite,重命名为sweet,用于控制甜品的渲染。然后将图标托给Sprite,发现较大。新建一个3D的Cube,默认为一个单位,调整Sprite的大小与Cube大致相同。

最后将预制体NormalSweetPrefab拖到Prefabs文件夹内。

(5)ctrl+D复制NormalSweetPrefab,建立格子背景预制。格子背景一经实例化创建出来,位置和大小就没有变化。所以不比分模型层和渲染层。删除渲染层。重命名为Grid。根据需求调整大小。最后将层级改为-1.

最后将预制体Grid拖到Prefabs文件夹内。

 

 

 

[展开全文]

游戏管理的创建,巧克力的生成

 

(1)创建背景

新建2D的Sprite,将图片拖给它。调整图片大小覆盖摄像机。重命名为Background。

(2)游戏管理

控制整个游戏的运行,甜品的产生、消除等。右键Create Empty,重命名为GameManager。

然后在其身上挂一个同名的脚本。即GameManager.cs。将脚本拖到Scripts文件夹下。

(3)保存场景

Ctrl+S保存场景,命名为Game,将其拖到Scenes文件夹下。

(4)编辑脚本

双击GameManager.cs脚本,进行VS编辑。

做成单例模式。

    // 单例
    private static GameManager _instance;  // ctr+r+e快捷键构建GET SET
    public static GameManager Instance
    {
        get
        {
            return _instance;
        }

        set
        {
            _instance = value;
        }
    }

 

所有东西开始前实例化GameManager。即最先初始化。

private void Awake()
    {
        _instance = this;
    }

定义行列数。

// 大网格的行列数
public int xColumn;
public int yRow;

然后进入unity,点击GameManager,在Inspector面板上可以设置行列数。

定义网格背景。

// 地图网格背景对象
public GameObject gridPrefab;

然后在unity的Inspector面板上将创建的Grid预制托给它。

整个地图实例化网格背景

在Start()方法中:

// 地图的实例化
        for (int x = 0; x < xColumn; x++)
        {
            for (int y = 0; y < yRow; y++)
            {
                // 实例化棋子的背景(地图的实例化)
                GameObject chessBg = Instantiate(gridPrefab, new Vector3(x,y,0),Quaternion.identity);
                // 使chess父对象为GameManager
                chessBg.transform.SetParent(transform);
            }
        }

棋子背景产生了,但位置不正确。下节课纠正位置。

修改背景层级为-2,位于最下方。

 

[展开全文]

甜品的类型枚举,结构体,字典的创建

 

(1)枚举类型。

// 棋子的种类
    public enum ChessType
    {
        EMPTY,              // 空
        NORMAL,             // 一般类型
        BARRIER,            // 障碍
        ROW_CLEAR,          // 行消除
        COLUMN_CLEAR,       // 列消除
        RAINBOWCHESS,       // 彩虹
        COUNT               // 标记类型
    }

(2)预制体字典。

// 棋子预制体的字典,我们可以通过棋子的种类来得到对应的棋子游戏物体
    public Dictionary<ChessType, GameObject> chessPrefabDict;

(3)定义结构体使其显示在unity的inspector面板中。

// 结构体可序列化,可在unity中自由修改
    [System.Serializable]
    public struct ChessPrefab
    {
        public ChessType type;
        public GameObject prefab;
    }

(4)结构体数组,存储所有棋子的类型,使其显示在unity的inspector面板中,可以进行修改。

// 结构体数组,
    public ChessPrefab[] chessPrefabs;

(5)预制体字典的实例化。将结构体中的值赋给字典。

在Start方法中。

// 字典的实例化
        chessPrefabDict = new Dictionary<ChessType, GameObject>();
        for (int i = 0; i < chessPrefabs.Length; i++)
        {
            if (!chessPrefabDict.ContainsKey(chessPrefabs[i].type))
            {
                // 传入键值
                chessPrefabDict.Add(chessPrefabs[i].type, chessPrefabs[i].prefab);
            }
        }

 

[展开全文]

(1)甜品数组

// 棋子数组,存放生成的棋子,用于后续操作
    private GameChess[,] chesses;

(2)2层循环产生甜品

代码

(3)自定义甜品类:为了对甜品进行操作(移动、消除、动画播放、自身属性)。因此写一个甜品的基础脚本。

代码

(4)自定义甜品类初始化

代码

 

 

 

[展开全文]

(1)将写好的自定义基础脚本挂载到预制体上。

(2)使用

// 棋子数组,存放生成的棋子,用于后续操作
    private GameChess[,] chesses;
// 初始化界面,产生棋子
代码

 

[展开全文]

新建移动脚本并将其挂载到预制上。

 

(1)移动算法实现:

  • 将新位置的newX赋值给sweet.X。
  • 将新位置的newY赋值给sweet.Y。
  • 更新位置:sweet .transform.position = sweet .gameManager.CorrectPosition(newX, newY);

(2)在自定义基础脚本里面添加一些东西。

// 棋子移动组件
    private MovedChess movedComponent;
    public MovedChess MovedComponent
    {
        get
        {
            return movedComponent;
        }
    }
// 判断棋子是否可以移动
    public bool CanMove()
    {
        return movedComponent != null;
    }

在上方加一个判断,是否能够更改x,y的值。

public int X
    {
        get
        {
            return x;
        }

        set
        {
            if (CanMove())
            {
                x = value;
            }   
        }
    }
    public int Y
    {
        get
        {
            return y;
        }

        set
        {
            if (CanMove())
            {
                y = value;
            }
 
        }
    }

 

 

[展开全文]

在Awake方法里为移动组件赋值。

movedComponent = GetComponent<MovedChess>();

 

[展开全文]

新建一个脚本ColorChess.cs来进行甜品不同类型的生成。由于GameManager.cs中已经定义的甜品的类型,注意这里是消除的类型(为了实现特殊消除)。因此这里为了生成不同样式的甜品,认为生成不同颜色的甜品。

[展开全文]

删除GameManager.cs里中Update中的return;可以解决结算界面分数与实际所得分数不同的问题。

 

饼干消除算法:在饼干的周围有消除就把饼干一起消除。遍历消除的每一个甜品的四周,看是否有障碍物。有就消除掉。

[展开全文]

1.解决旋转特效出现停顿的方法:

做一个旋转特效的时候出现停顿,原因是unity动画自动是曲线会有平滑作用,想要匀速就要改成直线

方法:

点击key右键改变both tangents改变成linear即可,所有的key都要改变

[展开全文]

1为什么只有行遍历不满足才列遍历

2

[展开全文]

授课教师

SiKi学院老师

课程特色

图文(1)
下载资料(1)
视频(49)