在我們的專案程序中經常會遇到某個組件迭代的程序,那么在廢棄舊組件,替換新組件的時候,就可以使用一個通用組件替換工具完成一鍵替換的功能,
設計圖如下:

基類ReplaceComponentBase泛型類,將舊組件和新組件傳遞進去,
public abstract class ReplaceComponentBase<TOldComponent, TNewComponent>
where TOldComponent : Component
where TNewComponent : Component
MakeFindFile方法是一個虛方法供派生類可重寫自己的查找方式,默認從預制體中進行查找,
protected string[] _findFiles;
protected virtual void MakeFindFile()
{
//收集所有預制資訊
var extensions = new List<string>() {".prefab"};
var files = Directory.GetFiles(Application.dataPath, "*.*", SearchOption.AllDirectories)
.Where(s => extensions.Contains(Path.GetExtension(s)?.ToLower())).ToArray();
_findFiles = Directory.GetFiles(Application.dataPath, "*.*", SearchOption.AllDirectories)
.Where(s => extensions.Contains(Path.GetExtension(s)?.ToLower())).ToArray();
}
StartReplace方法傳入資料背景關系,并打開進度條進行查找,
protected virtual void StartReplace(ComponentDataContextBase dataContextBase)
{
_findComponentDict = new Dictionary<string, List<TOldComponent>>();
_dataContextBase = dataContextBase;
MakeFindFile();
EditorUtilityHelp.ShowUpdate("正在查找", _findFiles.Length, (index) => { FindInPrefab(_findFiles[index]); },
FindPrefabOver);
}
ReplaceIng方法在替換程序中將舊的組件全部替換成新的組件,具體的資料操作交由ComponentDataContext子類實作,
protected virtual void ReplaceIng(TOldComponent oldComponent)
{
var gameObject = oldComponent.gameObject;
_dataContextBase.CopyComponent(oldComponent);
Object.DestroyImmediate(oldComponent, true);
var newComponent = gameObject.AddComponent<TNewComponent>();
_dataContextBase.PasteComponent(newComponent);
}
ReplaceOver在替換完成時呼叫,通常列印相關的替換資訊,
protected virtual void ReplaceOver()
{
foreach (var item in _findComponentDict)
{
GameObject prefab = LoadGameObjectByGuid(item.Key, out var prefabPath);
Debug.Log($"Replace Prefab {prefab.name} {prefabPath} ComponentsLength {item.Value.Count}", prefab);
}
}
ComponentDataContextBase這個類提供兩個抽象方法供子類重寫,主要完成對資料的賦值和粘貼操作,
public abstract class ComponentDataContextBase
{
public abstract void CopyComponent<TOldComponent>(TOldComponent oldComponent) where TOldComponent : Component;
public abstract void PasteComponent<TNewComponent>(TNewComponent newComponent) where TNewComponent : Component;
}
對于實際的應用類,例如我們需要將Test1換成Test2組件的話,testData和nameData為這兩個腳本中公用的資料,那么對應的兩個類分別為:
public class TestScriptComponentDataContext : ComponentDataContextBase
{
public object testData;
public object nameData;
private static BindingFlags _flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
public override void CopyComponent<TOldComponent>(TOldComponent oldComponent)
{
var test1Script = oldComponent as Test1;
testData = typeof(Test1).GetField("TestData1", _flags)?.GetValue(test1Script);
nameData = typeof(Test1).GetField("Name", _flags)?.GetValue(test1Script);
}
public override void PasteComponent<TNewComponent>(TNewComponent newComponent)
{
var test2Script = newComponent as Test2;
typeof(Test2).GetField("TestData1", _flags)?.SetValue(test2Script,testData);
typeof(Test2).GetField("Name", _flags)?.SetValue(test2Script,nameData);
}
}
public class TestScriptReplaceComponent : ReplaceComponentBase<Test1,Test2>
{
public void StartReplaceTestScript()
{
StartReplace(new TestScriptComponentDataContext());
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/294193.html
標籤:其他
上一篇:SQL基礎學習總結
