本套存档的优点:易使用,跨平台,防作弊(内容加密 + 防拷贝)
脚本下载地址
使用方法非常简单:
把GameDataManager和XmlSaver两个脚本添加至工程后
(1)新建一个GameObject,起名GameDataManager并将GameDataManager脚本拖到上面。
(2)在GameDataManager里的GameData类中添加需要储存的数据
OK,跨平台防破解防拷贝的存档就搞定了!之后 每次存档调用GameDataManager的Save函数, 读档调用GameDataManager的Load函数。每次启动后GameDataManager会自动调用Load读档。如果玩家拿外来存档来覆盖本地存档,则游戏启动后数据清零,任何一次存档后作弊档被自动覆盖。注意:请勿放入二维以上数组,一般一维数据,枚举,自定义类等等数据类型可放心添加。
PS:风宇冲自己的U3d单机游戏和公司的单机游戏都用的这个XML存档,iOS,Android,PC,MAC都使用过的。放心使用吧。密钥的设定根据平台而定。
附:脚本代码
- //=========================================================================================================
- //Note: Data Managing.
- //Date Created: 2012/04/17 by 风宇冲
- //Date Modified: 2012/12/14 by 风宇冲
- //=========================================================================================================
- using UnityEngine;
- using System.Collections;
- using System.IO;
- using System.Collections.Generic;
- using System;
- using System.Text;
- using System.Xml;
- using System.Security.Cryptography;
- //GameData,储存数据的类,把需要储存的数据定义在GameData之内就行//
- public class GameData
- {
//密钥,用于防止拷贝存档// publicstring key; //下面是添加需要储存的内容// publicstring PlayerName; publicfloat MusicVolume; publicGameData() { PlayerName ="Player"; MusicVolume= 0.6f; } - }
- //管理数据储存的类//
- public class GameDataManager:MonoBehavIoUr
- {
privatestring dataFileName ="tankyWarData.dat";//存档文件的名称,自己定// private XmlSaver xs = new XmlSaver(); public GameData gameData; publicvoid Awake() { gameData =new GameData(); //设定密钥,根据具体平台设定// gameData.key= SystemInfo.deviceUniqueIdentifier; Load(); } //存档时调用的函数// public void Save() { stringgameDataFile = GetDataPath() + "/"+dataFileName; stringdataString= xs.SerializeObject(gameData,typeof(GameData)); xs.CreateXML(gameDataFile,dataString); } //读档时调用的函数// public void Load() { stringgameDataFile = GetDataPath() + "/"+dataFileName; if(xs.hasFile(gameDataFile)) { string dataString =xs.LoadXML(gameDataFile); GameData gameDataFromXML =xs.DeserializeObject(dataString,typeof(GameData)) as GameData; //是合法存档// if(gameDataFromXML.key == gameData.key) { gameData =gameDataFromXML; } //是非法拷贝存档// else { //留空:游戏启动后数据清零,存档后作弊档被自动覆盖// } } else { if(gameData!= null) Save(); } } //获取路径// privatestatic string GetDataPath() { // Your gamehas read+write access to/var/mobile/Applications/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/Documents //Application.dataPath returnsar/mobile/Applications/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/myappname.app/Data // Strip"/Data" from path if(Application.platform == RuntimePlatform.IPhonePlayer) { string path= Application.dataPath.Substring (0,Application.dataPath.Length -5); // Stripapplication name path =path.Substring(0,path.LastIndexOf('/')); return path+ "/Documents"; } else // returnApplication.dataPath + "/Resources"; returnApplication.dataPath; } - }
- //=========================================================================================================
- //Note: XML processcing,
can not savemultiple-array!!! - //Date Created: 2012/04/17 by 风宇冲
- //Date Modified: 2012/04/19 by 风宇冲
- //=========================================================================================================
- using UnityEngine;
- using System.Collections;
- using System.Xml;
- using System.Xml.Serialization;
- using System.IO;
- using System.Text;
- using System.Security.Cryptography;
- using System;
- public class XmlSaver
- {
//内容加密 publicstring Encrypt(string toE) { //加密和解密采用相同的key,具体自己填,但是必须为32位// byte[]keyArray =UTF8Encoding.UTF8.GetBytes("123485789022233678777234 56789012"); RijndaelManaged rDel = new RijndaelManaged(); rDel.Key =keyArray; rDel.Mode =CipherMode.ECB; rDel.Padding= PaddingMode.PKCS7; ICryptoTransform cTransform = rDel.CreateEncryptor(); byte[]toEncryptArray = UTF8Encoding.UTF8.GetBytes(toE); byte[]resultArray =cTransform.TransformFinalBlock(toEncryptArray,toEncryptArray.Length); returnConvert.ToBase64String(resultArray,resultArray.Length); } //内容解密 publicstring Decrypt(string toD) { //加密和解密采用相同的key,具体值自己填,但是必须为32位// byte[]keyArray =UTF8Encoding.UTF8.GetBytes("123485789022233678777234 56789012"); RijndaelManaged rDel = new RijndaelManaged(); rDel.Key =keyArray; rDel.Mode =CipherMode.ECB; rDel.Padding= PaddingMode.PKCS7; ICryptoTransform cTransform = rDel.CreateDecryptor(); byte[]toEncryptArray = Convert.FromBase64String(toD); byte[]resultArray =cTransform.TransformFinalBlock(toEncryptArray,toEncryptArray.Length); returnUTF8Encoding.UTF8.GetString(resultArray); } publicstring SerializeObject(object pObject,System.Type ty) { stringXmlizedString = null; MemoryStreammemoryStream = new MemoryStream(); XmlSerializerxs = new XmlSerializer(ty); XmlTextWriterxmlTextWriter = new XmlTextWriter(memoryStream,Encoding.UTF8); xs.Serialize(xmlTextWriter,pObject); memoryStream =(MemoryStream)xmlTextWriter.BaseStream; XmlizedString =UTF8ByteArrayToString(memoryStream.ToArray()); return XmlizedString; } publicobject DeserializeObject(string pXmlizedString,System.Typety) { XmlSerializerxs = new XmlSerializer(ty); MemoryStreammemoryStream = newMemoryStream(StringToUTF8ByteArray(pXmlizedString)); XmlTextWriterxmlTextWriter = newXmlTextWriter(memoryStream,Encoding.UTF8); returnxs.Deserialize(memoryStream); } //创建XML文件 publicvoid CreateXML(string fileName,string thisData) { string xxx =Encrypt(thisData); StreamWriter writer; writer =File.CreateText(fileName); writer.Write(xxx); writer.Close(); } //读取XML文件 publicstring LoadXML(string fileName) { StreamReader sReader =File.OpenText(fileName); string dataString =sReader.ReadToEnd(); sReader.Close(); string xxx =Decrypt(dataString); return xxx; } //判断是否存在文件 publicbool hasFile(String fileName) { returnFile.Exists(fileName); } publicstring UTF8ByteArrayToString(byte[] characters ) { UTF8Encodingencoding = new UTF8Encoding(); stringconstructedString =encoding.GetString(characters); return(constructedString); } publicbyte[] StringToUTF8ByteArray(String pXmlString ) { UTF8Encodingencoding = new UTF8Encoding(); byte[]byteArray = encoding.GetBytes(pXmlString); return byteArray; } - }