上一篇里面,我们初次接触了 ink 语言,并且完成了一段非常简单的代码。在这一篇中,我们要试着将它放到 Unity 里面去跑一下!
Unity 插件
inkle 提供了将 ink 整合到 Unity 中的插件,我们可以到如下地址下载:
ink Unity 插件
去下载我们下载的是 v 0.8.1 的稳定版。UnityInkIntegration0.8.1.unitypackage
准备我们的 Unity 项目
创建一个新的 2D 项目,并且保存 Scene
为 Main
,然后引入 Unity 插件。
再把我们上一篇完成的 ink demo 拖进项目,我们的叫做 demo.ink
。
引入 ink 文件之后,会自动编译成 JSON 的可用格式,我们的素材库看起来会像下面这样:
然后创建 Canvas
画布并且增加两个必要的元素:Button
(按钮)和 Text
(文本),并且将它们做成 Prefab
,供后面使用。按钮是用来显示选项并做出选择的,而文本使用来显示基本内容的。
因为要使用 Prefab
所以将 Canvas
清空即可,然后给 Canvas
增加 C# 脚本,取名 Script.cs
吧!
这样,我们的素材就准备完毕了:
其实 ink 脚本引入以后,是可以直接在 Unity 中测试的。选中 .ink
文件,属性栏里面就会出现 Play
按钮,可以直接运行并测试。
编写脚本
脚本代码如下,已经添加了注释:
using UnityEngine; using Ink.Runtime; public class Script: MonoBehaviour { // ink JSON [SerializeField] private TextAsset inkFile; // 画布 [SerializeField] private Canvas canvas; // ink 故事 private Story _inkStory; // 是否需要新的故事片段 private bool _storyNeeded; // 距离(用来确定内容和按钮位置) private int _padding = 10; /* UI Prefabs */ // 文本 [SerializeField] private UnityEngine.UI.Text text; // 按钮 [SerializeField] private UnityEngine.UI.Button btnChoice; // 初始化 private void Awake() { _storyNeeded = true; _inkStory = new Story(inkFile.text); // 设置玩家名称 _inkStory.variablesState["player_name"] = "Someone"; } // Update is called once per frame private void Update() { if (!_storyNeeded) return; // 清空画布内容 RemoveChildren(); // 各个元素的偏移,需重新计算 float vOffset = 0; // 如果故事可以继续 if (_inkStory.canContinue) { var storyText = Instantiate(text); // 取得要显示的文字 storyText.text = _inkStory.Continue(); // 定位相关 storyText.transform.SetParent(canvas.transform, false); storyText.transform.Translate(new Vector2(0, vOffset)); vOffset -= (storyText.fontSize + _padding); } // 如果有多个选择,那么逐个处理 if (_inkStory.currentChoices.Count > 0) { for (var i = 0; i < _inkStory.currentChoices.Count; i++) { // 定位相关 var choiceButton = Instantiate(btnChoice); choiceButton.transform.SetParent(canvas.transform, false); choiceButton.transform.Translate(new Vector2(0, vOffset)); // 取得选择 var choice = _inkStory.currentChoices[i]; // 设置按钮的选择文本 var choiceText = choiceButton.GetComponentInChildren<UnityEngine.UI.Text>(); choiceText.text = choice.text; // 定位相关 var layoutGroup = choiceButton.GetComponent<UnityEngine.UI.HorizontalLayoutGroup>(); vOffset -= (choiceText.fontSize + layoutGroup.padding.top + layoutGroup.padding.bottom + _padding); // 获取按钮点击后对应的路径 var path = choice.pathStringOnChoice; choiceButton.onClick.AddListener(delegate { ChoicePathSelected(path); }); } } // 本次操作完成,等待响应 _storyNeeded = false; } /// <summary> /// 清空画布内容 /// </summary> private void RemoveChildren() { var childCount = canvas.transform.childCount; for (var i = childCount - 1; i >= 0; --i) { Destroy(canvas.transform.GetChild(i).gameObject); } } /// <summary> /// 选择路径 /// </summary> /// <param name="path">路径名称</param> private void ChoicePathSelected(string path) { _inkStory.ChoosePathString(path); _inkStory.Continue(); _storyNeeded = true; } }
代码还是很简单的,基本上跟官方提供的差不多,我们加入了:
_inkStory.variablesState["player_name"]
来进行玩家名称的设置,并且通过 path
来进行导航。
收尾工作
我们回到 Unity 编辑界面,将程序运行所需要的对象一一绑定,如图所示:
不过这还没有完,我们需要给按钮和文本加上自动居中的设置,并且做一些边距控制颜色调整等等的美化工作,基本上是这样:
如果一切顺利,就可以跑啦:
项目文件
如果懒得自己尝试,那么我们也提供了源代码供您下载使用:
项目源代码
去下载结束语
好了,这一次的 ink 初次尝试就完了啦,后续有什么问题或者需要交流的,请前往我们设立的小组继续探讨:
暂无关于此文章的评论。