Unity 2D對話系統 - 使用Ink標籤的名字、肖像和布局 | Unity + Ink 教程
目录
- 介绍 🌟
- 简介 📚
- 主要内容 🔍
- 创建NPC角色名称和头像布局系统 💬
- 使用标签设置对话框显示名称 📜
- 使用标签设置NPC头像和布局 🎭
- 切换NPC角色和布局 🔄
- 重置对话框和NPC信息 ♻️
- 总结和建议 💡
介绍 🌟
在这个视频教程中,我将向您展示一个简单但高效的方法,用于在Unity中显示和管理NPC名称、头像和不同的对话框布局系统。通过该视频,我们将构建一个系统,可以轻松地为每一行对话更改头像和名称,并且可以轻松更改对话框面板的布局,使得头像和名称可以在左侧或右侧显示。在这个视频中,我将使用前一个视频中构建的对话系统作为本教程的起点。因此,如果您刚开始构建对话系统并需要一个起点,我强烈建议您先观看另一个视频,然后再回到本教程。同时,我们将使用ink来编写对话内容,它在我们管理NPC名称、头像和布局方面起着非常重要的作用。
简介 📚
在本教程中,我们将学习如何使用ink标签在Unity中设置和管理NPC名称、头像和对话框布局。我们将通过编写一段简单的对话代码来演示如何使用标签,并使用C#代码来控制对话框的显示和更新。我们还将介绍如何在Unity的Animator控制器中设置头像和布局的动画。通过学习这些内容,您将能够为您的Unity游戏创建一个灵活而可定制的对话系统。
主要内容 🔍
创建NPC角色名称和头像布局系统 💬
在本节中,我们将介绍如何在Unity中创建NPC角色名称和头像布局系统。我们将使用Unity的UI组件来创建对话框面板,并使用Ink标签来设置NPC角色的名称和头像。通过这个系统,我们可以轻松地更改对话框面板上的显示名称和头像。
使用标签设置对话框显示名称 📜
在本节中,我们将学习如何使用Ink标签来设置对话框的显示名称。我们将根据对话行的标签中的值,设置对话框面板上的显示名称文本。这将使我们能够通过更改标签中的值来实时更新对话框的显示名称。
使用标签设置NPC头像和布局 🎭
在本节中,我们将介绍如何使用Ink标签来设置NPC的头像和布局。我们将在Unity的Animator控制器中创建动画状态,并使用Ink标签来触发和更改这些动画状态。通过这个系统,我们可以根据对话行中的标签来实时更改NPC的头像和布局。
切换NPC角色和布局 🔄
在本节中,我们将学习如何切换NPC角色和对话框布局。我们将使用C#代码来控制对话的进行,并根据需要更改NPC角色的标签和Animator状态。通过这个系统,我们可以实现对话行之间的平滑过渡和灵活的NPC角色切换。
重置对话框和NPC信息 ♻️
在本节中,我们将介绍如何重置对话框和NPC信息。我们将使用C#代码来重置对话框面板的显示名称、头像和布局,以及NPC角色的信息。通过这个系统,我们可以确保每次开始对话时,所有的信息都被重置为默认值。
总结和建议 💡
在本节中,我们将对整个教程进行总结,并提供一些建议来进一步完善和定制您的对话系统。我们将讨论遇到的一些常见问题,并提供解决方案和建议。我们还将分享一些额外的资源和参考资料,以帮助您进一步学习和探索这个主题。
这是我们在本教程中将涵盖的主要内容。希望这个教程对您有所帮助,并能为您的游戏开发工作提供一些有价值的见解和技巧。
创建NPC角色名称和头像布局系统 💬
在这一节中,我们将学习如何在Unity中创建NPC角色名称和头像布局系统。我们将使用Unity的UI组件来创建一个对话框面板,并在面板上显示NPC角色的名称和头像。这个系统将帮助我们轻松地更改对话框面板上的显示名称和头像,以适应不同的对话场景。
首先,我们将创建一个用于显示名称的UI文本组件。右键单击对话框面板,选择"UI",然后选择"文本(TextMeshPro)"。我们将把这个文本组件命名为"显示名称文本"。然后,在场景编辑器中将它拖动到适当的位置,并调整它的大小和样式。
接下来,我们将创建一个用于显示头像的图像组件。在对话框面板上右键单击,选择"UI",然后选择"图像(Image)"。我们将把这个图像组件命名为"头像图像"。然后,我们可以从资源文件夹中将适当的头像图像拖动到图像组件的"源图像"槽中。
现在,我们已经创建了用于显示名称和头像的UI组件。接下来,我们需要编写代码来控制这些组件的显示和更新。我们将使用C#脚本来实现这个功能,并将脚本附加到对话框面板上。
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class DialogPanel : MonoBehaviour
{
public TextMeshProUGUI displayNameText;
public Image portraitImage;
public void SetDisplayName(string displayName)
{
displayNameText.text = displayName;
}
public void SetPortrait(Sprite portrait)
{
portraitImage.sprite = portrait;
}
}
在这个脚本中,我们定义了两个公共方法来设置显示名称和头像。当调用这些方法时,脚本将更新UI组件的显示内容,以反映新的名称和头像。在Unity中,我们可以将这个脚本附加到对话框面板上,并将显示名称文本和头像图像分配给相应的UI组件。
现在,我们已经创建了NPC角色名称和头像布局系统所需的所有组件和代码。在接下来的节目中,我们将学习如何使用Ink标签和C#代码来设置和更新这些组件,以实现动态的对话场景。让我们继续进行下一步吧!
使用标签设置对话框显示名称 📜
在这一节中,我们将学习如何使用Ink标签来设置对话框的显示名称。我们将在对话文件中添加标签,然后在Unity中读取这些标签,并将它们设置为对话框面板上显示名称的文本。
首先,我们需要在Ink对话文件中添加用于设置显示名称的标签。在对话文件中,我们可以使用"#speaker:显示名称"的格式来添加标签。这将告诉Unity将显示名称文本设置为标签中的值。
接下来,我们需要在Unity的脚本中读取和处理这些标签。我们将使用Ink插件提供的方法来读取和解析对话文件中的标签,并将它们传递给对话框面板脚本来更新显示名称。
using System.Collections;
using System.Collections.Generic;
using Ink.Runtime;
using TMPro;
using UnityEngine;
public class DialogManager : MonoBehaviour
{
public TextAsset inkFile;
public DialogPanel dialogPanel;
private Story story;
// Start is called before the first frame update
void Start()
{
story = new Story(inkFile.text);
StartDialog();
}
public void StartDialog()
{
dialogPanel.SetDisplayName(GetCurrentSpeaker());
ContinueStory();
}
public void ContinueStory()
{
string currentText = story.Continue();
// TODO: Handle other story events and choices
// ...
}
private string GetCurrentSpeaker()
{
List<string> tags = story.currentTags; // Get the tags for the current line of dialog
string speakerTag = tags.Find(tag => tag.StartsWith("#speaker:")); // Find the speaker tag
if (speakerTag != null)
{
string[] tagParts = speakerTag.Split(':'); // Split the tag into parts
return tagParts[1]; // Return the value of the tag
}
else
{
return ""; // Return an empty string if no speaker tag is found
}
}
}
在这个脚本中,我们首先创建了一个Story对象,该对象负责加载和解析Ink对话文件。然后,我们在开始时调用StartDialog()方法来启动对话。在这个方法中,我们首先调用GetCurrentSpeaker()方法来获取当前对话的说话者,并将这个值传递给对话框面板脚本的SetDisplayName()方法,以更新显示名称。
接下来,在ContinueStory()方法中,我们使用Story对象的Continue()方法来继续对话。在这里,我们可以添加适当的代码来处理其他对话事件和选择。在这个例子中,我们只处理了显示名称的标签。
现在,我们已经设置了Ink标签,并将显示名称设置为对话框面板上的文本。接下来,我们将学习如何使用Ink标签来设置NPC头像和对话框布局。而在下一节中,我们将学习如何使用标签来实现这些功能。
使用标签设置NPC头像和布局 🎭
在这一节中,我们将学习如何使用Ink标签来设置NPC的头像和对话框布局。我们将在对话文件中添加标签,然后在Unity中读取和解析这些标签,并根据需要更改NPC的头像和对话框布局。
首先,我们需要在Ink对话文件中添加用于设置头像和布局的标签。在对话文件中,使用标签的格式为"#portrait:头像名称"和"#layout:布局名称"。这将告诉Unity在对话框面板上显示相应的头像并更改布局。
接下来,我们需要在Unity的脚本中读取和处理这些标签。我们将使用Ink插件提供的方法来读取标签,并将它们传递给对话框面板脚本来更新NPC的头像和对话框布局。
using System.Collections;
using System.Collections.Generic;
using Ink.Runtime;
using TMPro;
using UnityEngine;
public class DialogManager : MonoBehaviour
{
public TextAsset inkFile;
public DialogPanel dialogPanel;
public Animator portraitAnimator;
public Animator layoutAnimator;
private Story story;
// Start is called before the first frame update
void Start()
{
story = new Story(inkFile.text);
StartDialog();
}
public void StartDialog()
{
dialogPanel.SetDisplayName(GetCurrentSpeaker());
SetPortrait(GetCurrentPortrait());
SetLayout(GetCurrentLayout());
ContinueStory();
}
public void ContinueStory()
{
string currentText = story.Continue();
// TODO: Handle other story events and choices
// ...
}
private string GetCurrentSpeaker()
{
List<string> tags = story.currentTags; // Get the tags for the current line of dialog
string speakerTag = tags.Find(tag => tag.StartsWith("#speaker:")); // Find the speaker tag
if (speakerTag != null)
{
string[] tagParts = speakerTag.Split(':'); // Split the tag into parts
return tagParts[1]; // Return the value of the tag
}
else
{
return ""; // Return an empty string if no speaker tag is found
}
}
private string GetCurrentPortrait()
{
List<string> tags = story.currentTags; // Get the tags for the current line of dialog
string portraitTag = tags.Find(tag => tag.StartsWith("#portrait:")); // Find the portrait tag
if (portraitTag != null)
{
string[] tagParts = portraitTag.Split(':'); // Split the tag into parts
return tagParts[1]; // Return the value of the tag
}
else
{
return ""; // Return an empty string if no portrait tag is found
}
}
private string GetCurrentLayout()
{
List<string> tags = story.currentTags; // Get the tags for the current line of dialog
string layoutTag = tags.Find(tag => tag.StartsWith("#layout:")); // Find the layout tag
if (layoutTag != null)
{
string[] tagParts = layoutTag.Split(':'); // Split the tag into parts
return tagParts[1]; // Return the value of the tag
}
else
{
return ""; // Return an empty string if no layout tag is found
}
}
private void SetPortrait(string portrait)
{
portraitAnimator.Play(portrait); // Play the animation based on the portrait tag
}
private void SetLayout(string layout)
{
layoutAnimator.Play(layout); // Play the animation based on the layout tag
}
}
在这个脚本中,我们添加了两个新的私有方法,分别用于获取当前对话行中的头像和布局标签。我们使用相同的方式来解析这些标签,并将它们传递给对话框面板脚本的SetPortrait()和SetLayout()方法来更新NPC的头像和对话框布局。
我们还添加了两个Animator组件的引用,分别用于控制头像和布局的动画。在SetPortrait()和SetLayout()方法中,我们使用Animator的Play()方法来根据标签的值播放相应的动画。
现在,在ContinueStory()方法中,我们可以调用这些新的方法来更新对话框面板上的头像和布局。将这些方法添加到StartDialog()方法中,以便在对话开始时设置头像和布局。
接下来,在Unity中,将对话文件和对话框面板脚本分配给相应的引用,并将Animator组件分配给头像和布局的引用。
现在,当我们运行对话时,我们会发现NPC的头像和对话框布局会根据对话行中的标签而改变。这个功能允许我们根据需要动态地切换NPC的外观和对话框布局。
接下来,我们将学习如何在对话中切换NPC角色和布局。在下一节中,我们将学习如何使用C#代码来实现这个功能。
切换NPC角色和布局 🔄
在这一节中,我们将学习如何在对话中切换NPC角色和对话框布局。我们将使用C#代码来控制对话的进行,并根据需要更改NPC的角色和布局。
首先,我们需要在Ink对话文件中添加一些特殊的标签,用于切换NPC角色和对话框布局。在对话文件中,我们将使用"#speaker:角色名称"来切换角色,并使用"#layout:布局名称"来切换布局。这将告诉Unity在对话过程中更改NPC的角色和对话框布局。
接下来,我们需要在Unity的脚本中读取和处理这些标签。我们将使用Ink插件提供的方法来读取标签,并使用C#代码来控制角色的切换和动画布局。
using System.Collections;
using System.Collections.Generic;
using Ink.Runtime;
using TMPro;
using UnityEngine;
public class DialogManager : MonoBehaviour
{
public TextAsset inkFile;
public DialogPanel dialogPanel;
public Animator portraitAnimator;
public Animator layoutAnimator;
private Story story;
// Start is called before the first frame update
void Start()
{
story = new Story(inkFile.text);
StartDialog();
}
public void StartDialog()
{
dialogPanel.SetDisplayName(GetCurrentSpeaker());
SetPortrait(GetCurrentPortrait());
SetLayout(GetCurrentLayout());
ContinueStory();
}
public void ContinueStory()
{
string currentText = story.Continue();
// TODO: Handle other story events and choices
// Check for speaker tag
if (currentText.Contains("#speaker:"))
{
string[] textParts = currentText.Split('\n');
string speakerTag = textParts[0].Substring(1);
string[] tagParts = speakerTag.Split(':');
string speaker = tagParts[1];
dialogPanel.SetDisplayName(speaker);
SetPortrait(GetCurrentPortrait());
SetLayout(GetCurrentLayout());
}
else
{
dialogPanel.SetDialogText(currentText);
}
}
private string GetCurrentSpeaker()
{
List<string> tags = story.currentTags; // Get the tags for the current line of dialog
string speakerTag = tags.Find(tag => tag.StartsWith("#speaker:")); // Find the speaker tag
if (speakerTag != null)
{
string[] tagParts = speakerTag.Split(':'); // Split the tag into parts
return tagParts[1]; // Return the value of the tag
}
else
{
return ""; // Return an empty string if no speaker tag is found
}
}
private string GetCurrentPortrait()
{
List<string> tags = story.currentTags; // Get the tags for the current line of dialog
string portraitTag = tags.Find(tag => tag.StartsWith("#portrait:")); // Find the portrait tag
if (portraitTag != null)
{
string[] tagParts = portraitTag.Split(':'); // Split the tag into parts
return tagParts[1]; // Return the value of the tag
}
else
{
return ""; // Return an empty string if no portrait tag is found
}
}
private string GetCurrentLayout()
{
List<string> tags = story.currentTags; // Get the tags for the current line of dialog
string layoutTag = tags.Find(tag => tag.StartsWith("#layout:")); // Find the layout tag
if (layoutTag != null)
{
string[] tagParts = layoutTag.Split(':'); // Split the tag into parts
return tagParts[1]; // Return the value of the tag
}
else
{
return ""; // Return an empty string if no layout tag is found
}
}
private void SetPortrait(string portrait)
{
portraitAnimator.Play(portrait); // Play the animation based on the portrait tag
}
private void SetLayout(string layout)
{
layoutAnimator.Play(layout); // Play the animation based on the layout tag
}
}
在这个脚本中,我们修改了ContinueStory()方法,以便在每行对话中检查标签,并根据需要更新NPC角色和对话框布局。我们提取了标签的内容,并使用相同的逻辑来解析标签,并将其应用于NPC角色和布局。
现在,当我们运行对话时,我们会发现NPC角色和对话框布局会根据对话行中的标签而改变。这允许我们在对话的不同阶段切换NPC的外观和对话框布局。
在下一节中,我们将学习如何在对话开始时重置对话框和NPC信息,以确保每次开始对话时都有一个干净的状态。
重置对话框和NPC信息 ♻️
在这一节中,我们将学习如何在对话开始时重置对话框和NPC信息,以确保每次开始对话时都有一个干净的状态。我们将通过在对话开始时调用一个新的方法来实现这个功能。
首先,我们需要在对话开始时调用一个新的方法来重置对话框和NPC信息。在DialogManager脚本中,我们将添加一个新的公共方法ResetDialog(),在开始对话之前调用这个方法。
using System.Collections;
using System.Collections.Generic;
using Ink.Runtime;
using TMPro;
using UnityEngine;
public class DialogManager : MonoBehaviour
{
public TextAsset inkFile;
public DialogPanel dialogPanel;
public Animator portraitAnimator;
public Animator layoutAnimator;
private Story story;
// Start is called before the first frame update
void Start()
{
story = new Story(inkFile.text);
StartDialog();
}
public void StartDialog()
{
ResetDialog();
dialogPanel.SetDisplayName(GetCurrentSpeaker());
SetPortrait(GetCurrentPortrait());
SetLayout(GetCurrentLayout());
ContinueStory();
}
public void ContinueStory()
{
string currentText = story.Continue();
// TODO: Handle other story events and choices
// Check for speaker tag
if (currentText.Contains("#speaker:"))
{
string[] textParts = currentText.Split('\n');
string speakerTag = textParts[0].Substring(1);
string[] tagParts = speakerTag.Split(':');
string speaker = tagParts[1];
dialogPanel.SetDisplayName(speaker);
SetPortrait(GetCurrentPortrait());
SetLayout(GetCurrentLayout());
}
else
{
dialogPanel.SetDialogText(currentText);
}
}
public void ResetDialog()
{
dialogPanel.SetDisplayName("");
SetPortrait("Default");
SetLayout("Default");
}
private string GetCurrentSpeaker()
{
List<string> tags = story.currentTags; // Get the tags for the current line of dialog
string speakerTag = tags.Find(tag => tag.StartsWith("#speaker:")); // Find the speaker tag
if (speakerTag != null)
{
string[] tagParts = speakerTag.Split(':'); // Split the tag into parts
return tagParts[1]; // Return the value of the tag
}
else
{
return ""; // Return an empty string if no speaker tag is found
}
}
private string GetCurrentPortrait()
{
List<string> tags = story.currentTags; // Get the tags for the current line of dialog
string portraitTag = tags.Find(tag => tag.StartsWith("#portrait:")); // Find the portrait tag
if (portraitTag != null)
{
string[] tagParts = portraitTag.Split(':'); // Split the tag into parts
return tagParts[1]; // Return the value of the tag
}
else
{
return ""; // Return an empty string if no portrait tag is found
}
}
private string GetCurrentLayout()
{
List<string> tags = story.currentTags; // Get the tags for the current line of dialog
string layoutTag = tags.Find(tag => tag.StartsWith("#layout:")); // Find the layout tag
if (layoutTag != null)
{
string[] tagParts = layoutTag.Split(':'); // Split the tag into parts
return tagParts[1]; // Return the value of the tag
}
else
{
return ""; // Return an empty string if no layout tag is found
}
}
private void SetPortrait(string portrait)
{
portraitAnimator.Play(portrait); // Play the animation based on the portrait tag
}
private void SetLayout(string layout)
{
layoutAnimator.Play(layout); // Play the animation based on the layout tag
}
}
在这个脚本中,我们添加了一个新的公共方法ResetDialog(),用于重置对话框和NPC信息。在这个方法中,我们调用对话框面板脚本的SetDisplayName()、SetPortrait()和SetLayout()方法,将它们的值设置为默认值。这样,每次开始对话时,对话框和NPC信息都会被重置为干净的状态。
现在,我们已经学习了如何创建NPC角色名称和头像布局系统,如何使用标签设置对话框显示名称和NPC头像和布局,以及如何在对话中切换NPC角色和对话框布局。在下一节中,我们将总结教程,并提供一些建议和建议,以帮助您进一步完善和定制您的对话系统。
总结和建议 💡
在这个教程中,我们学习了如何使用Ink标签和C#代码来创建一个灵活和可定制的NPC对话系统。我们使用Unity的UI组件来创建对话框面板,使用Ink标签来设置NPC的名称、头像和布局,并使用C#代码来控制和更新这些信息。
我们首先创建了一个简单的NPC角色名称和头像布局系统,该系统允许我们根据需要更改对话框面板上的显示名称和头像。然后,我们学习了如何使用Ink标签来设置NPC的头像和布局,以实现更具动态性的对话场景。
接下来,我们学习了如何使用C#代码来切换NPC角色和对话框布局。这个功能允许我们在对话的不同阶段切换NPC的外观和对话框布局,并创建更多样化的对话情景。
最后,我们学习了如何在对话开始时重置对话框和NPC信息,以确保每次开始对话时都有一个干净的状态。这可以帮助我们避免在对话之间保留旧的NPC信息,以及清除可能在切换NPC时产生的任何错误。
在使用这个教程中学到的知识的基础上,您可以进一步探索和完善您的对话系统。您可以添加更多的NPC角色、头像和布局选项,扩展对话系统的功能,并丰富游戏的故事情节。
希望这个教程对您有所帮助,并且能够为您的游戏开发工作提供一些有价值的见解和技巧。如果您有任何问题或疑问,请随时提问。祝您游戏开发愉快!
常见问题解答
问题 1:如何添加更多的NPC角色和头像?
要添加更多的NPC角色和头像,您可以按照以下步骤操作:
- 在Unity的资源文件夹中,创建一个新的文件夹来存储NPC角色的头像图片。
- 将每个NPC角色的头像图片拖放到相应的文件夹中。
- 在Ink对话文件中,为每个NPC角色添加标签,并将头像标签的值设置为其名称。
- 在Unity的脚本中,为每个NPC角色创建一个新的Animator,然后将每个Animator分配给相应的NPC角色。
通过这些步骤,您将能够添加更多的NPC角色和头像选项,以丰富游戏的对话情节。
问题 2:如何添加更多的对话布局选项?
要添加更多的对话布局选项,您可以按照以下步骤操作:
- 在Unity的资源文件夹中,创建一个新的文件夹来存储对话布局的动画控制器。
- 对每个对话布局创建一个新的Animator控制器,并将其命名为相应的布局选项。
- 在Animator控制器中,为每个布局选项创建相应的动画状态。
- 在Ink对话文件中,为每个对话布局添加标签,并将布局标签的值设置为其名称。
- 在Unity的脚本中,为每个对话布局创建一个新的Animator,然后将每个Animator分配给相应的对话布局。
通过这些步骤,您将能够添加更多的对话布局选项,以丰富游戏的对话情节。
问题 3:如何处理多选项的对话?
要处理多选项的对话,您可以按照以下步骤操作:
- 在Ink对话文件中,为每个选项创建一个标签,并将标签的值设置为选项的文本。
- 在Unity的脚本中,使用Ink Story对象的currentChoices属性获取当前对话行的选项。
- 在对话框面板上显示当前选项,并将每个选项分配给相应的按钮。
- 当玩家选择一个选项时,使用Ink Story对象的ChooseChoiceIndex方法获取选择的索引,并将其传递给Story对象以继续对话。
通过这些步骤,您将能够处理多选项的对话,为玩家提供更多的选择和交互。
问题 4:如何在对话系统中添加声音效果?
要在对话系统中添加声音效果,您可以按照以下步骤操作:
- 在Unity的资源文件夹中,创建一个新的文件夹来存储声音效果的音频文件。
- 将每个声音效果的音频文件拖放到相应的文件夹中。
- 在Unity的脚本中,使用AudioSource组件来处理声音效果的播放。在需要播放声音效果的时候,调用AudioSource.Play()方法,并传递相应的音频文件。
通过这些步骤,您将能够为对话系统添加声音效果,增强游戏的沉浸感和交互性。