山寨Besiege(三)需求分析与架构设计

在昆明工作的日子,我虽对经理忽悠的作风极为不屑,但对他整天挂在嘴边的那些软件工程思想还是很尊崇的。无论是传统的瀑布流,还是敏捷开发,无论是大的系统,还是小的功能,先分析需求、再构思设计、再实现的流程是永恒真理。

事情还没弄清楚就开始动手做,是初学者的幼稚行径,越成熟的设计师,越是重视前期的需求分析,思路清晰后,编码也只是“唰”一下的事情了。

习惯总得从无到有养成。所以这次我刻意走一个完整的流程,即便不是那么适应,也要慢慢学会。主要就是在编码之前,先用Visio画UML图。

由于游戏工程的特殊性,大部分用于企业应用、网站设计、数据库设计的UML图并派不上用场,但描述一个软件工程的架构总是脱不开一款绘图软件,想法是不要求完全规范,仅仅是借用那些形状,也是一个路子。哪怕是最原始的用纯文字一条条描述需求的手段,也是聊胜于无。

并不是所有的游戏在被制作之前都有一个模仿对象,假如我是一个主策划,只会说“我们做一个dota传奇那样的”或是“我们做一个皇室战争那样的”,明显是没前途。迟早有一天我会面临原创,所以这里先简单交待一下《Besiege》是个怎样的游戏。

这是一个单机物理类沙盒游戏,玩家需要用游戏提供的各种零件,组装出自己的一台攻城器械,完成每一关卡的任务,任务基本都是摧毁某个建筑之类的了。它的玩点在于逼真的物理效果,以及可以无限自由组合的脑洞大开,你好不容易组装出可以通关的机械,抬头一看网上别的玩家做出的东西的时候,大概就会产生“我们玩的是同一个游戏吗?”的想法。由此奠定了此款游戏的神作地位。

然后我来山寨。

假如是正式的商业项目,肯定要先进行充分的可玩性探讨,但我的目的是练习技术,所以可能本来这个项目不太适合移植到手机上,比如有很多操作设计上的硬伤,我都忽略。

思路是尽量简化,抛弃关卡设计,直接进入主场景,可以组装,可以运行,就够了。

我是有把它做成联机版的想法的,考虑到自己的服务端经验尚浅,第一阶段的架构暂不考虑联机,先做出单机版,再研究如何改造成多人对战。

所以核心功能大概是这样:

组装阶段:

1.按各模块对应按钮,出现模块提示图标

2.拖动过程中图标随手指移动

3.触点进入已有模块可连结范围时,判断新模块是否可连结已有模块。若可以,出现新模块提示,此时若松手,则在结点创建新模块并连结,若不松手拖出范围外,新模块提示消失。

运行阶段:

1.激活所有模块

2.按控制按钮触发相应功能

注意,游戏和桌面应用软件的主循环结构,虽然本质上一样,但表现上还是有个主要的差别。

就是后者一般是消息驱动,比如鼠标点一下,就干什么,键盘按了下,再干什么,而无输入时,基本是个空循环啥都不干。

而游戏是个忙到死的程序,就算没有任何输入,它还是疯狂的往屏幕上渲染画面,基本只恨cpu不够用,鲜有说让cpu歇会的。

有没有特例?少数确实对性能要求不高的游戏可不可以利用这点做一些省电的优化?乃至于引擎限帧后是否已经帮我们做了类似优化?我都不敢乱说。

反正想起三年前刚学做游戏的时候为降cpu占用率主动在线程里加Sleep(),都只给三个字“拿衣服”。

然而,现在这个游戏,倒真是像极了应用软件,至少在组装模式下,除了响应各种操作外,没什么其他的事要做。所以,架构上,它自然也退化到消息驱动程序的样子。

主循环实际上隐藏在EasyTouch的Update()中,我们自己的代码只要给绑定一些On_TouchStart、On_TouchDown、On_TouchUp就好了,Update()中反而空空如也。代码外观上像极了我之前做的看图软件。

贴部分核心代码:

    public void ChangeMode()  //响应“运行/返回”按钮的方法
    {
        switch (gameState)
        {
            case GameState.Assembling:
                ChangeToRunningState();
                break;

            case GameState.Running:
                ChangeToAssemblingState();
                break;

            default:
                break;
        }
    }

    private void ChangeToRunningState()
    {
        gameState = GameState.Running;

        //unbind ET events of Assembling state
        EasyTouch.On_TouchStart -= On_TouchStartAssembling;
        EasyTouch.On_TouchDown -= On_TouchDownAssembling;
        EasyTouch.On_TouchUp -= On_TouchUpAssembling;

        //create a new copy of machine for running, hide the old one
        runTimeMachine = Instantiate(machine);
        machine.SetActive(false);

        //activate all modules in machine
        Rigidbody[] rigs = runTimeMachine.GetComponentsInChildren<Rigidbody>();
        foreach (Rigidbody r in rigs)
        {
            r.useGravity = true;
            r.isKinematic = false;
        }

        //bind ET events of Running state

    }

    private void ChangeToAssemblingState()
    {
        gameState = GameState.Assembling;

        //unbind ET events of Running state

        //destroy runTimeMachine, show the one for assembling
        Destroy(runTimeMachine);
        machine.SetActive(true);

        //unbind ET events of Assembling state
        EasyTouch.On_TouchStart += On_TouchStartAssembling;
        EasyTouch.On_TouchDown += On_TouchDownAssembling;
        EasyTouch.On_TouchUp += On_TouchUpAssembling;
    }

现在RunningMode的响应方法我还没添加,激活零件的方法也只针对小木块这一特殊类型,后面会改成调用不同类型零件的相应方法。

然后我又试着画了画各模块的类图:

这个设计以后肯定是会改的,可能做着做着发现某个方法不需要,而另外一些方法要加进来。该不该这么设计本身也有待商榷,比如动力轮是不是该从从动轮继承而来之类的,我们不要在意这些,错的预设计总是胜过不预设计。

另外由此图我看出来一些端倪,比如由于引擎所有的GameObject都自带Transform组件,而Unity提供的Rigidbody组件又已经包含了质量这一参数,实际上一些简单的类已经不需要自己设计了,只要包含基本的组件即可。另外像轮子、铰链这些类,可能引入Unity自带的一些相关组件后,也能省掉很多方法和成员。

摄像机控制模块相对比较独立,大体需求是这样:

a.组装阶段

1.始终以机器质心为目标点

2.滑动屏幕时摄像机围绕目标转动

3.双指拉伸调节摄像机距离目标远近

b.运行阶段

1.维持目标后上方跟随视角

由于我工作中搞摄像机控制搞得很多,所以对这块完全放心。

我对Unity物理引擎的轮子、铰链都不是太熟,接下来想做一些自己称之为“核心技术攻关”的工作,就是正式做项目之前,先对自己不太了解或者没什么把握的部分做一些试验。

已有的百来行代码已经把组装阶段的功能实现了个七七八八。

再直接做个可以控制开动、转向的小车,应该就能把运行阶段的主要工作都涵盖,再然后就是代码的整合工作了。

最后再说下这几天对UI代码这块的一些思考。

主要就是像UI按钮涉及的一些功能到底是分散在绑定在各UI元素上的脚本好,还是集中在某个主控类中好?

一开始我倾向于后者,这样代码不至于太过零碎,更易读,但后来再想一想,其实把功能代码就绑在它相关的触发源头也没那么难理解,反而更直观。

实际工作中再体会,见仁见智吧。

时间: 2024-10-08 04:51:10

山寨Besiege(三)需求分析与架构设计的相关文章

Robustness Diagram - 从需求分析到架构设计

转载自: http://www.dotblogs.com.tw/jed/archive/2010/11/21/robustness_diagram.aspx   什么是Robustness Diagram Robustness Diagram是一种很特殊的图形,介于Class Diagram与Activity Diagram之间,最早由 Ivar Jacobson 于1992年所提出,台湾这边翻成强韧图.稳健图,对岸则采译音翻成鲁棒图.在需求分析领域,UML的Use Case Diagram已经

Netty4具体解释三:Netty架构设计

     读完这一章,我们基本上能够了解到Netty全部重要的组件,对Netty有一个全面的认识.这对下一步深入学习Netty是十分重要的,而学完这一章.我们事实上已经能够用Netty解决一些常规的问题了. 一.先纵览一下Netty.看看Netty都有哪些组件? 为了更好的理解和进一步深入Netty.我们先整体认识一下Netty用到的组件及它们在整个Netty架构中是怎么协调工作的.Netty应用中不可缺少的组件: Bootstrap or ServerBootstrap EventLoop E

团队项目需求分析和架构设计

初稿 之后还会有修改. 工大助手: 前提: 用户根据学号密码登录 功能: 1.  用户可选择获取入学以来所有已修课程的相关信息:课程代号.课程名.课程属性.学分.成绩等信息. 2.  用户可选择获取特定已修课程的相关信息:课程代号.课程名.课程属性.学分.成绩等信息. 3.  用户可以获得特定学期的课程表(教务已经提供的). 4.  用户可以获得考试安排信息. 5.  用户可获得特定时间段内的加权平均分(1学期.1学年.全部). 6.  用户可获得特定课程在所有用户中的成绩排名. 7.  用户可

初学架构设计的第一步:需求、愿景与架构

了解<需求>.<愿景>与<架构>三者的关系.也就是<需求分析>.<观想愿景>与<架构设计>三者的关系. 一.需求(Requirements)分析: 这通常是由目前面临的问题(Problem)所引发出来的.着重于现实问题和条件的分析,然后寻求解决问题的方法.技术和资源.就系统开发人员来说,需求主要有两种:用户需求和系统需求.一般而言,人们通常会把它看成是系统开发时必须满足的<限制>(Constraint),也是要达成的<

数据仓库架构设计

一. 数据仓库架构,是IT架构的一个分支,随着数据在企业的核心作用的增强,数据仓库的架构日益重要.数据仓库架构由于其技术选择非常广泛,看上去复杂,不过背后有一套比较稳定的思路,这也是数据仓库架构设计的一个要点,稳定中蕴含变化,变化中蕴含稳定. 总 体来说,数据仓库架构分成两大块,一是硬件架构,二是软件架构.硬软架构又可以分成封闭式和开放式.封闭式硬件架构代表厂商有teradata,其硬件是 专属的,必须使用特殊的硬件才能运行.开放式硬件架构的代表有oracle,可以运行在各种硬件上,不过开放和封

架构设计实践二:需求分析

1.1 三个问题 掌握好需求分析,需要掌握三个问题的解决方式. 需求如何获得?需求开发=愿景分析+需求分析 如何判断需求全不全?功能.质量.约束三类需求 如何从需求转换为设计?功能.质量.约束对架构产生不同的影响. 1.2 软件研发与交付过程总图 其中概念化阶段一般都要完成愿景分析.风险评估.可行性分析及项目进度和成本的粗略估算,输出<愿景与范围文档>:需求分析阶段则完成需求捕获.需求分析,得到<软件需求规格说明书>,一个关键的思路是需求捕获与需求分析是迭代着进行的,完成需求捕获之

架构设计-架构需求分析

一.架构设计的需求分析从哪来 需求分析的前期工作是愿景描述及愿景分析, 即愿景分析就是需求的前期调研. 从软件过程来看,需求分析是一个承上启下的阶段–“上承”愿景,“下接”设计.需求分析的工作内容包含如下三方面: 需求捕获: 理解沟通需求分析:做什么,有哪些问题 系统分析:原因是什么, 怎么做 三者不是独立无关的阶段,而是相互伴随.交叉进行的. 需求捕获: 从各个方面收集需求, 并理解需求.典型的需求捕获是使用“需求采集卡”:需求描述.需求提出者.需求记录者.需求类型等.需求分析:需求捕获得到的

敏捷开发下, 如何将需求分析,架构(软件)设计,开发与测试,一气呵成式的结合且高效的完成 ?

产品开发中,时常会发生类似如图中 "削马铃薯"的悲剧. 悲剧的发生,往往是由于我们只传递了 "要作什么功能"给开发人员.却缺乏了一个有效的且轻量级的实践,能在正式进入迭代开发前,确认开发人员是否真有能力,能将 "使用者的需求"转化为 "可执行的代码"? "场景树" 便是一结合Use Case, Domain Driven Design, UML 的轻量级可视化的敏捷实践. 经由场景树,可确认开发人员,是否已

[转]MVC实用架构设计(三)——EF-Code First(3):使用T4模板生成相似代码

本文转自:http://www.cnblogs.com/guomingfeng/p/mvc-ef-t4.html 〇.目录 一.前言 二.工具准备 三.T4代码生成预热 (一) 单文件生成:HelloWorld.cs (二) 多文件生成 四.生成数据层实体相关相似代码 (一) 生成准备 (二) 生成实体相关相似代码 生成实体映射配置类 生成实体仓储接口 生成实体仓储实现 五.源码获取 系列导航 一.前言 经过前面EF的<第一篇>与<第二篇>,我们的数据层功能已经较为完善了,但有不少