父类一实现serializable_用128行代码实现一个文字冒险游戏

5a2419617a06f870548477fa79df299b.gif

哈喽大家好我是yumir

文字冒险游戏一直是一个广受欢迎的游戏类型,有小可爱问我有没有文字冒险游戏的制作思路,今天就分享一下,做一个简单的文字冒险游戏,只需要128行代码~

这次我只做了文字显示和分支选择的部分(已经足够用来制作一个游戏了),实际上不管有多少元素,按着我这个思路都是可以实现的。下图是当前的游戏效果:

9b2bbc60b9c2d5010b0c85f5285841db.gif

我的思路是把系统分为三个部分:

  1. 视图搭建:界面上所有的元素,比如:角色名称、立绘、对话等等元素,需要在场景中搭建制作好预制体。
  2. 数据结构:根据游戏内容设计需要填充的数据,对应以上比如:角色名、立绘图片名称、对话内容等等,除此之外需要一个字段“ID”作为句子的唯一标识。
  3. 业务逻辑:将读取到的数据(“2”的数据结构中的内容)和“1”的界面元素一一对应编写逻辑。

一、视图搭建

根据需求搭建界面,因人而异,我在场景中放了:背景、对话框和选项框。

aa1dedda5c3bf04bf5ed6e915387c4ba.png

背景是一张图片,对话框是在图片中加上文本,选项框稍微复杂,你需要新建一个空的UI物体,调整到合适的大小布局,然后在该物体上加上“Grid Layout Group”组件,设置如下(尺寸自行调整)。

9bd3a88180a6a9abf421612e98bc0a61.png

然后在该物体中新建一个子物体作为选项的预制体,我的选项特简单,就是底图加文字组成的按钮,选项预制体需要写一个对文字内容赋值用的脚本:

    public Text text;
    public int number;
    public void Start()
    {
        GetComponent<Button>().onClick.AddListener(()=> { TalkWin.instance.WhenSwitchNodeGetAnswer(number); });
    }
    public void SetAnswerUI(string s,int i)
    {
        text.text = s;
        number = i;
    }

二、数据结构

为了方便填充剧情,我们需要把所有可控条件(文本、图片名称、是否特效等等)都用一个一个的对象存储起来,针对需求定制不同的类。

根据我的需求,游戏中对话有两种情况,而所有游戏对话又有同质内容,所以我将他们提炼到父类中,他们之间的关系如下(类图):

04682650baa08ed46b8caf28800cbe0d.png

之所以这么写纯粹是因为写重复的字段很累,为了进一步偷懒(不使用额外的文件)在声明的类的前面加上[System.Serializable]。

using 

这样一来就可以直接在面板上填写数据了。

84c8b921365176ff8ec407f16f22723f.png

三、业务逻辑

我需要一个打字机的动画效果,而DOTween正好有现成的,所以直接封装一个方法来更新对话框部分的UI刷新逻辑:

    public void UpdateTalkWinShow(string nameText,string talkText, float charSpeed)
    {
        this.nameText.text = nameText;
        this.talkText.text = "";
        this.talkText.DOText(talkText, charSpeed * talkText.Length);
    }

为了知道每次持有的是哪个对话对象,我们需要在系统中声明一个int值类型的字段,作为当前“对话”的指针,初始值是第一个对话对象的ID,也就是“1001”。在每次播放当前对话内容之后将该值替换为实现设置好的“nextID”。

写一个点击事件根据不同的ID进行判断:

        if (textID>1000&&textID<2000)
        {
            UpdateTalkWinShow(commonDic[textID].nameText, commonDic[textID].talkText, (float)commonDic[textID].charSpeed);
            textID = commonDic[textID].nextID;
        }
        else if (textID > 2000 && textID < 3000)
        {
            UpdateTalkWinShow(switchDic[textID].nameText, switchDic[textID].talkText, (float)switchDic[textID].charSpeed);
            CreateAnswerUI(switchDic[textID].switchText);
            GetComponent<Button>().interactable = false;
        }

再回到场景中点击运行,欸,这么简单就完成了?

1381c86b7b8e3db69d146d495bc0eadc.png

链接:https://pan.baidu.com/s/1zaLoeu8RASWNKSyyookbFg

提取码:8mus

——照例的分割线——

欢迎加入游戏开发群欢乐搅基:610475807

对游戏开发感兴趣的童鞋可戳这里进一步了解:http://www.levelpp.com/

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值