那么问题来了,如何定义一个 Class 呢?
首先我们要知道,这个 Class 下面需要涵盖哪些东西 比如枪的名字,攻击力,冷却时间,描述等所以我们可以把这里的 Class 理解为一种整体的描述 using System.Collections; using System.Collections.Generic; using UnityEngine; public class Weapon // 创建一个武器的类,这里不需要继承 MonoBehaviour { public string name; public int attack; public float coolDown; public string description; } public class Player : MonoBehaviour { public Weapon smallGun; // 创建一个变量,类型为武器 public Weapon bigGun; // Start is called before the first frame update void Start() { smallGun = new Weapon(); // 实例化,即武器被实际创建出来 smallGun.name = "Mini"; // 设定名字 smallGun.attack = 2; // 攻击力 smallGun.coolDown = 0.1f; // 冷却时间 smallGun.description = "It's a small gun!"; // 描述 bigGun = new Weapon() { name = "Bob", attack = 20, coolDown = 2.2f, description = "It's a very big gun!" }; // 也可以通过这种方式实例化的时候同时设定属性 } // Update is called once per frame void Update() { } }注意,在 C# 中,也可以在一个 Class 中创建新的 Class。
上面的写法看起来还是比较复杂,我们还可以用构造函数使得写法更清晰明了:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Weapon // 创建一个武器的类,这里不需要继承 MonoBehaviour { public string name; public int attack; public float coolDown; public string description; public Weapon(string name, int attack, float coolDown, string description)// 构造函数 { this.name = name; this.attack = attack; this.coolDown = coolDown; this.description = description; } } public class Player : MonoBehaviour { public Weapon smallGun; // 创建一个变量,类型为武器 public Weapon bigGun; // Start is called before the first frame update void Start() { smallGun = new Weapon("Mini", 2, 0.1f, "It's a small gun!"); // 实例化,并设定属性 bigGun = new Weapon("Bob", 20, 2.2f, "It's a very big gun!"); // 实例化,并设定属性 } // Update is called once per frame void Update() { } }构造函数,就是在实例化一个 Class 的时候运行的代码,注意构造函数的名字需要和 Class 的名字相同。
我们还可以直接调用显示相应的信息:Debug.Log(smallGun.name);
这样在游戏中,我们就可以换武器了!
如何为一个 RPG 游戏创建一个道具的数据库
我们需要设计一个 Class 来定义 item首先创建一个 C# 脚本,命名为 Item
这里可以把 : MonoBehaviour 删除,因为这个脚本不需要挂载到游戏对象下面假设我们每个道具有 3 个属性:id,名字,描述 using System.Collections; using System.Collections.Generic; using UnityEngine; public class Item { public int id; public string name; public string description; public Item() { // 空的构造函数,用于初始化空的道具 // 这里多个构造函数是允许的 // 即我们实例化的时候会发现两种构造形式,一种不需要传入参数,一种需要 3 个参数 } public Item(int id,string name,string description) { this.id = id; this.name = name; this.description = description; } } 然后我们再创建一个 C# 脚本,命名为 ItemDatabase 这个 Class 是继承于 MonoBehaviour 的 using System.Collections; using System.Collections.Generic; using UnityEngine; public class ItemDatabase : MonoBehaviour { // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } } 再随便创建一个空的游戏对象,命名为 ItemDatabase 把 ItemDatabase 脚本挂载到这个游戏对象下面现在我们想要创建一个道具:一把剑
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ItemDatabase : MonoBehaviour { public Item sword; public Item Axe; // Start is called before the first frame update void Start() { sword = new Item(0, "sword", "It's a sword"); Axe = new Item(); // 由于有两种构造函数,这里可以选择先生成再赋值 Axe.id = 1; Axe.name = "axe"; Axe.description = "It's great!"; } // Update is called once per frame void Update() { } }我们也可以把创建道具的过程提取出来放置到一个函数中。
Unity 中还有一个特殊功能叫做 serialization,即可以让我们创建的 Class 在 inspector 中可见需要在我们创建的 Class 前面加上语句:[System.Serializable]
using System.Collections; using System.Collections.Generic; using UnityEngine; [System.Serializable] public class Item { public int id; public string name; public string description; public Item() { // 空的构造函数,用于初始化空的道具 // 这里多个构造函数是允许的 // 即我们实例化的时候会发现两种构造形式,一种不需要传入参数,一种需要 3 个参数 } public Item(int id,string name,string description) { this.id = id; this.name = name; this.description = description; } }保存脚本后,进入 unity,可以看到 inspector 中的脚本组件下面已经显示了 sword 和 axe
这时候我们甚至可以直接在 inspector 中对不同的属性进行设定
这个时候我们可以有更加灵活的编写方式,修改 ItemDatabase 的脚本:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ItemDatabase : MonoBehaviour { public Item[] items; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } }这个时候回到 unity 中,我们可以任意定义想要创建几个武器(比如20个),并输入每个武器的属性。
这里有个小技巧:
using System.Collections; using System.Collections.Generic; using UnityEngine; [System.Serializable] public class Item { public string name; // 把名字放在第一个属性 public int id; public string description; public Sprite icon; // 设定道具图标 public Item() { // 空的构造函数,用于初始化空的道具 // 这里多个构造函数是允许的 // 即我们实例化的时候会发现两种构造形式,一种不需要传入参数,一种需要 3 个参数 } public Item(int id,string name,string description) { this.id = id; this.name = name; this.description = description; } }如果我们把 name 放在第一个属性,那么进入 unity 中编辑每个 item 的名字,Element 2这样的编号就自动会变成 item 的名字!其实只要第一个属性是字符串就会有这样的效果,但是通常我们会将名字放在第一个位置,而不是描述或者其他的属性。
使用 public Sprite icon; 在 unity 中可以拖动赋值道具显示图标。
在脚本中,我们可以调取这些 unity 中设定的武器的具体信息:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ItemDatabase : MonoBehaviour { public Item[] items; // Start is called before the first frame update void Start() { Debug.Log(items[1].name); // 显示 1 号武器的名字 } // Update is called once per frame void Update() { } }首先建立一个脚本,定义角色的类:
using System.Collections; using System.Collections.Generic; using UnityEngine; [System.Serializable] public class Character // 记住这里不能继承 MonoBehaviour,否则会出错 { public string name; public int age; public string occupation; public int attack; public int defence; public int magic; public Character(string name,int age,string occupation,int attack, int defence, int magic) { this.name = name; this.age = age; this.occupation = occupation; this.attack = attack; this.defence = defence; this.magic = magic; } }创建一个空的游戏对象,定义为 CharacterDatabase,在其下面挂载数据库脚本:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CharacterDatabase : MonoBehaviour { public Character[] characters; // Start is called before the first frame update void Start() { foreach(var item in characters) { Debug.Log("Name: "+item.name+" Age: "+item.age); // 打印所有角色的名字和年龄 } } // Update is called once per frame void Update() { } }在 unity 中将角色个数设定为 3,然后输入 3 个角色的属性。
运行游戏后,即可打印出这 3 个角色的名字和年龄。
创建一个魔法的类:
using System.Collections; using System.Collections.Generic; using UnityEngine; [System.Serializable] public class Magic { public string name; // 魔法名字 public int level; // 魔法等级 public int damage; // 魔法伤害 public int exp; // 魔法熟练度 public Magic(string name,int level, int damage,int exp) { this.name = name; this.level = level; this.damage = damage; this.exp = exp; } public void Cast() // 在该类下面设置一个释放魔法的方法 { Debug.Log("Cast: " + name); // 释放魔法 } }创建一个 cube 游戏对象,命名为 Magician,挂载一个同名的脚本:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Magician : MonoBehaviour { public Magic[] magics; private int _id; // Start is called before the first frame update void Start() { magics = new Magic[3]; magics[0] = new Magic("Fire", 1, 10, 0); magics[1] = new Magic("Ice", 1, 20, 0); magics[2] = new Magic("Wind", 1, 30, 0); _id = 0; //设置默认魔法 Debug.Log("You are using: " + magics[_id].name); } // Update is called once per frame void Update() { if (Input.GetKeyDown(KeyCode.Q)) { _id = 0; // 按下 Q 切换到第一个魔法 Debug.Log("You are using: " + magics[_id].name); } else if (Input.GetKeyDown(KeyCode.W)) { _id = 1; // 按下 W 切换到第二个魔法 Debug.Log("You are using: " + magics[_id].name); } else if (Input.GetKeyDown(KeyCode.E)) { _id = 2; // 按下 E 切换到第三个魔法 Debug.Log("You are using: " + magics[_id].name); } if (Input.GetKeyDown(KeyCode.Space)) { magics[_id].Cast(); // 释放魔法 magics[_id].exp += 20; // 每次释放增加 20 点熟练度 if (magics[_id].exp == 100) // 熟练度达到 100 { magics[_id].level += 1; // 该魔法等级提升 magics[_id].damage = magics[_id].damage * magics[_id].level; // 伤害提升 magics[_id].exp = 0; // 熟练度回到 0 } } } }