首页 > 编程语言 > 详细

Unity中动态修改游戏中任意参数的框架

时间:2017-02-22 10:26:16      阅读:447      评论:0      收藏:0      [点我收藏+]

本文章由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

【2】 http://blog.csdn.net/cartzhang/article/details/49818953

【3】 http://blog.csdn.net/cartzhang/article/details/49884507

Unity中动态修改游戏中任意参数的框架

原文:http://blog.csdn.net/cartzhang/article/details/56292977

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!