视频效果
unity:通用美观可快进的对话系统
素材
素材下载地址
素材展示:
绘制地形&对话框
- 绘制地形
关于TileMap的使用,这里就不再过多介绍了,关于TileMap的介绍有很多
我们创建一个简单的地形如下:
- 绘制对话框,效果如下:
- 配置人物动画,主要是奔跑动画
- 实现简单的控制人物移动
新建脚本实现简单的控制人物的移动和动画切换
挂载到player上
player.csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
[Header("移动速度")]
public float speed;
Animator animator;
Vector3 movement;
void Start()
{
animator = GetComponent<Animator>();
}
void Update()
{
//移动
movement = new Vector3(Input.GetAxisRaw("Horizontal") * Time.deltaTime * speed, Input.GetAxisRaw("Vertical") * Time.deltaTime * speed, transform.position.z);
transform.Translate(movement);
//动画
if (movement != Vector3.zero)
{
animator.SetBool("run", true);
}else{
animator.SetBool("run", false);
}
//翻面
if(movement.x>0){
transform.localScale = new Vector3(1, 1, 1);
}
if(movement.x<0){
transform.localScale = new Vector3(-1, 1, 1);
}
}
}
效果如下:
5.控制对话框的显示隐藏
新增脚本TalkTrigger,控制NPC对话提示和对话框的显示和隐藏,为单实例类
TalkTrigger.csharp
using System;
using UnityEngine;
public class TalkTrigger : MonoBehaviour
{
private GameObject tipsButton;//对话提示按钮
[NonSerialized]
public Dialogue dialogue;//对话内容
[Header("对话框")]
public GameObject dialogBox;
public static TalkTrigger instance;
private void Awake()
{
if(instance == null)
{
instance = this;
}else{
if(instance != this){
Destroy(gameObject);
}
}
DontDestroyOnLoad(gameObject);
}
private void OnTriggerEnter2D(Collider2D other)
{
tipsButton = other.transform.Find("对话提示").gameObject;
dialogue = other.GetComponent<NPC>().dialogue;
tipsButton.SetActive(true);
}
private void OnTriggerExit2D(Collider2D other)
{
tipsButton.SetActive(false);
dialogBox.SetActive(false);
}
private void Update()
{
if (tipsButton != null && tipsButton.activeSelf && Input.GetKeyDown(KeyCode.R))
{
dialogBox.SetActive(true);
}
}
}
效果如下:
构建对话数据结构
1.新建DialogNode,定义每段对话的各种属性
DialogNode.csharp
using System;
using UnityEngine;
// 代表了一个对话节点。
[Serializable]
public class DialogNode
{
[Header("角色的名字")]
public string name;
[Header("角色的头像")]
public Sprite sprite;
[TextArea, Header("对话的内容")]
public string content;
}
2.新建Dialogue脚本,继承ScriptableObject,这样就可以方便的新建各种对话了
Dialogue.csharp
using UnityEngine;
// 表示一段对话
[CreateAssetMenu(menuName="创建对话" ,fileName = "对话")]
public class Dialogue : ScriptableObject
{
// 对话节点
public DialogNode[] dialogNodes;
}
3.在unity界面创建各种对话,并配置对话内容
随便配置了一些内容,如下:
3.实现简单的对话功能
定义NPC脚本
NPC.csharp
using UnityEngine;
public class NPC : MonoBehaviour {
[Header("对话内容")]
public Dialogue dialogue;
}
4.给不同NPC挂载不同的对话
以老者为例:
5.修改TalkButton,获取对应的NPC对话内容,并修改为单例,方便其他地方调用dialogue对话内容
[NonSerialized]
public Dialogue dialogue;//对话内容
//单例
public static TalkButton instance;
private void Awake()
{
if(instance == null)
{
instance = this;
}else{
if(instance != this){
Destroy(gameObject);
}
}
DontDestroyOnLoad(gameObject);
}
构建对话系统
新增DialogSystem脚本,挂载在对话框上
DialogSystem.csharp
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class DialogSystem : MonoBehaviour
{
private Dialogue dialogue;//对话内容
//索引
private int index;
//对话内容框
TextMeshProUGUI dialogueContent;
//名称框
TextMeshProUGUI dialogueName;
//头像框
Image dialogueImage;
private void Awake() {
gameObject.SetActive(false);
}
private void OnEnable()
{
dialogue = TalkButton.instance.dialogue;
dialogueContent = transform.Find("内容").GetComponent<TextMeshProUGUI>();
dialogueName = transform.Find("名字").GetComponent<TextMeshProUGUI>();
dialogueImage = transform.Find("头像").GetComponent<Image>();
//设置人物头像保持宽高比,防止压缩变形
dialogueImage.preserveAspect = true;
index = 0;
Play();
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.R) && dialogue != null)
{
//对话播放完,关闭对话
if (index == dialogue.dialogNodes.Length)
{
gameObject.SetActive(false);
index = 0;
}
else
{
//开始对话
Play();
}
}
}
// Play 函数用于开始播放对话。
private void Play()
{
// 获取当前对话节点,并更新索引值。
DialogNode node = dialogue.dialogNodes[index++];
// 设置对话内容、角色名称和头像
dialogueContent.text = node.content;
dialogueName.text = node.name;
dialogueImage.sprite = node.sprite;
}
}
效果如下:
逐字打印效果
修改DialogSystem,创建协程实现逐字打印效果,
我们要加判断,每一行执行完成后才可以继续进入下一段对话
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class DialogSystem : MonoBehaviour
{
[SerializeField, Header("目前逐字打印速度")]
private float textSpeed;
private float startTextSpeed;//开始逐字打印速度
private Dialogue dialogue;//对话内容
//索引
private int index;
//对话内容框
TextMeshProUGUI dialogueContent;
//名称框
TextMeshProUGUI dialogueName;
//头像框
Image dialogueImage;
bool isDialogue;//是否正在对话
private void OnEnable()
{
dialogue = TalkTrigger.instance.dialogue;
dialogueContent = transform.Find("内容").GetComponent<TextMeshProUGUI>();
dialogueName = transform.Find("名字").GetComponent<TextMeshProUGUI>();
dialogueImage = transform.Find("头像").GetComponent<Image>();
//设置人物头像保持宽高比,防止压缩变形
dialogueImage.preserveAspect = true;
isDialogue = false;
startTextSpeed = textSpeed;
index = 0;
Play();
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.R) && dialogue != null)
{
//如果正在对话,再次按下R,快速显示所有对话
if (isDialogue)
{
textSpeed = 0;
}
else
{
//回复文本速度
textSpeed = startTextSpeed;
//对话播放完,关闭对话
if (index == dialogue.dialogNodes.Length)
{
gameObject.SetActive(false);
index = 0;
}
else
{
//开始对话
Play();
}
}
}
}
// Play 函数用于开始播放对话。
private void Play()
{
// 获取当前对话节点,并更新索引值。
DialogNode node = dialogue.dialogNodes[index++];
// 设置对话内容、角色名称和头像
// dialogueContent.text = node.content;
StartCoroutine(SetTextUI(node));
dialogueName.text = node.name;
dialogueImage.sprite = node.sprite;
}
//逐字打印
IEnumerator SetTextUI(DialogNode node)
{
isDialogue = true;
dialogueContent.text = "";
for (int i = 0; i < node.content.Length; i++)
{
dialogueContent.text += node.content[i];
yield return new WaitForSeconds(textSpeed);
}
isDialogue = false;
}
}
记得在面板配置textSpeed值,就可以实现不同的速度逐字显示文字啦
效果如下:
按下按键跳过文本
修改DialogSystem,我们通过控制文本播放速度实现
private void Update()
{
if (Input.GetKeyDown(KeyCode.R) && dialogue != null)
{
//如果正在对话,再次按下R,快速显示所有对话
if (isDialogue)
{
textSpeed = 0;
}
else
{
//回复文本速度
textSpeed = startTextSpeed;
//对话播放完,关闭对话
if (index == dialogue.dialogNodes.Length)
{
gameObject.SetActive(false);
index = 0;
}
else
{
//开始对话
Play();
}
}
}
}
效果如下:
不同的对话文件读入探索
TextAsset 读取文档文件
TextAsset 是把一种某种格式的文件输入到我们的游戏项目当中,支持的类型有:
.txt
.html
.htm
.xml
.bytes
.json
.csv
.yaml
.fnt
这也是一种读取对话文件的方法,例如:
public class DialogSystem : MonoBehaviour
{
[Header("文本文件")]
public TextAsset textFile; // 用于存储对话文本的文本文件
public int index; // 对话索引,用于跟踪当前对话位置
List<string> textList = new List<string>(); // 存储从文本文件中读取的对话内容的列表
void Start()
{
GetTextFromFile(textFile);
}
void GetTextFromFile(TextAsset file)
{
var lineData = file.text.Split('\n'); // 将文本文件按行分割
foreach (var line in lineData)
{
textList.Add(line); // 将每行对话文本添加到对话内容列表中
}
}
}
修改字体样式
可以支持Rich Text
<color=red>红色</color>
<color=#FF0000>红色</color>
<color=rgb(255,0,0)>红色</color>
<b>加粗</b>
<i>斜体</i>
<size=30>大号</size>
和markdown很像
既可以用代码控制,也可以直接unity编写文字的时候添加进去
效果:
文章来源:https://www.toymoban.com/news/detail-824626.html
争优亮点
- 美观的素材/UI界面,有游戏的美感,风格类似《星谷露物语》,精心设计美术元素,值得优秀
- 善于游戏程序设计技术,参考网上资料与unity官方文档,提出了一种通用易拓展的对话系统,精心设计了数据结构与脚本对象元素,代码结构清晰,通用性强,易于拓展(例如增加对话的其他属性、与txt xml json格式文本数据结合)
- 擅长写技术普及博客,本学期所有的技术博客,都有详细的视频演示、思路分析、代码分析、图文并茂、附带源码,方便初学者理解并迅速复现
源码
已在GITHUB开源:repo文章来源地址https://www.toymoban.com/news/detail-824626.html
到了这里,关于Unity:美观通用易扩展的对话系统的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!