前言
当创建各种Rogue-Lite(肉鸽)风格的游戏时,物品和BUFF效果是非常重要的元素之一。为了更加规范地创建这些物品和BUFF效果,可以使用抽象类来定义不同的BUFF。
那么什么是抽象类呢?他的用法?为什么用它?好处是什么呢?
在Unity中,抽象类是一种特殊的类,它不能被实例化,只能被用作其他类的基类。抽象类通常用于定义一些通用的行为和属性,但并不提供具体的实现细节。其目的是让子类来实现这些抽象方法和属性,以便根据具体的需求进行定制化。
使用抽象类的主要原因是为了实现代码的重用和统一性。抽象类可以定义一些通用的方法和属性,从而避免在多个类中重复编写相似的代码。同时,它也可以作为约定,强制子类实现特定的方法和属性,确保了程序的一致性和可扩展性。
抽象类的主要好处
包括:
- 提供了一种模板化的设计方式,使得代码更易维护和扩展。
- 强制了子类必须实现抽象方法和属性,从而减少了程序出错的可能性。
- 通过抽象类可以实现多态性,使得代码更加灵活和可复用。
在Unity中,经常会用到抽象类来定义一些通用的行为或者规范,例如定义一个抽象的游戏角色类,其中定义了移动、攻击等方法,然后具体的角色类(如玩家角色、敌对角色等)继承并实现这些方法。这样可以保持代码的一致性和可维护性。
总之,抽象类在Unity中的使用可以帮助我们更好地组织和管理代码,提高代码的复用性和可维护性。
定义基类
物品就是
物品BUFF
,下面我都会用物品
作为注释
新增Item,定义一个名为 Item 的物品BUFF抽象类
[System.Serializable] public abstract class Item { // 定义BUFF名称 public abstract string GiveName(); // 定义一个虚方法 Update,其中 player 表示玩家对象,stacks 表示物品的叠加数量(及BUFF层数) public virtual void Update(Player player, int stacks){ } }
新增ItemList,定义物品BUFF列表参数
[System.Serializable] public class ItemList { // 表示物品 public Item item; // 表示名称 public string name; // 表示叠加数量(及BUFF层数) public int stacks; // 构造函数,用于初始化 ItemList 对象 public ItemList(Item newItem, string newName, int newStacks) { item = newItem; name = newName; stacks = newStacks; } }
实现不同的BUFF效果
一、回血BUFF
1. 简单的回血效果实现
定义一个名为 HealingItem 的类,继承自 Item,定义回血BUFF
public class HealingItem : Item { public override string GiveName() { return "回血BUFF"; } public override void Update(Player player, int stacks) { // 将玩家的生命值增加 5 player.health += 5; } }
新增玩家脚本,调用BUFF
public class Player : MonoBehaviour { // 表示玩家的生命值 public int health; // 表示玩家的物品BUFF列表 public List<ItemList> items = new List<ItemList>(); void Start() { HealingItem item = new HealingItem(); // 将回血BUFF对象添加到物品列表中 items.Add(new ItemList(item, item.GiveName(), 1)); StartCoroutine(CallItemUpdate()); } IEnumerator CallItemUpdate() { // 遍历物品列表中的每个物品 foreach (ItemList i in items) { // 调用物品的 Update 方法 i.item.Update(this, i.stacks); } //暂停1秒继续执行 yield return new WaitForSeconds(1); // 重新启动协程 CallItemUpdate StartCoroutine(CallItemUpdate()); } }
运行效果,角色每秒回5点血
2. BUFF层数控制回血量
修改HealingItem
public override void Update(Player player, int stacks) { // 将玩家的生命值增加 player.health += 3 + (2 * stacks); }
效果,两层每秒加7血
二、攻击附带火焰伤害
新增敌人脚本,定义敌人生命值
public class Enemy : MonoBehaviour { public int health; }
修改Item,定义攻击事件
public virtual void OnHit(Player player, Enemy enemy, int stacks){ }
新增FireDamageItem,实现火焰攻击效果
public class FireDamageItem : Item { public override string GiveName() { return "火焰攻击"; } public override void OnHit(Player player, Enemy enemy, int stacks) { enemy.health -= 10 * stacks; } }
修改Player,默认加2层火焰攻击效果
// 表示玩家的攻击力 public int attackDamage; void Start() { FireDamageItem item = new FireDamageItem(); items.Add(new ItemList(item, item.GiveName(), 2)); } public void CallItemOnHit(Enemy enemy) { foreach (ItemList i in items) { i.item.OnHit(this, enemy, i.stacks); } }
新增PlayerHitbox,定义攻击判定,攻击附加额外火焰攻击BUFF伤害
public class PlayerHitbox : MonoBehaviour { public Player player; //触发器检测 private void OnTriggerEnter(Collider other) { // 判断进入碰撞体的对象是否为敌人 if (other.tag == "Enemy") { Enemy enemy = other.GetComponent<Enemy>(); // 减少敌人的生命值,减少的值为玩家的攻击力 enemy.health -= player.attackDamage; // 调用玩家的 CallItemOnHit 方法,附加额外伤害 player.CallItemOnHit(enemy); } } }
效果,攻击附带额外伤害
三、治疗领域
实现治疗领域效果一般需要加载一些特性,而我们定义的BUFF是没办法挂载特效物品的,这时候就需要使用
Resources
加载指定的特效了
1. 简单的治疗领域实现
绘制预制体
修改Item,定义跳跃方法
public virtual void OnJump(Player player, int stacks) { }
新增HealingArea,实现跳跃方法生成治疗领域
public class HealingArea : Item { //特效 GameObject effect; public override string GiveName() { return "治疗领域"; } public override void OnJump(Player player, int stacks) { if (effect == null) effect= (GameObject)Resources.Load("Item Effects/Healing Area", typeof(GameObject)); GameObject healingArea = GameObject.Instantiate(effect, player.transform.position, Quaternion.Euler(Vector3.zero)); } }
修改Player,实现每次按Space,执行治疗领域OnJump方法
private void Update() { if (Input.GetKeyDown(KeyCode.Space)) { CallItemOnJump(); } } public void CallItemOnJump() { foreach (ItemList i in items) { i.item.OnJump(this, i.stacks); } }
效果,每次跳跃生成一个治疗光环
2. 添加技能冷却时间
修改HealingArea
public class HealingArea : Item { GameObject effect; float internalCoolDown;//技能冷却时间 public override string GiveName() { return "Healing Area"; } public override void Update(Player player, int stacks) { internalCoolDown -= 1; } public override void OnJump(Player player, int stacks) { if (internalCoolDown <= 0) { if (effect == null) effect = (GameObject)Resources.Load("Item Effects/Healing Area", typeof(GameObject)); GameObject healingArea = GameObject.Instantiate(effect, player.transform.position, Quaternion.Euler(Vector3.zero)); internalCoolDown = 10;//技能冷却时间默认定义10秒 } } }
效果,每10秒才能释放一次治疗光环
通过拾取物品获取对应的BUFF
新增ItemPickup ,物品拾取类
public class ItemPickup : MonoBehaviour { // 掉落的物品对象 public Item item; // 物品类型 public Items itemDrop; void Start() { // 调用 AssignItem 方法,传入掉落的物品类型,并将返回值赋值给 item item = AssignItem(itemDrop); } // 触发器检测 private void OnTriggerEnter(Collider other) { // 判断进入碰撞体的对象是否为玩家 if (other.tag == "Player") { // 获取玩家对象 Player player = other.GetComponent<Player>(); // 调用 AddItem 方法,传入玩家对象 AddItem(player); // 销毁 Pickup 对象 Destroy(this.gameObject); } } public Item AssignItem(Items itemToAssign) { // 根据不同的物品类型返回不同的物品对象 switch (itemToAssign) { case Items.HealingItem: return new HealingItem(); case Items.FireDamageItem: return new FireDamageItem(); case Items.HealingAreaItem: return new HealingArea(); default: return new HealingItem(); } } public void AddItem(Player player) { // 遍历玩家物品列表中的每个物品 foreach (ItemList i in player.items) { // 如果该物品已经存在于列表中,则将该物品的叠加数量加 1,并直接返回 if (i.name == item.GiveName()) { i.stacks += 1; return; } } // 将新的物品添加到玩家物品列表中 player.items.Add(new ItemList(item, item.GiveName(), 1)); } } // 定义一个公共枚举类型 Items,表示所有可用的物品类型 public enum Items { HealingItem, FireDamageItem, HealingAreaItem }
修改Player,删除前面旧的BUFF添加
// HealingItem item = new HealingItem(); // items.Add(new ItemList(item, item.GiveName(), 1)); // FireDamageItem item = new FireDamageItem(); // items.Add(new ItemList(item, item.GiveName(), 2));
新增各种BUFF物品,配置预制体
效果,拾取物品即可获取对应的BUFF效果
ps:后续要加入其他BUFF,直接就可以修改ItemPickup很方便的进行添加定义即可
参考
【视频】https://www.youtube.com/watch?v=iU6mKyQjOYI