心血来潮,根据之前做的一个控制台的输入,就想根据控制台的输入,来控制和修改游戏中的某些参数。
目前大部分简单游戏修改参数有数据库,XML,json 等各式各样,现在做的是一个可以在游戏过程中,实时修改任意变量的一个东西。
用法很简单,tab 按键来打开控制台,输入需要修改的参数就可以,看到参数实时被修改。
也可以把它理解成简单的修改器,用于调节参数和可能的命令修改游戏中的参数。
当然,也需要稍微修改一个项目中原有的代码。这个功能已经使用代码一键实现了,并且使用 unity 中不加入编译的方式,在代码文件名字前加 "." 的方式保留了原来的代码。
先看下整体的思维导图
思维导图
输入部分有控制台来实现输入。
图 0
在 ConsoleInput 类中添加了 OnInputText 时间,这样就可以根据输入不同进行处理了。
关于具体控制台程序的一些用法和使用事项,请参考后面给出的 github 和博客地址,里面进行了说明和更新,也非常期待感兴趣的可以自己提交更改。
- void OnInputText( string obj )
- {
- this.ConsolePrint(obj);
- if (!NotifyToChangeVarialbe(obj))
- {
- this.ConsolePrint("not correct input to change variable");
- }
- }
顺便说下,this.ConsolePrint 是对 MonoBehaviour 类进行了扩展。
具体代码:
- public static class ExtendDebugClass
- {
- public static void ConsolePrint(this MonoBehaviour mono, string message)
- {
- if (message.Length < 0) return;
- System.Console.WriteLine(message);
- }
- }
输入的字符串作为参数,需要不同进行处理。
输入的参数有三部分组成,类名称,变量名,变量新值。
目前只可以处理整形,浮点型,字符串和布尔型四种常用类型。
- public static bool IsVarialbeInList(string classname,string classname_variableName, out string valuetype)
- {
- bool bresult = false;
- string tmpclassName = classname;
- Debug.Assert(!string.IsNullOrEmpty(tmpclassName));
- Debug.Assert(!string.IsNullOrEmpty(classname_variableName));
- valuetype = null;
- if (CollectAttributeUtil.myFuctionList.ContainsKey(tmpclassName))
- {
- List mlist = (List)myFuctionList[tmpclassName];
- for (int i = 0; i < mlist.Count; i++)
- {
- if (mlist[i] != null &&
- string.Compare( mlist[i].class_variable ,classname_variableName,true) == 0)
- {
- valuetype = CheckVariableType(mlist[i].variable_type);
- bresult = true;
- break;
- }
- }
- }
- return bresult;
- }
然后进行消息触发,就搞定了修改参数,并且可以实时修改。
这里自定义类一个字段属性 ModifyAttribute
ModifyAttribute.cs
- using System;
- [System.AttributeUsage(AttributeTargets.All)]
- public class ModifyAttribute : Attribute
- {
- //public ModifyAttribute()
- //{
- //}
- }
若使用这个框架,只需在需要改变的变量代码前添加这个属性描述。
例如:
- [ModifyAttribute]
- public int clolor;
- [ModifyAttribute]
- public string attack;
下面这个函数负责收集所有的可修改变量,在 ServerConsole.cs 中的 Awake 中被调用。
- CollectAttributeUtil.InitialCollectModifyAttribute();
收集变量的主要代码在 CollectAttributeUtil.cs 中实现。
代码不是很多,但是很重要。
主要的是这个
- /// <summary>
- /// get attribute type variable in each monobehaviour class.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="p"></param>
- private static void CollectAttributeProperty(MonoBehaviour p) where T : ModifyAttribute
- {
- var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static;
- var type = p.GetType();
- FieldInfo[] fieldInfor = type.GetFields(flags);
- foreach (var field in fieldInfor)
- {
- var objs = field.GetCustomAttributes(typeof(T), false);
- if (objs.Length > 0)
- {
- string keyTmp = type.FullName;
- AttributeForClass attri4Class = new AttributeForClass();
- attri4Class.class_variable = (type.FullName + "#" + field.Name);
- attri4Class.variable_type = field.FieldType;
- if (!myFuctionList.Contains(keyTmp))
- {
- List AttriClassList = new List();
- AttriClassList.Add(attri4Class);
- myFuctionList.Add(keyTmp, AttriClassList);
- }
- else
- {
- List mlist = (List)myFuctionList[keyTmp];
- mlist.Add(attri4Class);
- }
- //Debug.Log(type.ToString() + " current varible is " + field.Name + " type is " + field.FieldType);
- }
- }
- }
这个函数把所有收集对象按类的名字为基础,然后形成列表,存放到 myFuctionList 中,等待被使用。
由于使用了消息机制,需要自动来把需要修改的变量,写为函数,然后在注册为消息。
不用担心,这些工作已经做为了。只需要按下一个按键,一键搞定。
在 Editor 文件夹下,有个 CreateCode.cs 文件,且只可以在编辑器模式下运行。
图 3
这里的代码还是蛮多,说下主要的,
第一,得到所有需要注册的类名和变量名,这个工作其实代码已经写过了就是前面的收集工作。这里只需要调用一下就可以了。
第二,创建 partial 文件夹,根据类创建每个类的文件. cs。
第三,给每个类文件,根据类中所需要修改的变量,自动添加变量消息和赋值函数。
第四,把消息注册自动的编写到原有的代码的 start 函数中,这就结束了。
这里有个小的约束:
函数必须有
- void Start ()
- {
- }
必须有,并且最好大括号不能在同一行,也就是说不能写成
- void Start () {
因为需要便是这个函数,在里面添加代码;
- void Start ()
- {
- // auto regist code. @cz
- Start4AutoSubscribe();
- transf = this.transform;
- //string messName = GETNAME(new { this.movespeed });
- //NotificationManager.Instance.Subscribe(messName, ControlMove_movespeed);
- }
start 后面的两行是代码自动添加的。代码中已经做了判断,若添加过
- // auto regist code. @cz
- Start4AutoSubscribe();
就不会再次添加。
这里还有个保存原有代码的功能呢,就是最原始的你写的项目中代码。根据 unity 的特性,对点开头的. cs 文件视而不见,默认不加入编译中。
图 2
若有需要可以把原代码给还原了。但是,还是自动 svn 提交的好。
为什么需要修改源代码呢?
有两个原因:一个是需要注册消息。一个是需要扩展这个需要修改的类,这里会把原来的类前面添加一个关键字 partial。
- public partial class ControlMove : MonoBehaviour
- {
代码中没有加,没有关系,代码会自动运行修改。
你需要做的就是按下 AutoModifyClass 按钮,等待编译修改。
消息的处理,也就是这个消息机制之前说过多次。主要用于解耦对象。
这里不过多说明了。
说怎么使用呢?
第一,把带导入的项目中,把 prefab 文件中的 TestConsole 拖到场景中即可。
图 5
第二,把项目中所需要在游戏中动态修改的变量添加属性
- [ModifyAttribute]
修类型不限于 public。当前对变量的类型还是做了限制的,只有 public。
限制的代码在这里:
- var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static;
第三,点击生成按钮
添加完毕后,点击生成按钮。
图 3
第四,所有代码代码就会自动生成,也会修改源工程中的部分需要修改的类的代码。
第五,运行
图 4
运行,使用 tab 键或~键都可以调出和关闭控制台窗口。
在输入类,变量,修改值,就可以看到了。
这适用于基础版本的打包测试,编辑器测试,或其他项目,不用为了一个变量来回的打包测试,当然也可以与其他比方说 json 或 xml,数据库等配合使用。
目前的还需要做的事情:
1. 命令行不区分大小写,输入参数现在必须区分大小写,有空格隔开。可能需要处理为不区分大小写的模式。
2. 命令行需要丰富,现在控制台命名只有两个,一个是清屏 clear,一个是退出控制台 exit。
3. 控制台命令行输入提示,根据需要提示和回滚之前的输入信息。
4. 项目中源代码的回滚功能,防止错误的替换。
项目地址:
相关图片可下载地址:
更多控制台的输入项目工程地址和说明,见参考。
【1】
【2】
【3】
来源: http://www.bubuko.com/infodetail-1954412.html