新手教程分为很多类型,有的是一边玩一边引导玩家,通常是玩一半指导一半。有一种是直接提供对应的提示文字,不强制玩家观看。这两种引导也出现直接的面板提示或者视频和动画类型,其中第一种教程形式是市面上最为常见的,但是这也强制了玩家进行一些操作。第二种没有强制玩家,但是在某些情况下可能会影响玩家对于游戏的理解(例如有的玩家并不耐心观看完全部规则直接动手游戏,结果玩的懵懵懂懂--特别对于文字量较大的,这种教程一般也会搭配一些小视频出现)具体的教程就不多说了,一般也是策划设计好了再动手。今天我们主要对于第二种类型的教程制作。
目录
1 需求分析
首先我们接到需求:当玩家还是新手的时候,进入游戏没进入一个全新的格子就会进行对应的引导:例如战斗格子会出现战斗类型的引导,地形格子会出现地形类型的引导等等。当玩家不是新手时,则不会再出现这种类型的引导,但是玩家可以通过主界面的新手引导按钮再次观看,并且通过左右翻页可以观看全部的内容,左侧面板出现一系列按钮,分为战斗教程,地形教程,游戏总界面教程等等。总界面最上方有两个标题栏对应着哪一种类型的教程,下方显示页码和页数以及上一页和下一页的按钮可以翻页。如果是第一页则呈现灰色不可点击,如果是最后一页则下一页变成灰色不可点击。教程的面板最顶部有隐藏面板的关闭按钮。
我们开始分析需求:对于整个新手教程分为两种,一种是单个出现的新手面板,只能在新手阶段在新格子里面出现,一种是总教程的合集,可以通过主界面的新手教程按钮点击观看。这里由玩家是否是新手控制,于是我们制作一个玩家类,并且对于玩家是否是新手进行标注,当玩家通过新手关卡则认定为玩家不再是新手。
public class PlayMgr : BaseMgr<PlayMgr>
{
/// <summary>
/// 玩家是否是新手
/// </summary>
public bool IsNew = true;
private PlayMgr()
{
}
}
我们简单制作一下玩家类并且添加了新手的标识,后续我们只需要控制这个新手标识就可以得到玩家是否是新手,是否需要在每一个格子之中进行新手引导。
分析完这一项之后,我们开始分析面板之中需要的内容:主标题和副标题不是确定的,是根据对应的教程有所改变的,例如战斗教程会显示战斗的名字:比如蜘蛛会显示蜘蛛战斗教程,骷髅兵会显示骷髅兵战斗教程。副标题也不是一成不变的,例如如果是胜利与失败条件则显示条件,如果是对应该小关卡的技能内容则显示技能运用相关的副标题。对于里面的文字提示也是对应教程的名字,右侧的提示教程视频也是对应的战斗教程视频。
2 参数制作
于是我们将这一系列内容制作出相应的参数,我们选择list链表或者字典将他们存储,并且后续可以通过ID更新并且可以实现上下翻动改变内容,对此我们设置页码,ID,视频地址,文字提示,主标题,副标题等等...
表格设计如下:
得到这些关键数据,我们开始制作单个数据类,并且将他们表示在某一个控制器当中,确保数据单一。
3 逻辑制作
于是,我们分析完数据并且填写完数据之后,开始制作面板的逻辑部分:
using NicoleFrameWork;
using UnityEngine;
using UnityEngine.Video;
public class NewPlayerPanel : NewPlayerPanelBase
{
private AudioSource _sourceButton;
/// <summary>
/// 一开始的ID页码
/// </summary>
public int ID=1;
public NewPlayerInfoContainer NewPlayerInfoContainers=new();
public bool CanClickLeft=true;
public bool CanClickRight = true;
/// <summary>
/// 是否是没有左边的
/// </summary>
public bool IsSingle = true;
public override void Start()
{
base.Start();
NewPlayerInfoContainers = MyCardGameMgr.Instance.NewPlayerInfoContainers;
Init();
}
/// <summary>
/// 初始化新手教程,注意:图片没有进行处理
/// </summary>
public void Init()
{
txtEx.text = NewPlayerInfoContainers.DataDic[ID].NewText;
txtName.text = NewPlayerInfoContainers.DataDic[ID].TitleName;
txtNameS.text = NewPlayerInfoContainers.DataDic[ID].MiddleName;
ExceptionBK.GetComponent<VideoPlayer>().clip =
ResMgr.Instance.Load<VideoClip>("JC/" + NewPlayerInfoContainers.DataDic[ID].ImageRes);
if (IsSingle)
{
Single(false);
if(NewPlayerInfoContainers.DataDic[ID].AllNum==1)
NumBK.gameObject.SetActive(false);
txtPage.text = $"{NewPlayerInfoContainers.DataDic[ID].SelfID}/{NewPlayerInfoContainers.DataDic[ID].AllNum}";
if (NewPlayerInfoContainers.DataDic[ID].SelfID == 1)
{
CanClickLeft = false;
BtnLast.image.color = Color.gray;
}
else
{
CanClickLeft = true;
BtnLast.image.color = Color.white;
}
if (NewPlayerInfoContainers.DataDic[ID].SelfID == NewPlayerInfoContainers.DataDic[ID].AllNum)
{
CanClickRight = false;
BtnNext.image.color = Color.gray;
}
else
{
CanClickRight = true;
BtnNext.image.color = Color.white;
}
}
else
{
Single(true);
txtPage.text = $"{NewPlayerInfoContainers.DataDic[ID].ID}/13";
if (NewPlayerInfoContainers.DataDic[ID].ID == 1)
{
CanClickLeft = false;
BtnLast.image.color = Color.gray;
}
else
{
CanClickLeft = true;
BtnLast.image.color = Color.white;
}
if (NewPlayerInfoContainers.DataDic[ID].ID == 13)
{
CanClickRight = false;
BtnNext.image.color = Color.gray;
}
else
{
CanClickRight = true;
BtnNext.image.color = Color.white;
}
}
}
/// <summary>
/// 是否会出现左边的一些按钮
/// </summary>
public void Single(bool isOn)
{
BtnJB.gameObject.SetActive(isOn);
BtnAttack.gameObject.SetActive(isOn);
BtnD.gameObject.SetActive(isOn);
}
protected override void BtnJBClick()
{
base.BtnJBClick();
_sourceButton = BtnJB.GetComponent<AudioSource>();
_sourceButton.Play();
ID = 1;
Init();
}
protected override void BtnAttackClick()
{
base.BtnAttackClick();
_sourceButton = BtnAttack.GetComponent<AudioSource>();
_sourceButton.Play();
ID = 4;
Init();
}
protected override void BtnDClick()
{
base.BtnDClick();
_sourceButton = BtnD.GetComponent<AudioSource>();
_sourceButton.Play();
ID = 9;
Init();
}
protected override void BtnNextClick()
{
base.BtnNextClick();
_sourceButton = BtnNext.GetComponent<AudioSource>();
_sourceButton.Play();
if(!CanClickRight)return;
ID = NewPlayerInfoContainers.DataDic[ID].JumpID;
Init();
}
protected override void BtnLastClick()
{
base.BtnLastClick();
_sourceButton = BtnLast.GetComponent<AudioSource>();
_sourceButton.Play();
if(!CanClickLeft)return;
ID--;
Init();
}
public override void HideMe()
{
base.HideMe();
}
public override void ShowMe()
{
base.ShowMe();
}
protected override void BtnCloseClick()
{
base.BtnCloseClick();
_sourceButton = BtnClose.GetComponent<AudioSource>();
_sourceButton.Play();
Time.timeScale = 1;
UIMgr.Instance.HidePanel<NewPlayerPanel>(true);
}
}
对于每一个格子之中显示对应的内容则制作为:
if (PlayMgr.Instance.IsNew)
{
UIMgr.Instance.ShowPanel<NewPlayerPanel>(E_LoadingMethod.Res,E_UI_Layer.System,false, (panel) =>
{
panel.ID = 9;//这里是控制数据是第几条,没有数据分离,但是可以分离操作一波这里不演示
panel.IsSingle = true;
Time.timeScale = 0;
});
}
这样,一个完整的新手教程部分就做完了。对于新手标识最后还需要数据持久化一波,这里不作演示。
如果对你有帮助就点个小红心支持一下吧。关注我,了解更多精彩!