当前位置:   article > 正文

【Unity连载】斗兽棋—棋类游戏开发演示(1)_unity 围棋

unity 围棋

序言

“黄梅时节家家雨,青草池塘处处蛙。有约不来过夜半,闲敲棋子落灯花。”

“象棋终日乐悠悠,苦被严亲一旦丢。兵卒坠河皆不救,将军溺水一齐休。马行千里随波去,象入三川逐浪游。炮响一声天地震,忽然惊起卧龙愁。”

棋类游戏是最早的“电子游戏”。从开发者的视角来说,虽然棋类游戏的玩法是相对简单的回合制,内容也远没有电子游戏那样复杂;但它们的玩法中的经典元素,却非常适合于游戏开发过程中的入门级和中级训练。具体到使用Unity开发而言,棋类游戏主要依赖基本的编程思想和简易算法来实现,这在游戏开发的早期学习中有着莫大的好处——只需要制作(或者说“复刻”)一款经典棋类游戏,即可接触并掌握游戏开发领域中的许多通用技能,而避免过早地成为只会调用插件和游戏引擎API,缺乏自力更生能力的“调库怪”。

在这篇教程中,请大家跟随Vic的视角,一起来制作一款经典童年棋类游戏——斗兽棋!同时,制作过程中搭建的基本框架,也可以被方便地改造为其它战棋类游戏,例如中国象棋、跳棋、军棋等。

第一章 项目初始

1.1 游戏规则介绍

斗兽棋是一种简单有趣的棋类游戏。

双方各有八只棋子,依强弱顺序为象、狮、虎、豹、狼、狗、猫、鼠。双方轮流走棋,每只动物每次能够走一格,前后左右都可以。

较强的兽可吃较弱的兽,但鼠能吃象而象不能吃鼠;当同类的兽相遇时,主动走棋的一方能够吃掉另一方。

棋盘横七列,纵九行。棋子放在格子中。双方各有三个陷阱和一个兽穴。如果一方的动物进入了对方的兽穴便胜出,任何一方都不能进入自己的兽穴。一只动物若处于对方的陷阱中,则为虚弱状态——对方的任何一只动物都可以把它吃掉。

棋盘中间有两条小河。狮、虎可以横向或纵向跳过河,而且可以直接把对岸的动物吃掉。只有鼠可以下水,在水中的鼠可以阻止狮、虎跳河。鼠可以在水中吃掉对方的鼠,但不能在入水或出水的同时吃子。

1.2 建立项目

新建一个Unity项目(版本:2019.4.10f1),取名为Animal Checker(斗兽棋)。初始你会看到一个名为SampleScene的空场景。此时可以在Assets目录下新建几个文件夹,如Prefabs(预制体)、Scripts(C#代码)、Pictures(图片)等。

这里Vic还建立了一个名为TestField的文件夹,用来在开发过程中暂存各种临时性的零散文件,避免项目文件管理混乱。

1.3 自力更生——对外部代码坚决Say No

正如Vic在序言中所说,本项目的关键在于【自力更生】——除了Unity官方APIC#标准库(.NET Framework)DOTween(可选)之外,不会使用任何外部插件和代码,实现真正意义上的从零开发。

这里要再次强调,在Unity学习阶段,不建议从网上四处搜索,将完成度很高的现成内容拼凑成自己的游戏。这只会给自己带来虚假的自信而非真实的进步,还容易导致自己的项目被大量的错误和警告淹没。

最好不要听信任何【3天教会你制作一款游戏】的缥缈承诺。

1.4 美术资源

这个项目的核心内容只需要用到12张图片资源。分别是

动物棋子8张卡通风格图:象、狮、虎、豹、狼、狗、猫、鼠;

棋盘方格4种类型:普通地面、小河、陷阱、兽穴。

新建一个文件夹Pictures,将这些图片导入其中,图片类型为Sprite。

当然,在实际开发过程中还可以使用更多的美术资源,对游戏的方方面面进行美化。

1.5 导入插件(可选)

为了使行棋时的棋子移动效果平滑美观,在项目的初始会导入DOTween作为动画插件。

DOTween是Unity领域最为高效和安全的插件(可能没有之一),故在这里可以放心使用而不必担心引发问题。如果你希望不引入任何插件,也可以跳过这里并继续,但在之后有关棋子移动的部分,将进行瞬间移动而非平滑移动,有损游戏观感,除此之外没有影响。

在Asset Store中搜索DOTween,可以看到这个插件是免费的,下载并一键导入即可。

导入DOTween后,只需要按照提示弹窗操作即可顺利启用。

配置完成后,DOTween的相关内容会出现在Plugins和Resources文件夹中。

第二章 搭建界面

2.1 搭建棋盘

斗兽棋的棋盘由7x9=63个棋盘方格组成。通过几行编辑器脚本,即可快速地制作出符合要求的棋盘。

在场景中新建一个按钮,清除按钮上的文字,将按钮命名为Square(方格)。重置Square的RectTransform信息,可以看到按钮变成了100x100的正方形。

新建文件夹Editor,在其中创建脚本CreateBoard.cs,内容如下。

  1. using UnityEngine;
  2. using UnityEditor;
  3. public class CreateBoard : MonoBehaviour
  4. {
  5. public static GameObject square;
  6. [MenuItem("棋盘/创建棋盘")]//在Unity顶部工具栏增加选项卡
  7. public static void Create()
  8. {
  9. square = GameObject.Find("Square");//以这个按钮为基准进行复制
  10. for (int col = 0; col < 7; col++)//7列
  11. {
  12. for (int row = 0; row < 9; row++)//9行
  13. {
  14. //棋子边长为100,设定两个棋子的中心点间距为105,这样棋子之间有宽度为5的空隙
  15. float posx = 105 * col;
  16. float posy = 105 * row;
  17. GameObject creation = Instantiate(square, new Vector3(posx, posy, 0), Quaternion.identity);//创建棋盘上的各个棋子
  18. creation.transform.SetParent(GameObject.Find("Canvas").transform);//置于Canvas下
  19. creation.name = $"{col},{row}";//以棋盘坐标的形式,自动为棋子命名
  20. }
  21. }
  22. }
  23. }

保存脚本后,在Unity主界面工具栏选取【棋盘/创建棋盘】,即可一键完成棋盘的搭建。每个棋盘方格的名称,代表了它在棋盘上的坐标。

现在,整理界面。删除Squares按钮,将新创建的各个棋盘方格按钮归拢到一个空物体ChessBoard下,将整个棋盘移动到镜头的中央;找到先前导入的4种棋盘方格图片,按照斗兽棋的棋盘样式张贴到按钮上;调整摄像机背景设置为纯色,不看默认天空盒。

此外,棋盘方格在游戏中是不需要点击反馈效果的,因此我们将全部63个方格上的Button组件的反馈效果设置为None。

脚本CreateBoard.cs的使命已经结束,此时可以删除。

完成以上操作后,棋盘界面的制作全部完成。

2.2 制作棋子

棋子的制作与棋盘方格类似,同样是正方形按钮的形式,长宽设置为90x90,比棋盘方格(100x100)略小;按钮图片采用先前导入的8种动物图片。

全部8种动物的棋子制作完成后,将它们复制一份成为16个棋子,在Image组件上加入适当的颜色滤镜,以便区分蓝方和红方。

最后,为16个棋子手动输入名字,将它们保存为预制体,存放在Prefabs文件夹内。

到这里,斗兽棋游戏所需的游戏界面元素基本上制作完毕,可以开始编写游戏代码,实现斗兽棋所需的功能了。

第三章 构建游戏对象

3.1 坐标

正如围棋用"A15""D13"等表示棋盘上的点,中国象棋用"车四平三""兵五进一"等说法表示棋步的执行;要想实现斗兽棋的游戏功能,首先需要对棋盘上的各个方格进行坐标化处理。

新建代码文件GameBasic.cs,将新文件中的Unity默认内容删除。在这个文件中,我们将对斗兽棋游戏所需的一些基本概念和对象进行定义。

首先写入一个值类型Location。这是一个抽象的结构体类型,用来表达棋盘方格和棋子的【坐标】概念,内容如下:

  1. using UnityEngine;
  2. using System;
  3. # region Location:坐标
  4. /// <summary>
  5. /// 一个棋盘格或棋子的坐标。
  6. /// </summary>
  7. [Serializable]
  8. public struct Location
  9. {
  10. public int x;//横坐标,表示棋盘上的列,范围从0至6
  11. public int y;//纵坐标,表示棋盘上的行,范围从0至8
  12. public Vector2Int Vector => new Vector2Int(x, y);//允许以Unity二维向量形式表示一个棋盘坐标——这能够方便坐标之间距离的计算
  13. public override string ToString()
  14. {
  15. return $"({x},{y})";
  16. }
  17. //IsNear方法:判断两个坐标是否是相邻坐标
  18. public bool IsNear(Location other)
  19. {
  20. if (Vector2Int.Distance(Vector, other.Vector) == 1)
  21. {
  22. return true;
  23. }
  24. return false;
  25. }
  26. public static bool IsNear(Location a, Location b)
  27. {
  28. return a.IsNear(b);
  29. }
  30. //坐标值的合法范围
  31. public const int Xmin = 0;
  32. public const int Xmax = 6;
  33. public const int Ymin = 0;
  34. public const int Ymax = 8;
  35. //IsValid方法:判断一个坐标是否是合法坐标,即位于棋盘范围内的坐标
  36. public bool IsValid()
  37. {
  38. if (x >= Xmin && x <= Xmax && y >= Ymin && y <= Ymax)
  39. {
  40. return true;
  41. }
  42. return false;
  43. }
  44. private static bool IsValid(int x, int y)
  45. {
  46. if (x >= Xmin && x <= Xmax && y >= Ymin && y <= Ymax)
  47. {
  48. return true;
  49. }
  50. return false;
  51. }
  52. //构造函数:使用一组x和y的值创建新坐标
  53. public Location(int x, int y)
  54. {
  55. this.x = x;
  56. this.y = y;
  57. if (!IsValid(x, y))
  58. {
  59. Debug.LogWarning($"正在创建一个超出棋盘范围的方格:({x},{y})");
  60. }
  61. }
  62. public static bool operator ==(Location a, Location b)
  63. {
  64. return a.Vector == b.Vector;
  65. }
  66. public static bool operator !=(Location a, Location b)
  67. {
  68. return a.Vector != b.Vector;
  69. }
  70. public override bool Equals(object obj)
  71. {
  72. return base.Equals(obj);
  73. }
  74. public override int GetHashCode()
  75. {
  76. return base.GetHashCode();
  77. }
  78. }
  79. #endregion

在定义这个Location类型时,我们需要具有一定的预见性,为这个数据类型加入必要的功能,用以满足之后的游戏逻辑编写需要。例如在Location的内部方法中,你可以看到用于判断两个坐标是否相邻的IsNear()方法、用于判断一个坐标是否合法的IsValid()方法,甚至还有重载过的等号==,用以判定两个坐标是否相等。这些方法将会在后续的程序中发挥作用。

3.2 阵营

斗兽棋是由两名玩家进行对战的棋类,棋子分为蓝方和红方;棋盘上的大部分方格是”中立“的,但是陷阱和兽穴则各有所属。因此,我们需要定义【阵营】数据类型。继续在GameBasic.cs中写入代码,用一个枚举类型Camp来定义游戏中的三种阵营: 蓝方红方中立。

  1. #region Camp:阵营
  2. /// <summary>
  3. /// 玩家阵营。
  4. /// </summary>
  5. public enum Camp
  6. {
  7. Neutral, Blue, Red
  8. }
  9. #endregion

3.3 动物种类

斗兽棋中共有8种不同的动物种类,同样适合以枚举类型进行定义。定义一个枚举类型Animal

  1. #region Animal:动物类型
  2. /// <summary>
  3. /// 动物类型
  4. /// </summary>
  5. public enum Animal
  6. {
  7. Rat = 0,
  8. Cat = 1,
  9. Dog = 2,
  10. Wolf = 3,
  11. Leopard = 4,
  12. Tiger = 5,
  13. Lion = 6,
  14. Elephant = 7
  15. }
  16. #endregion

8种动物的枚举数值(0-7)按由弱至强的顺序排列。

3.4 地形类型

棋盘方格的类型分为地面Land小河River陷阱Trap兽穴Cave四种。和前面一样,定义一个枚举类型SquareType,表示棋盘方格的地形种类。

  1. #region SquareType:地形类型
  2. /// <summary>
  3. /// 棋盘方格的地形类型。
  4. /// </summary>
  5. public enum SquareType
  6. {
  7. Land, River, Trap, Cave
  8. }
  9. #endregion

3.5 棋盘方格

有了上述这些抽象性的游戏概念定义,我们就可以来对每个棋盘方格进行具体的定义了。思考一下,如何描述一个棋盘方格呢?

不难想到,一个棋盘方格的属性信息,总共包含坐标地形类型和所属阵营这三项内容。描述起来就像这样:

图中的方格1,是坐标为(0,0)地面方格,阵营为中立

图中的方格2,是坐标为(3,1)陷阱方格,阵营为蓝方;

图中的方格3,是坐标为(3,8)兽穴方格,阵营为红方

(注意:在本项目的棋盘描述中,规定下方为蓝方,左下角的方格坐标为(0,0)。后续内容皆以此为准)

新建脚本Square.cs,定义棋盘方格并实现其功能。这是本项目中的第一个游戏脚本,它将作为组件被挂载在场景中的每一个棋盘方格(按钮)上。

  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. using UnityEditor;
  4. using System;
  5. public class Square : MonoBehaviour
  6. {
  7. public Location location;
  8. public SquareType type;
  9. public Camp camp;
  10. private void Start()
  11. {
  12. GetComponent<Button>().onClick.AddListener(OnSquareClicked);
  13. }
  14. public override string ToString()
  15. {
  16. return $"棋盘方格坐标:{location},地形类型:{type},阵营:{camp}"
  17. }
  18. public void OnSquareClicked()
  19. {
  20. Debug.Log(this);
  21. }
  22. }

将这个组件挂载到之前创建的每一个棋盘方格上。

可以看到,每个方格上的Square组件都有三个可填写的配置项,分别表示对应方格的坐标、地形类型和所属阵营。与2.1小节类似,我们使用编辑器脚本来自动填写这些信息——不过这里的代码稍显繁琐,因此你可以选择不使用脚本,而是手动为63个方格进行填写。

自动填写方格信息的脚本如下——这些内容写在任意C#文件内效果均相同,这里Vic写在了Square.cs的后面。注意需要加入【using System】和【using UnityEditor】指令。

  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. using UnityEditor;
  4. using System;
  5. public class Square : MonoBehaviour
  6. {
  7. public Location location;
  8. public SquareType type;
  9. public Camp camp;
  10. private void Start()
  11. {
  12. GetComponent<Button>().onClick.AddListener(OnSquareClicked);
  13. }
  14. public override string ToString()
  15. {
  16. return $"棋盘方格坐标:{location},地形类型:{type},阵营:{camp}"
  17. }
  18. public void OnSquareClicked()
  19. {
  20. Debug.Log(this);
  21. }
  22. [MenuItem("棋盘/初始化棋盘方格")]
  23. public static void InitSquares()
  24. {
  25. var squares = FindObjectsOfType<Square>();
  26. foreach (var square in squares)
  27. {
  28. //自动填写方格坐标
  29. string name = square.gameObject.name;
  30. string[] locationValues = name.Split(',');
  31. int x = Convert.ToInt32(locationValues[0]);
  32. int y = Convert.ToInt32(locationValues[1]);
  33. square.location = new Location(x, y);
  34. //自动填写方格地形
  35. var location = square.location;
  36. //地形:小河
  37. if ((location.x == 1 || location.x == 2 || location.x == 4 || location.x == 5) && location.y >= 3 && location.y <= 5)
  38. {
  39. square.type = SquareType.River;
  40. }
  41. //地形:兽穴
  42. else if (location.Vector == new Vector2Int(3, 0) || location.Vector == new Vector2Int(3, 8))
  43. {
  44. square.type = SquareType.Cave;
  45. }
  46. //地形:陷阱
  47. else if (location.IsNear(new Location(3, 0)) || location.IsNear(new Location(3, 8)))
  48. {
  49. square.type = SquareType.Trap;
  50. }
  51. //地形:地面
  52. else
  53. {
  54. square.type = SquareType.Land;
  55. }
  56. //自动填写方格阵营
  57. var type = square.type;
  58. //阵营:中立
  59. if (type == SquareType.Land || type == SquareType.River)
  60. {
  61. square.camp = Camp.Neutral;
  62. }
  63. else
  64. {
  65. //阵营:蓝方
  66. if (square.location.y <= 1)
  67. {
  68. square.camp = Camp.Blue;
  69. }
  70. //阵营:红方
  71. else
  72. {
  73. square.camp = Camp.Red;
  74. }
  75. }
  76. }
  77. }
  78. }

保存脚本后,在Unity工具栏选择【棋盘/初始化棋盘方格】选项卡,即可一键完成对所有棋盘方格的信息填写;

此时你可以选中不同的方格,检查Square组件上的信息是否填写正确,是否与棋盘方格的在棋盘上的实际位置匹配,如下图。

检查无误后,即可删去刚刚使用过的临时性脚本内容。

Square.cs中包含了OnSquareClicked方法,用以对棋盘方格的被点击事件作出响应。由于我们的游戏还没有具体功能,所以这个方法的内容暂时只是打印出一条控制台日志。

运行游戏,用鼠标左键单击棋盘上的各个方格,可以看到打印出了若干日志。日志将会显示出你单击的方格的具体信息。

到这里,我们已经以程序的方式将棋盘上的所有格子都纳入了管理,同时还能够对每个格子的被点击事件进行接收,并进行正确的响应。这为我们将要实现的游戏功能打下了非常可靠的基础。

3.6 棋盘

在配置好所有的棋盘方格之后,我们还需要一个针对整个棋盘的管理模块——或者说,一个能够对棋盘上的每个方格进行查询和访问的入口。

添加脚本ChessBoard.cs,用于对棋盘的整体管理。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using System;
  5. public class ChessBoard : MonoBehaviour
  6. {
  7. public static ChessBoard Get = null;
  8. public List<Square> squares;
  9. public Square this[int x, int y]
  10. {
  11. get
  12. {
  13. foreach (Square square in squares)
  14. {
  15. if (square.location.x == x && square.location.y == y)
  16. {
  17. return square;
  18. }
  19. }
  20. return null;
  21. }
  22. }
  23. public Square this[Location location]
  24. {
  25. get
  26. {
  27. return this[location.x, location.y];
  28. }
  29. }
  30. private void Awake()
  31. {
  32. Get = this;
  33. }
  34. }

ChessBoard是一个全局唯一的管理器组件,使用单例模式。这个脚本采用C#的索引机制,实现了对棋盘方格的查询功能。例如,ChessBoard.Get[3,0]表示的就是坐标为(3,0)的蓝方兽穴。

创建游戏物体GameCtrl,再创建它的子物体ChessBoard,挂载ChessBoard组件。

将全部63个棋盘方格上的Square组件填入到ChessBoard组件上的Squares列表中。

和前面的两次自动化操作类似,你既可以编写临时性脚本进行自动填写,也可以手动填写。

到这里,ChessBoard组件配置完成。它扮演的是一个被动接受请求的查询器角色,将在后续的代码中发挥作用。

3.7 棋子

有了完善的棋盘,现在终于可以开始描述和定义棋子了。但与悠然不动的棋盘方格不同,棋子是游戏逻辑中的核心元素,需要承担和执行大量的功能;因此,棋子的相关代码远比前面的内容要复杂,并且需要在开发过程中不断补充更多的功能。

创建脚本Chessman.cs,开始定义棋子。第一个版本的Chessman.cs内容如下。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using System;
  4. using UnityEngine;
  5. using UnityEngine.UI;
  6. using DG.Tweening;//DOTween
  7. public class Chessman : MonoBehaviour
  8. {
  9. public Location location;//棋子的坐标
  10. public Animal animal;//棋子的动物类型
  11. public Camp camp;//棋子的阵营
  12. public override string ToString()
  13. {
  14. return $"棋子坐标:{location} 动物类型:{animal} 阵营:{camp}";
  15. }
  16. /// <summary>
  17. /// 获取当前场上的全部棋子,或者某一方的全部棋子。
  18. /// </summary>
  19. /// <param name="camp">Neutral:查询全部棋子; Blue or Red: 查询一方的全部棋子</param>
  20. /// <returns></returns>
  21. public static List<Chessman> All(Camp camp = Camp.Neutral)
  22. {
  23. List<Chessman> ret = new List<Chessman>();
  24. var chessmen = FindObjectsOfType<Chessman>();
  25. foreach (var chessman in chessmen)
  26. {
  27. if (camp == Camp.Neutral || camp == chessman.camp)
  28. {
  29. ret.Add(chessman);
  30. }
  31. }
  32. return ret;
  33. }
  34. /// <summary>
  35. /// 清除场上的全部棋子。
  36. /// </summary>
  37. public static void ClearAll()
  38. {
  39. var all = All();
  40. for (int i = all.Count - 1; i >= 0; i--)
  41. {
  42. all[i].ExitFromBoard();
  43. }
  44. }
  45. /// <summary>
  46. /// 依照坐标查询,找到位于相应坐标上的棋子。
  47. /// </summary>
  48. /// <param name="location"></param>
  49. /// <returns></returns>
  50. public static Chessman GetChessman(Location location)
  51. {
  52. foreach (var chessman in All())
  53. {
  54. if (chessman.location.Equals(location))
  55. {
  56. return chessman;
  57. }
  58. }
  59. return null;
  60. }
  61. /// <summary>
  62. /// 棋子所在的方格。
  63. /// </summary>
  64. public Square Square => ChessBoard.Get[location];
  65. /// <summary>
  66. /// 初始化棋子
  67. /// </summary>
  68. public void Start()
  69. {
  70. if (camp == Camp.Neutral)
  71. {
  72. Debug.LogError("棋子阵营不能为中立。");
  73. return;
  74. }
  75. MoveTo(location);
  76. GetComponent<Button>().onClick.AddListener(OnChessmanClicked);
  77. }
  78. /// <summary>
  79. /// 使棋子移动到指定坐标。这会删除目标位置上的另一个棋子。
  80. /// </summary>
  81. /// <param name="target">目标坐标</param>
  82. public void MoveTo(Location target)
  83. {
  84. try
  85. {
  86. Square square = ChessBoard.Get[target.x, target.y];//定位目标棋盘格
  87. if (square.Chessman != this)
  88. {
  89. square.RemoveChessman();//删除目标位置上已有的棋子
  90. }
  91. location = target;//修改自身坐标为新的坐标
  92. transform.DOMove(square.transform.position, 0.35f);//执行移动
  93. //transform.position = square.transform.position;//无DOTween时以此替代上一行
  94. }
  95. catch (Exception ex)
  96. {
  97. Debug.LogError($"移动棋子失败.{ex.Message}");
  98. }
  99. }
  100. private void OnChessmanClicked()
  101. {
  102. Debug.Log(this);
  103. }
  104. /// <summary>
  105. /// 使这个棋子退场。
  106. /// </summary>
  107. public void ExitFromBoard()
  108. {
  109. Destroy(gameObject);
  110. }
  111. }

与前面对棋盘方格的定义过程类似,Chessman.cs中包含了描述棋子所需的全部信息(坐标、动物类型、阵营),并包含了棋子所需的一组原始功能。这些功能包括:

·获取当前场上的全部棋子:All()

·获取当前场上某一阵营的全部棋子:All(Camp camp)

·清空场上的全部棋子:ClearAll()

·查询位于某一坐标的棋子:GetChessman(Location location)

·令一个棋子移动到另一坐标:MoveTo(Location target)  如果该位置上有其它棋子,则该棋子将被取代,即“吃掉”。

·令一个棋子退场:ExitFromBoard()

眼下,我们尚未在任何地方调用棋子的这些功能,它们将在后面的章节中发挥作用。

Square.cs也需要进行扩充,以支持棋子的相关功能。

扩充后的Square.cs在棋盘方格与棋子之间建立了联系,能够查询访问移除位于棋盘方格上的棋子。扩充后的内容如下。

  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. public class Square : MonoBehaviour
  4. {
  5. public Location location;
  6. public SquareType type;
  7. public Camp camp;
  8. public Chessman Chessman => Chessman.GetChessman(location);//通过此属性,可以访问位于此方格上的棋子
  9. private void Start()
  10. {
  11. GetComponent<Button>().onClick.AddListener(OnSquareClicked);
  12. }
  13. public override string ToString()
  14. {
  15. return $"棋盘方格坐标:{location},地形类型:{type},阵营:{camp}";
  16. }
  17. public void OnSquareClicked()
  18. {
  19. Debug.Log(this);
  20. }
  21. /// <summary>
  22. /// 移除棋盘方格上的棋子(如果有的话)。
  23. /// </summary>
  24. public void RemoveChessman()
  25. {
  26. if (Chessman != null)
  27. {
  28. Chessman.ExitFromBoard();
  29. }
  30. }
  31. }

在Prefabs文件夹内找到2.2小节中制作的16个棋子预制体,为它们挂载Chessman组件,然后在每个棋子上填写Animal动物类型Camp阵营Location坐标信息,如图。由于只有16个棋子,工作量很小,这里就不需要使用脚本了。

 全部16个棋子的坐标如下表。

目前版本的Chessman.cs包含Start方法,能够将自身直接初始化到预定的坐标位置。

进行测试,将全部16个棋子预制体拖到场景内的Canvas-ChessBoard物体下。

运行游戏,可以看到所有的棋子都在游戏开始时出现在了各自的方格上,可见它们的位置已经成功初始化。

试试用鼠标左键点击蓝猫。与棋盘方格的情况类似,此时将会执行Chessman.cs中的OnSquareClicked方法,在日志中显示相应棋子的介绍信息。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/235872
推荐阅读
相关标签
  

闽ICP备14008679号