本文章由cartzhang编写,转载请注明出处。 所有权利保留。
文章链接:http://blog.csdn.net/cartzhang/article/details/56292977
作者:cartzhang
心血来潮,根据之前做的一个控制台的输入,就想根据控制台的输入,来控制和修改游戏中的某些参数。
目前大部分简单游戏修改参数有数据库,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<AttributeForClass> mlist = (List<AttributeForClass>)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<T>(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<AttributeForClass> AttriClassList = new List<AttributeForClass>();
AttriClassList.Add(attri4Class);
myFuctionList.Add(keyTmp, AttriClassList);
}
else
{
List<AttributeForClass> mlist = (List<AttributeForClass>)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.项目中源代码的回滚功能,防止错误的替换。
项目地址:
https://github.com/cartzhang/dynamic_parameter_frame
相关图片可下载地址:
https://github.com/cartzhang/dynamic_parameter_frame/tree/master/image
更多控制台的输入项目工程地址和说明,见参考。
【1】 https://github.com/cartzhang/UnityConsoleWindow
原文:http://blog.csdn.net/cartzhang/article/details/56292977