对话,任务与背包系统
1.对话系统
1.1 对话系统的UI搭建
- 1.在Canvas画布调整自适应模式的尺寸(根据图片尺寸调整),新建一个对话面板
Dialogue Panel
,在其下创建Image组件,并在布局中切换为撑满整个面板(Alt + Shift + 右下角),引入对话背景素材。可以再装饰一下对话的UI(顶部花纹等等)。 - 2.在处理文字时,可以加入富文本的写法(记得勾选
Rich Text
)对部分文字进行特殊处理,比如:<size=120><color=red> 文本内容 </color></size>
。也可以勾选Best Fit
对字体大小进行规范化限制。
1.2 对话系统的单向交互
写一个交互脚本DialogueLogic进行简单交互处理:
public class DialogueManager : MonoBehaviour
{
//实现单例模式
public static DialogueManager Instance;
//整个对话面板,用于对话的显隐
public GameObject panel_dialogue;
//对话文字内容以及说话人文本
public Text txt_dialogue,txt_name;
//定义数组存储一次对话有几句话
[TextArea(1,3)]
public string[] dialogueLines;
[SerializeField] private int currentLine;
void Awake()
{
//初始化单例模式
if (Instance == null){
Instance = this;
}
else{
if (Instance != this){
Destroy(gameObject);
}
}
DontDestroyOnLoad(gameObject);
}
void Start()
{
txt_dialogue.text = dialogueLines[currentLine];
}
void Update()
{
//如果面板是激活的并且点击了鼠标左键
if (panel_dialogue.activeInHierarchy && Input.GetMouseButtonUp(0))
{
currentLine ++;
//判断对话是否结束(预防数据越界)
if (currentLine < dialogueLines.Length)
txt_dialogue.text = dialogueLines[currentLine];
else
panel_dialogue.SetActive(false);
}
}
//显示对话方法,外界调用只需要将对话内容数组传入即可
public void ShowDialogue(string[] newLines)
{
//如果正在对话,再次按下F不可再次重新读取内容
if (panel_dialogue.activeInHierarchy) return;
//将当前NPC对话内容赋值给内容数组
dialogueLines = newLines;
//将对话从第一句开始播放
currentLine = 0;
//设置当前显示的内容
txt_dialogue.text = dialogueLines[currentLine];
//将对话框设为可见
panel_dialogue.setActive(true);
}
}
给地图上添加触发器,并在触发器的地方添加脚本:
Talkable.cs:
一般情况下对话内容会写在Talkable脚本中,因为每个目标有不同对话内容。
public class Talkable : MonoBehaviour
{
[SerializeField] private bool isEntered;
[TextArea(1,3)]
public string[] lines;
//触发器方法的实现省略
OnTriggerEnter2D();
OnTriggerExit2D();
private void Update()
{
//如果玩家在范围内并且按下F键,要考虑正在对话时玩家的操作(移动或者再次对话)
if (isEntered && Input.GetKeyDown(KeyCode.F))
{
DialogueManager.Instance.ShowDialogue(lines);
}
}
}
1.3 对话系统的双向交互
实现思路:为了在一个地方实现说话人的称呼,我们可以采用在对话数组某一项添加特殊标识的形式,比如,说话人物名字的内容前加上 n- 标识。
DialogueManager.cs中加上以下方法:
public class DialogueManager : MonoBehaviour
{
//此方法应在正确切换对话内容时调用
//此方法也应该在第一次显示对话面板时调用
public void CheckName()
{
//判断对话内容是否以n-开头
if (dialogueLines[currentLine].StartsWith("n-")){
//当前内容时说话人
txt_name.text = dialogueLines[currentLine].Replace("n-","");
//跳到下一句
currentLine++;
}
}
}
1.4 路标告示栏对话实现
- 1.将对话长度设置为1,在之前脚本的
ShowDialogue
的方法中加入参数 hasName,如果该参数为false,则不显示右下角说话人,反之,显示说话人姓名。
public void ShowDialogue(string[] newLines,bool hasName)
{
//其余代码无更改
txt_name.gameObject.SetActive(hasName);
}
1.5 实现文字内容跳转出现的效果
public class DialogueManager : MonoBehaviour
{
//设置参数控制是否开启滚动出现文字
private bool isScroll;
//文字跳出效果时间间隔
[SerializeField] private float textSpeed;
//在ShowDialogue方法的替换掉之前给内容赋值的方式改为开启协程
//同样在鼠标点击处替换开启协程,并加入只有显示完成文字内容时才可跳转下一句
void Update()
{
if (!isScroll){...}
}
//开启一个协程控制文字效果
private IEnumerator ScrollingText()
{
isScroll = true;
txt_dialogue.text = "";
foreach(char letter in dialogueLines[currentLine].ToCharArray())
{
txt_dialogue.text += letter;
yield return new WaitForSeconds(textSpeed);
}
isScroll = false;
}
}