Unity教程之-Unity3d游戏剧情对话(二)

 

上篇文章《Unity教程之-Unity3d游戏剧情对话(一)》我们在CommandManager中直接写入一个个的指令,实际上这样是很不好的,因为一个游戏可能会出现很多的剧情动画,那么不就是要写n个类吗?而且修改起来也不是很好的。所以一个比较好的方法就是写一个Unity Editor编辑器类。

以下是本人写的一个Editor编辑器类,功能还不是很完善,例如可以加入”插入命令”,”从文本中读取命令”等等等的功能,不过,先将就用了,看下效果图

Unity Editor

贴上扩展的Editor代码:


using UnityEngine;
using UnityEditor;
using System.Collections.Generic;

public enum Option
{
CommandDestory,
CommandDialogue,
CommandDialogueModeEnter,
CommandDialogueModeExit,
CommandGenerate,
CommandMove,
CommandMusic,
CommandPlayAnim,
CommandRotate,
CommandWait
}

public class Window : EditorWindow
{
List<Option> options = new List<Option>();
List<string[]> strings = new List<string[]>();
List<int[]> ints = new List<int[]>();
List<float[]> floats = new List<float[]>();
List<Vector3[]> vector3s = new List<Vector3[]>();

Vector2 v2 = new Vector2(0, 0);//滚动条参数

[MenuItem("Window/My Window")]
static void Init()
{
EditorWindow.GetWindow(typeof(Window));
}

void OnGUI()
{
if (GUILayout.Button("保存命令"))
{
}

if (GUILayout.Button("添加命令"))
{
Option x = Option.CommandDialogueModeEnter;
options.Add(x);
string[] a = new string[5];
strings.Add(a);
int[] b = new int[5];
ints.Add(b);
float[] c = new float[5];
floats.Add(c);
Vector3[] d = new Vector3[5];
vector3s.Add(d);
}

if (GUILayout.Button("删除命令"))
{
options.RemoveAt(options.Count - 1);
strings.RemoveAt(options.Count - 1);
ints.RemoveAt(options.Count - 1);
floats.RemoveAt(options.Count - 1);
vector3s.RemoveAt(options.Count - 1);
}

v2 = EditorGUILayout.BeginScrollView(v2,false,true,null);
for (int i = 0; i < options.Count; i++)
{
options[i] = (Option)EditorGUILayout.EnumPopup("选项" + i, options[i]);
switch (options[i])
{
case Option.CommandDestory:
strings[i][0] = EditorGUILayout.TextField("物体名字", strings[i][0]);
break;
case Option.CommandDialogue:
strings[i][0] = EditorGUILayout.TextField("xml文本名字", strings[i][0]);
ints[i][0] = EditorGUILayout.IntField("开始序号", ints[i][0]);
ints[i][1] = EditorGUILayout.IntField("结束序号", ints[i][1]);
ints[i][2] = EditorGUILayout.IntField("点击后执行的步骤数", ints[i][2]);
break;
case Option.CommandDialogueModeEnter:
break;
case Option.CommandDialogueModeExit:
break;
case Option.CommandGenerate:
strings[i][0] = EditorGUILayout.TextField("物体名字", strings[i][0]);
vector3s[i][0] = EditorGUILayout.Vector3Field("生成位置", vector3s[i][0]);
vector3s[i][1] = EditorGUILayout.Vector3Field("生成角度", vector3s[i][1]);
break;
case Option.CommandMove:
strings[i][0] = EditorGUILayout.TextField("物体名字", strings[i][0]);
vector3s[i][0] = EditorGUILayout.Vector3Field("终点位置", vector3s[i][0]);
floats[i][0] = EditorGUILayout.FloatField("所用时间", floats[i][0]);
break;
case Option.CommandMusic:
strings[i][0] = EditorGUILayout.TextField("音乐名字", strings[i][0]);
break;
case Option.CommandPlayAnim:
strings[i][0] = EditorGUILayout.TextField("物体名字", strings[i][0]);
ints[i][0] = EditorGUILayout.IntField("动画状态", ints[i][0]);
break;
case Option.CommandRotate:
strings[i][0] = EditorGUILayout.TextField("物体名字", strings[i][0]);
vector3s[i][0] = EditorGUILayout.Vector3Field("终点角度", vector3s[i][0]);
floats[i][0] = EditorGUILayout.FloatField("所用时间", floats[i][0]);
break;
case Option.CommandWait:
floats[i][0] = EditorGUILayout.FloatField("等待时间", floats[i][0]);
break;
default:
break;
}
}
EditorGUILayout.EndScrollView();
}
}

下面是Xml保存的方法


void Save()
{
string filePath = Application.dataPath + @"/my.xml";

XmlDocument xmlDoc = new XmlDocument();
XmlElement root = xmlDoc.CreateElement("root");

for (int i = 0; i < options.Count; i++)
{
XmlElement child = xmlDoc.CreateElement("child");
XmlElement x = xmlDoc.CreateElement("type");
x.InnerText = options[i].ToString();
child.AppendChild(x);

int count = 1;
for (int q = 0; q < strings[q].Length; q++)
{
XmlElement q1 = xmlDoc.CreateElement("string_" + count);
q1.InnerText = strings[i][q];
child.AppendChild(q1);
count++;
}

for (int q = 0; q < ints[q].Length; q++)
{
XmlElement q1 = xmlDoc.CreateElement("int_" + count);
q1.InnerText = ints[i][q].ToString();
child.AppendChild(q1);
count++;
}

for (int q = 0; q < floats[q].Length; q++)
{
XmlElement q1 = xmlDoc.CreateElement("float_" + count);
q1.InnerText = floats[i][q].ToString();
child.AppendChild(q1);
count++;
}

for (int q = 0; q < vector3s[q].Length; q++)
{
XmlElement q1 = xmlDoc.CreateElement("vector3_" + count);
q1.InnerText = vector3s[i][q].ToString();
child.AppendChild(q1);
count++;
}
root.AppendChild(child);
}

xmlDoc.AppendChild(root);
xmlDoc.Save(filePath);
AssetDatabase.Refresh();
Debug.Log("Ok!!");
}

读取Xml文件


void Load(string xmlPath)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlPath);

XmlNodeList childs = xmlDoc.SelectSingleNode("root").ChildNodes;//所有child
for (int i = 0; i < childs.Count; i++)
{
XmlNodeList nodes = childs[i].ChildNodes;//单个child的所有节点

string a = nodes[0].InnerText;
switch (a)
{
case "CommandDestory":
commands.Add(new CommandDestory(nodes[1].InnerText));
break;
case "CommandDialogue":
int int1 = int.Parse(nodes[6].InnerText);
int int2 = int.Parse(nodes[7].InnerText);
int int3 = int.Parse(nodes[8].InnerText);
commands.Add(new CommandDialogue(nodes[1].InnerText, int1, int2, int3));
break;
case "CommandDialogueModeEnter":
commands.Add(new CommandDialogueModeEnter());
break;
case "CommandDialogueModeExit":
commands.Add(new CommandDialogueModeExit());
break;
case "CommandGenerate":
Vector3 v1 = StringToVector3(nodes[16].InnerText);
Vector3 v2 = StringToVector3(nodes[17].InnerText);
commands.Add(new CommandGenerate(nodes[1].InnerText,v1,v2));
break;
case "CommandMove":
Vector3 v = StringToVector3(nodes[16].InnerText);
commands.Add(new CommandMove(nodes[1].InnerText, v, float.Parse(nodes[11].InnerText)));
break;
case "CommandMusic":
commands.Add(new CommandMusic(nodes[1].InnerText));
break;
case "CommandPlayAnim":
commands.Add(new CommandPlayAnim(nodes[1].InnerText, int.Parse(nodes[6].InnerText)));
break;
case "CommandRotate":
Vector3 v3 = StringToVector3(nodes[16].InnerText);
commands.Add(new CommandRotate(nodes[1].InnerText, v3, float.Parse(nodes[11].InnerText)));
break;
case "CommandWait":
commands.Add(new CommandWait(float.Parse(nodes[11].InnerText)));
break;
default:
break;
}
}
}

Vector3 StringToVector3(string s)
{
s = s.Substring(1,s.Length - 2);
string[] a = s.Split(',');
Vector3 b = new Vector3(float.Parse(a[0]), float.Parse(a[1]), float.Parse(a[2]));
return b;
}

xml文件里的一个命令节点内容:

可以看到,节点名称都被标号了,这样读取的时候就很容易拿到我们想要的数据了。

其实做编辑器工具是一种挺好的加快效率的方式,因为生活中,程序主要负责的是程序,策划主要就是弄表格等等的,这样就可以把程序的一部分工作交给策划来弄,策划只需在编辑器上使用这些工具,就可以实现同等的功能,可谓是双赢啊哈哈。

好了,本篇unity3d教程到此结束,下篇我们再会!