真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

使用Unity怎么實現(xiàn)一個游戲存檔框架

使用Unity怎么實現(xiàn)一個游戲存檔框架,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

創(chuàng)新互聯(lián)長期為近千家客戶提供的網(wǎng)站建設(shè)服務(wù),團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為天寧企業(yè)提供專業(yè)的成都網(wǎng)站建設(shè)、成都網(wǎng)站制作,天寧網(wǎng)站改版等技術(shù)服務(wù)。擁有10多年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。

ISavable,表示這個類型可以存檔

public interface ISavable{ uint Id {get; set;} Type DataType {get;} // 存檔數(shù)據(jù)類型 Type DataContainerType {get;} // 存檔數(shù)據(jù)容器類型 void Read(object data); void Write(object data);}

ISavableContainer,用來返回一組ISavable的容器:

public interface ISavableContainer{  IEnumerable Savables;}

IId, 具有Id的接口:

public interface IId{  uint Id {get; set;}}

SaveEntity, 這是一個MonoBehaviour,將這個組件放到需要存檔的GameObject上就可以實現(xiàn)該GameObject的存檔了,這是最核心的類之一:

public class SaveEntity : MonoBehaviour{  public void Save(SaveDataContainer container){    foreach(ISavable savable in GetSavables()){      if(savable.DataContainerType = container.GetType()){        IId newData = Activator.CreateInstance(savable.DataType) as IId;        newData.Id = savable.Id;        savable.Write(newData);        container.SetData(newData);      }    }  }   public void Load(SaveDataContainer container){    foreach(ISavable savable in GetSavables()){      if(savable.DataContainerType = container.GetType()){        IId data = container.GetData(savable.Id);        savable.Read(data);      }    }      }   public IEnumerable GetSavables(){    foreach(ISavable savable in GetComponents()){      yield return savable;    }    foreach(ISavable savableContainer in GetComponents()){      foreach(ISavable savable in savableContainer.Savables){        yield return savable;      }    }  }}

SaveFile代表一個文件

[Serializable]public class SaveFileData{  public uint CurId;  public string DataContainer;} // 代表一個存檔文件public class SaveFile: MonoBehaviour{  // 包含實際數(shù)據(jù)的數(shù)據(jù)類  private SaveDataContainer _saveDataContainer;  private uint _curId;   public string Path{get;set;}  public SaveDataContainer SaveDataContainer{get{return _saveDataContainer;}}   private uint NextId{get{return ++_curId;}}   // 得到場景里所有的SaveEntity  private IEnumerable GetEntities(){    // 實現(xiàn)略過  }    // 將場景物體中的數(shù)據(jù)存入到_saveDataContainer中  public void Save() where T:SaveDataContainer, new()  {    // 一輪Id賦值,保證Id為0的所有ISavable都賦值一個新Id    foreach(SaveEntity entity in Entities){      foreach (Savable savable in entity.GetSavables()){        if(savable.DataContainerType == typeof(T)){          if(savable.Id == 0){            savable.Id = NextId;          }        }      }    }     T dataContainer = new T();     foreach(SaveEntity entity in Entities){      entity.Save(this, dataContainer);    }     _saveDataContainer = dataContainer;  }   // 將_saveDataContainer中的數(shù)據(jù)載入到場景物體中  public void Load(){    foreach(SaveEntity entity in Entities){      entity.Load(this, _saveDataContainer);    }  }   public void LoadFromFile() where T:SaveDataContainer  {    string json = File.ReadAllText(Path);    SaveFileData data = JsonUtility.FromJson(json);    _saveDataContainer = JsonUtility.FromJson(data.DataContainer);    _curId = data.CurId;  }   public void SaveToFile(){    SaveFileData data = new SaveFileData();    data.CurId = _curId;    data.DataContainer = JsonUtility.ToJson(_saveDataContainer);    string json = JsonUtility.ToJson(data);    File.WriteAllText(Path, json);  }}

SaveDataContainer:

// 這個類型存儲了實際的數(shù)據(jù),相當(dāng)于是一個數(shù)據(jù)庫[Serializable]public class SaveDataContainer{  // 這個中存儲這實際物體的數(shù)據(jù),需要將這個字典轉(zhuǎn)換成數(shù)組并序列化  private Dictionary _data;   public Dictionary Data{get{return _data}}   public IId GetData(uint id){    return _data[id];  }   public void SetData(IId data){    _data[data.Id] = data;  }}

好了,框架就講到這里,接下來實現(xiàn)示例代碼:

Unit:

[Serializable]public class UnitSave:IId{  [SerializeField]  private uint _id;  public uint PrefabId;  public uint InventoryId;  public int Hp;  public int Level;  public uint Id {get{return _id;}set{_id = value;}}} public class Unit:MonoBehaviour, ISavable{  public int Hp;  public int Level;  public int PrefabId;  public Inventory Inventory;    public uint Id{get;set;}  ISavable.DataType{get{return typeof(UnitSave);}}  ISavable.DataContainerType{get{return typeof(ExampleSaveDataContainer);}}  ISavable.Read(object data){    UnitSave save = data as UnitSave;    Hp = save.Hp;    Level = save.Level;  }   ISavable.Write(object data){    UnitSave save = data as UnitSave;    save.Hp = Hp;    save.Level = Level;    save.InventoryId = Inventory.Id;  }}

Inventory:

[Serializable]public class InventorySave:IId{  [SerializeField]  private uint _id;  public uint UnitId;  public uint[] Items;  public uint Id{get{return _id;}set{_id = value;}}} public class Inventory:MonoBehaviour, ISavable, ISavableContainer{  public Unit Unit;  public List Items;   public uint Id{get;set;}  ISavable.DataType{get{return typeof(InventorySave);}}  ISavable.DataContainerType{get{return typeof(ExampleSaveDataContainer));}}  ISavable.Read(object data){    // 空  }  ISavable.Write(object data){    InventorySave save = data as InventorySave;    save.UnitId = Unit.Id;    save.Items = Items.Select(item => item.Id).ToArray();  }   ISavableContainer.Savables{    return Items;  }}

Item:

[Serializable]public ItemSave: IId{  [SerializeField]  private uint _id;  public uint PrefabId;  public int Count;  public uint Id{get{return _id;}set{_id = value;}}} // 道具并不是繼承自MonoBehaviour的,是一個普通的類public class Item:ISavable{  // 道具源數(shù)據(jù)所在Prefab,用于重新創(chuàng)建道具  public uint PrefabId;  public int Count;  public uint Id {get;set;}   public uint Id{get;set;}  ISavable.DataType{get{return typeof(ItemSave);}}  ISavable.DataContainerType{get{return typeof(ExampleSaveDataContainer));}}  ISavable.Read(object data){    ItemSave save = data as ItemSave;    Count = save.Count;  }  ISavable.Write(object data){    ItemSave save = data as ItemSave;    save.PrefabId = PrefabId;    save.Count = Count;  }}

ExampleSaveDataContainer:

[Serializable]public class ExampleSaveDataContainer: SaveDataContainer, ISerializationCallbackReceiver {  public UnitSave[] Units;  public ItemSave[] Items;  public InventorySave[] Inventories;   public void OnBeforeSerialize(){    // 將Data字典中的數(shù)據(jù)復(fù)制到數(shù)組中,實現(xiàn)略過  }   public void OnAfterDeserialize(){    // 將數(shù)組中的數(shù)據(jù)賦值到Data字典中,實現(xiàn)略過  }}

ExampleGame:

public class ExampleGame:MonoBehaviour{   public void LoadGame(SaveFile file){    // 從文件中讀入數(shù)據(jù)到SaveDataContainer    file.LoadFromFile();    SaveDataContainer dataContainer = file.SaveDataContainer;     // 創(chuàng)建所有物體并賦值相應(yīng)Id    Unit[] units = dataContainer.Units.Select(u=>CreateUnit(u));    Item[] items = dataContainer.Items.Select(item=>CreateItem(item));     // 將道具放入相應(yīng)的道具欄中    foreach(Unit unit in units){      uint inventoryId = unit.Inventory.Id;      InventorySave inventorySave = dataContainer.GetData(inventoryId);      foreach(Item item in items.Where(i=>inventorySave.Items.Contains(i.Id))){        unit.Inventory.Put(item);      }    }     // 調(diào)用Load進行實際的數(shù)據(jù)載入    file.Load();  }   public void SaveGame(SaveFile file){    // 相對來說,存檔的實現(xiàn)比載入簡單了許多    file.Save();    file.SaveToFile();  }   public Unit CreateUnit(UnitSave save){    Unit unit = Instantiate(GetPrefab(save.PrefabId)).GetComponent();    unit.Id = save.Id;    unit.Inventory.Id = save.InventoryId;    return unit;  }   public Item CreateItem(ItemSave save){    Item item = GetPrefab(save.PrefabId).GetComponent().CreateItem();    item.Id = save.Id;    return item;  }}

使用方法:

給單位Prefab中的Unit組件和Inventory組件所在的GameObject上放SaveEntity組件即可。

思考問題:

1.擴展功能,讓SaveFile包含一個SaveDataContainer數(shù)組,這樣子可以實現(xiàn)包含多個數(shù)據(jù)容器(數(shù)據(jù)庫)的情況2.對SaveFile存儲內(nèi)容進行壓縮,減少存儲體積3.SaveFile存儲到文件時進行加密,避免玩家修改存檔4.如何避免存儲時候卡頓

存儲過程:

1.從場景中搜集數(shù)據(jù)到SaveFile中(SaveFile.Save),得到一個SaveFileData的數(shù)據(jù)2.將SaveFileData序列化成一個json字符串3.對字符串進行壓縮4.對壓縮后的數(shù)據(jù)進行加密5.將加密后的數(shù)據(jù)存儲于文件

可以發(fā)現(xiàn),只要完成第1步,得到一個SaveFileData,實際上就已經(jīng)完成了存檔了,接下來實際上就是一個數(shù)據(jù)轉(zhuǎn)換的過程。所以,這也給出了避免游戲卡頓的一種方法:

完成第一步之后,將后面的步驟全部都放到另一個線程里面處理。實際上,第一步的速度是相當(dāng)快的。往往不會超過50ms,可以說,卡頓并不會很明顯。

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進一步的了解或閱讀更多相關(guān)文章,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。


標(biāo)題名稱:使用Unity怎么實現(xiàn)一個游戲存檔框架
標(biāo)題URL:http://weahome.cn/article/gieggh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部