今天我们来揭秘带有人物选项的剧情系统该如何制作。
半年前我接到了一个剧情系统的需求,本着能抄代码绝不自己动手的想法在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();
});
完美运行,于是我们将剧情系统的测试视频发送给策划看,通过一系列交流发现该系统与我们的策划案需求完美符合。
至此,一个对应游戏需求的剧情系统制作完毕。
(提供剧情系统思路,仅供参考,喜欢就请点赞收藏吧!)