开发思想-(数据驱动+组合模式)VS 继承

利用一个需求对比两者,并说明什么是数据驱动?为什么在某些场景下组合优于继承?

一、需求例子

设计消除类游戏的方块,

方块可能有普通方块、不可被移动方块、不可被消除方块、既不能被移动也不能被消除方块、相邻方块消除后消除自己的方块、自己消除后会发射火箭的方块等等,。

二、用接口、继承、多态那一套来做是怎么样

  1. 接口用来规范行为,定义能力

比如:

cs 复制代码
public interface IMovable
{
    bool canMove();
}

那么继承这个接口,实现方法,方法内容是判断方块是否可以被移动。

  1. 实现一个抽象类,实现共享的公共方法和属性
cs 复制代码
public abstract class BaseBlock : IMovable,...其他接口
{
    // 公共属性
    // 比如位置信息、配置信息等等。

    // 实现ICanNotMove方法
    public virtual bool CanMove()
    {
    }

    // ... 其他接口的方法
}
  1. 实现具体的类型方块,通过继承BaseBlock,多态

    public class NormalBlock : BaseBlock
    {
    // 子类自己的特别属性

    复制代码
     //实现自己的逻辑
     public override bool CanMove()
     {
         return true;
     }

    }

    public class CanNotMoveBlock : BaseBlock
    {
    // 子类自己的特别属性

    复制代码
     //实现自己的逻辑
     public override bool CanMove()
     {
         return false;
     }

    }

每需要一个新方块几乎都要创建一个新的子类,子类爆炸。

  1. 移动管理模块,访问方块BaseBlock或者ICanNotMove,判断是否可以移动

    // 移动管理模块
    // 通过方块管理类拿到这个Block
    BaseBlock block = BlockManager.instance.GetBlock(pos);
    bool blockCanMove = block.CanMove();
    if(blockCanMove)
    {
    // 移动逻辑
    }

  2. 阶段总结

我们发现这种开发模式的一个特点,那就是每需要一个新的方块,就需要开发者用代码开发出一个新的方块类,开发新的接口。

也就是说创建新方块类型的操作在程序员这里。

三、利用数据驱动思想,将创建方块的操作从程序员代码创建移交给策划。

  1. 定义配置文件,配置就是数据
cs 复制代码
public class BlockType:ScriptableObject
{
    public int id;
    public string Desc;
    // 基础属性
    public bool canMove = true;
    public bool canClear = true;
    
    // 为了防止属性过多,将大块属性分到各个模块
    public List<BaseBehaviour> behaviours;
}

public abstract class BaseBehaviour : ScriptableObject
{
    // 当被消除调用
    public virtual void OnClearBlock()
    {
    }
}

public class FireRocketBehaviour : BaseBehaviour
{
    public int FireCount = 2;
    // .. 其他属性
    
    public override void  OnClearBlock()
    {
        // 火箭管理系统发射火箭
        FireRocketManager.Fire();
    }
}
  1. 创建一个方块的操作,就交给了和程序无关的人

直接创建这个Scriptobject,填写信息、勾选基础能力、添加模块能力,就组合出了一个新的方块。

方块可以同时拥有配置中的多种能力,这些能力任由策划配置驱使。

  1. 开发做什么?

开发要在游戏逻辑中,实现每个能力的效果和先后顺序。

针对配置的canMove 字段,就要在移动阶段判断,然后做相应操作。

针对配置的canClear字段,就要在消除阶段判断,然后判断是否能将其删除。

程序从既要用代码创建模块还要实现能力->转变为专注地实现能力,创建交给配置和数据。

继承是"类型决定能力",组合是"能力拼出类型"。

有 N 种能力,就能组合出 2^N 种玩法,而不需要创建 2^N 个类。

相关推荐
技术探讨者5 小时前
Unity 框架:从核心构成到实践应用的全面解析
unity·游戏引擎
牛掰是怎么形成的5 小时前
Unity Legacy动画与骨骼动画的本质区别
unity·游戏引擎
weixin_458360915 小时前
Unity使用Cursor Editor
unity
萘柰奈5 小时前
Unity学习--2D动画--[序列帧动画]2D序列帧动画
学习·unity·游戏引擎
EQ-雪梨蛋花汤5 小时前
【Unity笔记】Unity 模型渲染优化:从 Batching 到 GI 设置的完整指南
笔记·unity·游戏引擎
花花_15 小时前
一步封神:Unity环境搭建终极全宇宙级攻略(Win/Mac/云)
macos·unity·游戏引擎
Unity打怪升级5 小时前
【Unity精品源码】Ultimate Character Controller:高级角色控制器完整解决方案
游戏·unity·ue5·游戏引擎·godot·游戏程序·cocos2d
qq_312982135 小时前
Unity国际版下载方法 https://unity.com/releases 被重定向问题导致下载不到Unity国际版的问题解决
unity·游戏引擎
光光的奇妙冒险5 小时前
Luban+Unity使用,看这一篇文章就够了
unity·游戏引擎·游戏程序·游戏策划
米芝鱼6 小时前
Unity读取Excel转换为二进制数据文件与自定义数据读写
游戏·unity·游戏引擎·excel·urp