1. 程式人生 > >Unity中動態修改遊戲中任意引數的框架

Unity中動態修改遊戲中任意引數的框架

一、 引言


心血來潮,根據之前做的一個控制檯的輸入,就想根據控制檯的輸入,來控制和修改遊戲中的某些引數。

目前大部分簡單遊戲修改引數有資料庫,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.專案中原始碼的回滾功能,防止錯誤的替換。

八、原始碼分享


專案地址:


更多控制檯的輸入專案工程地址和說明,見參考。

九、參考

相關推薦

Unity動態修改遊戲任意引數框架

一、 引言 心血來潮,根據之前做的一個控制檯的輸入,就想根據控制檯的輸入,來控制和修改遊戲中的某些引數。 目前大部分簡單遊戲修改引數有資料庫,XML,json等各式各樣,現在做的是一個可

Android佈局動態修改TextView等控制元件文字的顏色

在Android介面展示資訊時,有時我們需要相近或相鄰的文字顯示不同的文字格式,這時該怎麼辦呢?我們有至少兩種辦法: 新增多個控制元件 在控制元件修改區域性文字 今天我們來談一下如何在控制元件中修改區域性文字。 1、SpannableStringB

實現動態修改ListView某個Item裡的元件值

1.理解ListView及GridView檢視複用的機制Adapter+靜態ViewHolder的方式可以參照 http://www.myandroidsolutions.com/2012/07/19/android-listview-with-viewholder-tut

#遊戲unity-VR場景漫遊#遊戲的優化(一)

基於之前製作專案的經歷教訓——沒有報錯的程式碼合在一起整體執行的時候就執行特別卡,深刻認識到了專案優化的重要性;VR遊戲的流暢度是影響使用者體驗的一個很重要的因素,而且,三區的場景模型也是一個有很多面的模型,執行起來會相當佔資源,為了解決執行卡頓的問題,就必須在

#遊戲unity-VR場景漫遊#遊戲的優化(二)

這篇文章接著上一篇的內容進行整理。 畫素優化 畫素優化的重點在於減少overdraw。之前提過,overdraw指的就是一個畫素被繪製了多次。關鍵在於控制繪製順序。 Unity還提供了檢視overdraw的檢視,在Scene檢視的Render Mode-&

C#動態修改ListBox的Item的顏色的方法

最近搞了C#需要在ListBox中顯示不同型別的資料,為了讓使用者容易區分,增加了顏色區分的功能,就是需要不同的型別資料顯示出不同的顏色。針對上述的要求我們需要使用控制元件的重繪方法,就是用重繪的方法啟用重繪事件,在重繪事件內修改Item的字型顏色。方法如下(基於DrawI

Unity2D——動態修改動畫的圖片尺寸

在製作動畫過程中,有時會遇到圖片尺寸不統一,使得播放的動畫怪怪的,這時就需要我們實時修改圖片尺寸。程式碼如下: Image Image; void Update () { Image = this.transform.GetComponent<Ima

動態修改android的資源索引resId

一、引言1、為什麼要動態修改資源索引一般情況下我們不需要干預資源索引,因為gradle會自動整合專案及所有依賴的資源,再進行相關編譯工作,這樣資源索引不會衝突。但是如果我們在app中從另外一個apk包中獲取程式碼或資源來使用,就有可能產生衝突。這時候就需要進行動態修改。2、怎

Unity實現動態修改模型材質球

一、定義需要替換的材質球(且載入該材質球) private Material _HighLightMat; //實現閃爍高亮效果材質球 _HighLightMat = Resources.Load("Prefabs

WPF動態載入XAML的控制元件

原文: WPF中動態載入XAML中的控制元件 using System; using System.Collections.Generic; using System.Linq; using System.Text;

springboot logback動態獲取application配置項

在多環境的情況下,logback的日誌路徑需要進行鍼對性配置,也就是需要通過application.yml檔案中進行配置。 logback自身支援以下方式配置: <property name="USER_HOME" value="/home/sebastien" /> 但是怎

MySql資料庫查詢修改字元編碼(charset)的方法

MySQL字符集多種多樣,下面為您列舉了其中三種最常見的MySQL字符集檢視方法,該方法供您參考,希望對您學習MySQL資料庫能有所啟迪。 一、檢視MySQL資料庫伺服器和資料庫MySQL字符集。 mysql> show variables like '%char%

關於oracle資料庫直接修改資料點選小鎖出現"these query results are not updateable"的問題

 一、想通過plsql在表中直接新增一條記錄點選小鎖的時候,出現如下錯誤:These query results are not updateable.Include the ROWID to get updateable results. 如截圖: 解決方法: 1、

在Heidisql批量修改MySQL的某列資料

UPDATE 表名 SET 要修改的列名 = CASE 標識列 WHEN 標識列的值 THEN '要修改的值' WHEN 標識列的值 THEN '要修改的值' END WHERE (標識列>=1 and 標識列<=3) 例如:要依據id值

ios開發如何修改AppStore開發商的資訊

AppStore中開發商的資訊是在申請開發者賬號時設定的,有時候,我們需要修改開發商資訊比如變更公司名稱。這個只能通過蘋果客戶來完成。蘋果開發技術支援電話:400-670-1855,是中文的,電話告知你的賬號情況以及提供一些申請賬號的資訊,客服就會幫你變更資訊,一般24小時

Unity-程式碼動態設定Material引數

我們知道在Unity中可以在程式碼中動態地改變Material監視面板中的引數,如改變數值大小或替換貼圖。常用的API有:SetColor , SetFloat, SetInt, SetTexture. 然而今天在設定一個StandardShader的材質貼圖

Unity建立自己的mesh以及動態修改mesh

開頭 最近發現有很多人不知道在unity中可以建立和修改mesh,以為mesh只能從3dmax等軟體中匯入,所以這篇就相當於科普了。 正文 首先介紹如何建立mesh。   先建立一個空物體,名為test。   然後為這個物體增加 meshrender 和 mesh

讀取URL引數修改URL引數動態修改URL replaceState js程式碼

都是抄來的知識彙總 1、讀取URL中的引數值 /* *獲取URL引數 */ function GetQueryString(name) {     var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$

Unity遊戲使用貝塞爾曲線

str net 順序 復雜 讓我 創建 函數 高程 gin 孫廣東 2015.8.15比方在3D rpg遊戲中。我們想設置彈道,不同的軌跡類型!目的:這篇文章的主要目的是要給你關於在遊戲怎樣使用貝塞爾曲線的基本想法。 貝塞爾曲線是最主要的曲線,一般用

unity實用技能】unity遊戲更換角色的shader,比如加個流光

無原本想著這個功能怎麽實現,剛好在項目裏看到這裏記錄一下。 首先項目的模型裏會有一個基本的Material,這個就是美術出給你的模型的材質。 可能有的需求是在遊戲中觸發一個事件,你身上加個流光或者描邊等效果。 我們知道這些效果如果要表現在身上,用特效是不好看的,要用Shader去表現。 這時候就需要你換一個S