U3D游戏开发之中剧情系统的制作

今天我们来揭秘带有人物选项的剧情系统该如何制作。

半年前我接到了一个剧情系统的需求,本着能抄代码绝不自己动手的想法在B站上面找现成系统,大概看了一些内容,发现比较繁琐就直接自己动手写了。

目录

 1 需求分析

 2 梳理代码逻辑

 3 代码书写

 4 代码测试与系统验收


 1 需求分析

拿到需求之后我们开始分析列表之中需要的参数:


里面包含对话ID,对话具体内容string,对话可能需要用到的图片路径icon,对话者名字,对话类型(是对话还是选项)对话出现的时间(比如第几章节),对话出现的音效(比如可能出现打雷,喧闹声,笑声,鼓掌等等声音),跳转的对话ID(主要是方便对应下一句的ID:比如我从ID为1 的对话结束后,下一句是ID为4的对话,当我选择继续按钮时就会显示ID为4的这一条数据),还有选项数,例如这段对话结束出现选项提供玩家选择,此时程序员需要知道有几条选项,方便我们动态加载他们并且初始化他们,如果出现选项则不可点击继续按钮(意思是:只有选择了选项才可以继续剧情,而不能直接跳过选择)

根据上方的梳理,我们的数据也差不多够用了,表格list是我个人设置的编辑器小工具功能,如果填写list就自动生成链表(此处不附加小工具源码,仅提供剧情系统开发思路)

我们将内容分析完成之后,就可以将表格内容拿给策划填写参数,(如果你是独立游戏开发者就自己填写,如果你们公司策划自己填写了表头那么上面一步直接省略,如果你是打gamejam比赛,那么多数情况下是需要你自己或者你协助策划一起填写表头的)

 2 梳理代码逻辑

一切准备就绪之后,我们就开始分析代码逻辑:

首先,我们要制作初始化的方法,让剧情显示的时候同时显示人物名字,人物对话的具体内容,如果有音效的就播放音效,如果是选项就隐藏继续按钮,并且动态加载选项内容,点击之后获取跳转的ID,然后再根据跳转的ID查找到下一条对应的剧情内容,依法炮制,知道结束,表格内剧情状态为END,就关闭剧情界面。

 3 代码书写

大概思路已经非常清晰,我们开始写代码:

using System.Collections.Generic;
using NicoleFrameWork;
using UnityEngine.UI;

public class StoryPanels : StoryPanelsBase
{
    public int ID=1;
    
    private List<StoryLevel1> _storyLevel1s;
    private int _id;
    public override void Start()
    {
        base.Start();
        _storyLevel1s = GameJsonDataMgr.Instance.StoryLevel1List;
        InitShowStory();
    }

    public override void HideMe()
    {
        base.HideMe();
        
    }

    public override void ShowMe()
    {
        base.ShowMe();
    
        
    }
    /// <summary>
    /// 刷新对话和选项的方法
    /// </summary>
    public void RefreshAll()
    {
        InitShowStory();
        ShowChooseStory();
    }
    /// <summary>
    /// 显示对话框内的对话内容(直接刷新对话的方法)
    /// </summary>
    public void InitShowStory()
    {
        HideBtns();
        //播放音效
        if (_storyLevel1s[ID-1].Source != "null")
        {
            
        }
        //修改名字
        Name.text = _storyLevel1s[ID-1].TalkName;
        if (Name.text != "我")
        {
            NameImage1.gameObject.SetActive(false);
            NameImage.gameObject.SetActive(true);
        }
        else
        {
            NameImage1.gameObject.SetActive(true);
            NameImage.gameObject.SetActive(false);
        }
        
        //修改人物图片
        
        //修改对话内容
        Story.text = _storyLevel1s[ID-1].Story;
        //修改下一步按钮状态
        //如果选项个数不为0 (有选项)   或者 对话以后没有其他内容了
        //后续要对于没有内容的做更详细的内容
        if(_storyLevel1s[ID-1].ChooseNum!=0||_storyLevel1s[ID-1].JumpID==0)
            BtnNext.gameObject.SetActive(false);
        else
        {
            BtnNext.gameObject.SetActive(true);
        }
    }
    /// <summary>
    /// 处理按钮显示逻辑
    /// </summary>
    /// <param name="numID"></param>
    public void ShowChooseStory()
    {
        int ChooseNum = _storyLevel1s[ID-1].ChooseNum;
        _id = _storyLevel1s[ID - 1].JumpID-1;
        switch (ChooseNum)
        {
            case 0:
                HideBtns();
                break;
            case 1:
                Choose1.gameObject.SetActive(true);
                Choose2.gameObject.SetActive(false);
                Choose3.gameObject.SetActive(false);
                Choose1.GetComponentInChildren<Text>().text = _storyLevel1s[_id].Story;
                break;
            case 2:
                Choose1.gameObject.SetActive(true);
                Choose2.gameObject.SetActive(true);
                Choose3.gameObject.SetActive(false);
                Choose1.GetComponentInChildren<Text>().text = _storyLevel1s[_id].Story;
                Choose2.GetComponentInChildren<Text>().text = _storyLevel1s[_id+1].Story;
                break;
            case 3:
                Choose1.gameObject.SetActive(true);
                Choose2.gameObject.SetActive(true);
                Choose3.gameObject.SetActive(true);
                Choose1.GetComponentInChildren<Text>().text = _storyLevel1s[_id].Story;
                Choose2.GetComponentInChildren<Text>().text = _storyLevel1s[_id+1].Story;
                Choose3.GetComponentInChildren<Text>().text = _storyLevel1s[_id+2].Story;
                break;
                
        }
    }
    /// <summary>
    /// 处理所有按钮隐藏的方法
    /// </summary>
    public void HideBtns()
    {
        Choose1.gameObject.SetActive(false);
        Choose2.gameObject.SetActive(false);
        Choose3.gameObject.SetActive(false);   
    }
    protected override void Choose1Click()
    {
        base.Choose1Click();
        ID = _storyLevel1s[_id].JumpID;
        HideBtns();
        InitShowStory();
        MusicMgr.Instance.PlayerSound("Choose",E_LoadingMethod.ABRes);
    }

    protected override void Choose2Click()
    {
        base.Choose2Click();
        ID = _storyLevel1s[_id+1].JumpID;
        HideBtns();
        InitShowStory();
        MusicMgr.Instance.PlayerSound("Choose",E_LoadingMethod.ABRes);
    }

    protected override void Choose3Click()
    {
        base.Choose3Click();
        ID = _storyLevel1s[_id+2].JumpID;
        HideBtns();
        InitShowStory();
        MusicMgr.Instance.PlayerSound("Choose",E_LoadingMethod.ABRes);
    }

    protected override void BtnNextClick()
    {
        base.BtnNextClick();
        MusicMgr.Instance.PlayerSound("Choose",E_LoadingMethod.ABRes);
        ID = _storyLevel1s[ID-1].JumpID;
        if(_storyLevel1s[ID-1].ChooseNum==0)
            InitShowStory();
        else
        {
            InitShowStory();
            ShowChooseStory();
        }
    }
}

 4 代码测试与系统验收

代码写的比较暴力,但是符合之前所说的所有条件。我们在main脚本之中测试一下我们的剧情系统:

         if(Input.GetKeyDown(KeyCode.S))
            UIMgr.Instance.GetPanel<StoryPanels>((story) =>
            {
             story.InitShowStory();   
             
            });
        if(Input.GetKeyDown(KeyCode.D))
            UIMgr.Instance.GetPanel<StoryPanels>((story) =>
            { 
                story.InitShowStory();
                story.ShowChooseStory();
            });

完美运行,于是我们将剧情系统的测试视频发送给策划看,通过一系列交流发现该系统与我们的策划案需求完美符合。

至此,一个对应游戏需求的剧情系统制作完毕。

(提供剧情系统思路,仅供参考,喜欢就请点赞收藏吧!)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nicole Potter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值