07变量,自定义姓名,好感度,flag
本教程由水螅制作,教程内所有提供下载的练习素材皆为水螅制作,只可用于练习,不可用于其他用途。
那么开始今天的内容,首先我们来做一个自定义姓名的界面,大概长这样,需要增加的素材是ui_bt.png
看起来有点单调,因为我希望尽可能少的使用额外的素材。你在做自己的姓名输入界面时可以加入自己的图片和设计来让它好看一点。
到现在大家对于用工具组拉界面应该已经很熟练了吧。
在canvas上右键增加一个和屏幕等大的image,命名为ui_editname,设定一下颜色。顺便给它添加上canvas group的component
在ui_editname上右键给它添加一个InputField
我将InputField的背景图片由默认换为了我们之前持有的ui_bg.png来让它看起来柔和一点,你也可以将之换为自己设计的图片。
将它拉动到合适的位置和大小,
因为是姓名输入,不能够让玩家可以无限的输入文字,所以把它的character limit设定在5个字
顺便一提这个字数限定在手机上会变成只能输入五个字母的拼音而没办法用,需要用其他方式来进行字数限制。不过目前我们的目标只是完成一个在windows下可以正常跑的游戏,所以就直接用这个就好。
然后可以来看一下它的子object有Placeholder和Text两个,
Placeholder是用来显示输入提示文字的,我们将它的文字改为“请输入主角姓名”,并且将文字的字号和对齐等适当的改成自己想要的样子
将Text的字号颜色和对齐也相对的进行修改,如果你需要查看效果,可以在inputfield的text里输入文字来查看
编辑得差不多和预期一致后,在ui_editname上右键再增加一个button,将button的图片更换为切割好九宫格(在教程3讲过)的ui_bt.png,同样的,如果你有自己设计好的按钮图片,可以用自己的。
将按钮拉动到合适的尺寸和位置,在它的子Text里写上“确定”
这样姓名输入界面就像最上边的图一样做好了。和往常一样,为它增加淡入淡出的动画和function(已经做了很多遍同样的操作了呢),function名字就叫做editnamefadein和editnamefadeout好了。
void editnamefadein()
{
GameObject temp = GameObject.Find("ui_editname");
Animator an = temp.GetComponent<Animator>();
an.SetInteger("a_num", 1);
}
public void editnamefadeout()
{
GameObject temp = GameObject.Find("ui_editname");
Animator an = temp.GetComponent<Animator>();
an.SetInteger("a_num", 2);
StartCoroutine(waittime(1f));
}
给确定按钮挂载上editnamefadeout的事件(给按钮挂载事件见教程2),如果你不想在界面上操作,那么和教程6一样使用代码挂载事件也是一样的。
编辑主角姓名应该在开始界面之后和开始剧情之前,所以我们的脚本加入一行
@bg1fadein storage=op1
@opbtfadein
@editnamefadein
@bg1fadein storage=bg1
@fg1fadein storage=fg1 n=0
@dialogfadein
你吃不吃包子?
@textfadein
@selectfadein text1=吃 text2=不吃 target1=*t1 target2=*t2
*t1
@textfadeout
那就分你一半。
@jumpscript target=*c1
*t2
@textfadeout
不吃饱会长不高的。
*c1
@textfadein
@textfadeout
@dialogfadeout
@fg1fadeout
@bg1fadeout
但是现在有个问题,那就是输入到姓名界面的姓名,并没有被保存在任何地方。所以我们需要在结束姓名输入界面的editnamefadeout里边加入将姓名保存在变量里的代码。
//建立一个用来储存游戏变量的字典,为了让用krkr的人感觉更亲切一些,我给这个字典起名叫f
Dictionary<string, string> f = new Dictionary<string, string>();
public void editnamefadeout()
{
GameObject temp = GameObject.Find("ui_editname");
//将玩家输入的姓名起名叫name放入储存变量的字典里,字典里的变量名字(key)也可以是中文的,不过还是推荐使用英文。
f["name"] = temp.transform.Find("InputField").gameObject.GetComponent<InputField>().text;
Animator an = temp.GetComponent<Animator>();
an.SetInteger("a_num", 2);
StartCoroutine(waittime(1f));
}
现在我们的canvas下边应该是这样的
不知不觉得增加了很多东西呢。
那么我们来跑一下吧~~~
发现开始界面的按钮点不到了=口=
canvas下边放了这么多东西就是会这样的啊哈哈哈哈,虽然所有的界面默认状态都是透明的,但是他们依然会拦截点击事件,ui_opbt在ui_editname下边,所以就被ui_editname挡住了,虽然ui_editname现在是透明,但是就像是一块透明玻璃板一样挡住了鼠标的点击,会导致下边的界面全部都无法点击的。
解决的方法有很多种,比较方便的是将ui_editname的active设为false或者直接删掉ui_editname。我们采取第一种方法。
在hierarchy里选中ui_editname,在inspector里边把这个小勾选掉。
这样ui_editname的active就是false了,场景中相当于不再存在这个东西,不会描绘它也不会计算它。
但是我们还需要当用得到的时候它的active变成true,所以就要修改它的editnamefadein
void editnamefadein()
{
//以往用的Gameobject.Find无法获取active是false的gameobject,一定要先获取ui_editname的父object “Canvas”,然后通过它的transform来寻找到没有被激活的ui_editname
GameObject temp = GameObject.Find("Canvas").transform.Find("ui_editname").gameObject;
//将它激活
temp.SetActive(true);
Animator an = temp.GetComponent<Animator>();
an.SetInteger("a_num", 1);
}
然后我们需要在editnamefadeout结束的时候将它的active回复成false。
虽然有很多种方法,不过这次我们也用以前用过的动画事件来解决吧。
我们选中ui_editname,查看它的animation界面,选择淡出动画editnamea2,这个动画我做的很简单,就完全是透明度改变而已。
我们希望的是,当动画播放到一秒钟完全淡出的那一帧的时候,执行一个function将ui_editname的active设为false。
首先我们在project的script文件夹里新建一个叫做uicontroller的c#文件,
打开它,为它添加一个叫做activefalse的function
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class uicontroller : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public void activefalse()
{
//这里的this指的是挂载了这个c#脚本的gameobject,比如把它挂在ui_editname上,这个this就指的是ui_editname,挂在ui_dialog上指的就是ui_dialog,一个脚本可以挂在多个gameobject上,他们的行为也不会相互影响
this.gameObject.SetActive(false);
}
}
然后将project里边的c#文件拖到hierarchy里边的ui_editname上,这样ui_editname的inspector里应该就会出现uicontroller了
然后在animation界面将时间轴放在1秒处,右键add animation event,时间轴上会出现一个白色的小方块表示这里要触发一个function
选中这个小方块让它变成蓝色,可以看到他的inspector里有个function的选项,展开列表,在列表的最下边可以看到我们刚写的activefalse,选中这个。
现在,再点击play,可以看到,游戏像我们期待的那样运行着
接下来,为了节省资源和避免冲突,将canvas下边的所有第一层object都像ui_editname那样设定一遍active吧
全部设定好并且正常运行后,我们发现……姓名框里什么也不输入就这么空着进入游戏也可以呢……
所以还要再修改一下挂在确定按钮上的editnamefadeout,让它检测一下,如果没有输入名字的话就没有反应
//建立一个用来储存游戏变量的字典,为了让用krkr的人感觉更亲切一些,我给这个字典起名叫f
Dictionary<string, string> f = new Dictionary<string, string>();
public void editnamefadeout()
{
GameObject temp = GameObject.Find("ui_editname");
//将玩家输入的姓名起名叫name放入储存变量的字典里,字典里的变量名字(key)也可以是中文的,不过还是推荐使用英文。
f["name"] = temp.transform.Find("InputField").gameObject.GetComponent<InputField>().text;
//如果传入的名字是空,就不执行下边的淡出动画
if (f["name"] =="")
{
return;
}
Animator an = temp.GetComponent<Animator>();
an.SetInteger("a_num", 2);
StartCoroutine(waittime(1f));
}
这样就可以了。然后我们来考虑一下下一步。既然记录了自定义的名字,那么肯定是想要在对话里显示这个名字的。
也就是说我们要操作之前设定好用来显示对话的dtext变量(如果忘了的话请回去看一下教程4)。
我们写一个叫做ch的function,把要求的变量值加在dtext末尾。
void ch(Dictionary<string ,string>elm)
{
dtext = dtext + f[elm["text"]];
startscript();
}
比如我们想要在对话框里写这么一句话“今天天气不错,(玩家名),你要吃包子吗?”
脚本上就是
今天天气不错,
@ch text=name
,你要吃包子吗?
可以看到,通过ch传入的elm[“text”]的值是name, f[elm["text"]]就相当于f[“name”]也就是我们之前记录在字典里的玩家自定义名。通过ch,不仅是玩家自定义的”name”,以后有别的储存的变量也可以直接这样显示出来,比如假设玩家有个攻击力的值f[“atk”],就可以通过
你的攻击力是
@ch text=atk
来显示在对话中。
由于ch对dtext进行了操作,之前简单的dtext的赋值也需要做一些修改。首先为了对话能够连贯,onscript()中的
dtext = line;
要改为
dtext = dtext + line;
这样才能把所有要显示的文字都连起来。
然后在显示完成后要将dtext清空
public void textfadein()
{
GameObject temp = GameObject.Find("ui_dialog_text");
//将dtext里边存的文字赋值给画面,为了能够使用Text,需要在文件头加上using UnityEngine.UI;
temp.GetComponent<Text>().text = dtext;
dtext = "";
Animator an = temp.GetComponent<Animator>();
an.SetInteger("a_num", 1);
//设定开始等待点击
onwaitclick = true;
}
将脚本改为
@bg1fadein storage=op1
@opbtfadein
@editnamefadein
@bg1fadein storage=bg1
@fg1fadein storage=fg1 n=0
@dialogfadein
今天天气不错,
@ch text=name
,你要吃包子吗?
@textfadein
@selectfadein text1=吃 text2=不吃 target1=*t1 target2=*t2
*t1
@textfadeout
那就分你一半。
@jumpscript target=*c1
*t2
@textfadeout
不吃饱会长不高的。
*c1
@textfadein
@textfadeout
@dialogfadeout
@fg1fadeout
@bg1fadeout
点一下play,顺利的显示了自定义的名字。
既然已经知道了变量的用法,那么这次就来试一试加上角色的好感度吧。一直不辞辛劳的在问我们要不要吃包子的这个小哥的名字叫做宿彦,那么他的好感度的名字就叫做xyfeel吧…………
我们写一个在游戏开始的时候会被调用的fuction来初始化各种需要的数值,当然目前就只有xyfeel这一个数值要进行初始化就是了……
void initf()
{
//c#是强类型语言,因为我们的字典在定义的时候是<string,string>也就是名字和值都是字符串,所以即使是好感度,也是要用”0”这个字符串而不是0来保存。在使用的时候也要再临时将字符串转换成数值才能使用。
f["xyfeel"] = "0";
startscript();
}
将脚本里刚输入完玩家名字,游戏开始的位置插入@initf,这样在游戏刚开始的时候,宿彦小哥的好感度就是0。
@bg1fadein storage=op1
@opbtfadein
@editnamefadein
@initf
@bg1fadein storage=bg1
@fg1fadein storage=fg1 n=0
@dialogfadein
今天天气不错,
@ch text=name
,你要吃包子吗?
@textfadein
@selectfadein text1=吃 text2=不吃 target1=*t1 target2=*t2
*t1
@textfadeout
那就分你一半。
@jumpscript target=*c1
*t2
@textfadeout
不吃饱会长不高的。
*c1
@textfadein
@textfadeout
@dialogfadeout
@fg1fadeout
@bg1fadeout
然后我们希望他问吃不吃包子的时候,选择吃好感度+1,选择不吃好感度不变。
我们来写一个给变量增加指定数值的function addvar,用于将一个值加在指定的变量上,这个值可以是整数,小数或负数。
为了能用将字符串和数字进行转换的Convert,我们需要在文件头写上
using System;
void addvar(Dictionary<string,string>elm)
{
double temp = Convert.ToDouble(f[elm["tar"]]);
double add= Convert.ToDouble(elm["num"]);
temp = temp + add;
f[elm["tar"]] = temp.ToString();
startscript();
}
这样增加好感度1的脚本应该是
@addvar tar=xyfeel num=1
把它插入选择了“吃”的标签后边
@bg1fadein storage=op1
@opbtfadein
@editnamefadein
@initf
@bg1fadein storage=bg1
@fg1fadein storage=fg1 n=0
@dialogfadein
今天天气不错,
@ch text=name
,你要吃包子吗?
@textfadein
@selectfadein text1=吃 text2=不吃 target1=*t1 target2=*t2
*t1
@addvar tar=xyfeel num=1
@textfadeout
那就分你一半。
@jumpscript target=*c1
*t2
@textfadeout
不吃饱会长不高的。
*c1
@textfadein
@textfadeout
现在我对你的好感度是
@ch text=xyfeel
。
@textfadein
@textfadeout
@dialogfadeout
@fg1fadeout
@bg1fadeout
然后试着来跑一下吧
现在我们来设计一组对话,需要好感度超过2且有一个flag的情况下才会进入he,否则是ne,flag的名字就命名为xyflag1好了。
我们要在initf里将flag也初始化。
void initf()
{
f["xyfeel"] = "0";
f["xyflag1"] = "0";
startscript();
}
脚本加入了三个选项,前两个是好感度,第三个是flag
@bg1fadein storage=op1
@opbtfadein
@editnamefadein
@initf
@bg1fadein storage=bg1
@fg1fadein storage=fg1 n=0
@dialogfadein
今天天气不错,
@ch text=name
,你要吃包子吗?
@textfadein
@selectfadein text1=吃 text2=不吃 target1=*t1 target2=*t2
*t1
@addvar tar=xyfeel num=1
@textfadeout
那就分你一半。
@jumpscript target=*c1
*t2
@textfadeout
不吃饱会长不高的。
*c1
@textfadein
@textfadeout
你喜欢的是梅菜肉包还是白菜肉包呢?
@textfadein
@selectfadein text1=梅菜肉包 text2=白菜肉包 target1=*t3 target2=*t4
*t3
@textfadeout
我比较喜欢白菜包。
@jumpscript target=*c2
*t4
@addvar tar=xyfeel num=1
@textfadeout
和我一样呢。
*c2
@textfadein
@textfadeout
你喜欢我吗?
@textfadein
@selectfadein text1=喜欢 text2=不喜欢 target1=*t5 target2=*t6
*t5
@addvar tar=xyflag1 num=1
@textfadeout
啊,是么。
@jumpscript target=*c3
*t6
@textfadeout
呃……这样啊…………
*c3
@textfadein
@textfadeout
@checkend
*end1
晚饭之后,请给我留一点时间。
@textfadein
@textfadeout
嗯,有些事情想要对你说。
@jumpscript target=*c4
*end2
嗯,我们算是很好的朋友吧。
*c4
@textfadein
@textfadeout
@dialogfadeout
@fg1fadeout
@bg1fadeout
增加了叫做checkend的function,用来判断好感度和flag到底够了没有
void checkend()
{
double feel = Convert.ToDouble(f["xyfeel"]);
double flag = Convert.ToDouble(f["xyflag1"]);
//只有好感度有2以上且触发了flag1的情况下才会进入end1,其他情况进入end2
if(feel>=2&&flag==1)
{
jumpscript1("*end1");
}
else
{
jumpscript1("*end2");
}
}
来play一下吧,可以看到选择对变量的影响和变量对结局的影响。
现在我们可以做的事情已经很多了,接下来会放慢速度,稍微回过头来完善一下演出,毕竟直到现在我们都只有一个面瘫的宿彦小哥……下次来加入对话框的名字显示,等待点击动画,多个角色同屏等功能吧。
Created by Hydrozoa.2011
不支持IE7以下浏览器
凯恩插件程序:Hydrozoa 美术:Hydrozoa,红渊