转自:http://blog.sina.com.cn/s/blog_471132920101d3kh.html
两步实现超实用的XML存档
本套存档的优点:易使用,跨平台,防作弊(内容加密 + 防拷贝)
脚本下载地址
使用方法非常简单:
把GameDataManager和XmlSaver两个脚本添加至工程后
(1)新建一个GameObject,起名GameDataManager并将GameDataManager脚本拖到上面。
(2)在GameDataManager里的GameData类中添加需要储存的数据
OK,跨平台防破解防拷贝的存档就搞定了!之后每次存档调用GameDataManager的Save函数,读档调用GameDataManager的Load函数。每次启动后GameDataManager会自动调用Load读档。如果玩家拿外来存档来覆盖本地存档,则游戏启动后数据清零,任何一次存档后作弊档被自动覆盖。注意:请勿放入二维以上数组,一般一维数据,枚举,自定义类等等数据类型可放心添加。
iOS,Android,PC,MAC都使用过的。密钥的设定根据平台而定。
GameDataManager.cs的内容
//========================================================================================================= //Note:DataManaging. //DateCreated:2012/04/17by风宇冲 //DateModified:2012/12/14by风宇冲 //=========================================================================================================usingUnityEngine; usingSystem.Collections; usingSystem.IO; usingSystem.Collections.Generic; usingSystem; usingSystem.Text; usingSystem.Xml; usingSystem.Security.Cryptography; //GameData,储存数据的类,把需要储存的数据定义在GameData之内就行//publicclassGameData { //密钥,用于防止拷贝存档// publicstringkey; //下面是添加需要储存的内容// publicstringPlayerName; publicfloatMusicVolume; publicGameData() { PlayerName="Player"; MusicVolume=0.6f; } } //管理数据储存的类//publicclassGameDataManager:MonoBehavIoUr { privatestringdataFileName="tankyWarData.dat";//存档文件的名称,自己定// privateXmlSaverxs=newXmlSaver(); publicGameDatagameData; publicvoidAwake() { gameData=newGameData(); //设定密钥,根据具体平台设定// gameData.key=SystemInfo.deviceUniqueIdentifier; Load(); } //存档时调用的函数// publicvoidSave() { stringgameDataFile=GetDataPath()+"/"+dataFileName; stringdataString=xs.SerializeObject(gameData,typeof(GameData)); xs.CreateXML(gameDataFile,dataString); } //读档时调用的函数// publicvoidLoad() { stringgameDataFile=GetDataPath()+"/"+dataFileName; if(xs.hasFile(gameDataFile)) { stringdataString=xs.LoadXML(gameDataFile); GameDatagameDataFromXML=xs.DeserializeObject(dataString,typeof(GameData))asGameData; //是合法存档// if(gameDataFromXML.key==gameData.key) { gameData=gameDataFromXML; } //是非法拷贝存档// else { //留空:游戏启动后数据清零,存档后作弊档被自动覆盖//} } else { if(gameData!=null) Save(); } } //获取路径// privatestaticstringGetDataPath() { //Yourgamehasread+writeaccessto/var/mobile/Applications/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/Documents //Application.dataPathreturnsar/mobile/Applications/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/myappname.app/Data //Strip"/Data"frompath if(Application.platform==RuntimePlatform.IPhonePlayer) { stringpath=Application.dataPath.Substring(0,Application.dataPath.Length-5); //Stripapplicationname path=path.Substring(0,path.LastIndexOf('/')); returnpath+"/Documents"; } else //returnApplication.dataPath+"/Resources"; returnApplication.dataPath; } }
XmlSaver.cs
//========================================================================================================= //Note:XMLprocesscing,cannotsavemultiple-array!!! //DateCreated:2012/04/17by风宇冲 //DateModified:2012/04/19by风宇冲 //=========================================================================================================usingUnityEngine; usingSystem.Collections; usingSystem.Xml; usingSystem.Xml.Serialization; usingSystem.IO; usingSystem.Text; usingSystem.Security.Cryptography; usingSystem; publicclassXmlSaver { //内容加密 publicstringEncrypt(stringtoE) { //加密和解密采用相同的key,具体自己填,但是必须为32位// byte[]keyArray=UTF8Encoding.UTF8.GetBytes("12348578902223367877723456789012"); RijndaelManagedrDel=newRijndaelManaged(); rDel.Key=keyArray; rDel.Mode=CipherMode.ECB; rDel.Padding=PaddingMode.PKCS7; ICryptoTransformcTransform=rDel.CreateEncryptor(); byte[]toEncryptArray=UTF8Encoding.UTF8.GetBytes(toE); byte[]resultArray=cTransform.TransformFinalBlock(toEncryptArray,toEncryptArray.Length); returnConvert.ToBase64String(resultArray,resultArray.Length); } //内容解密 publicstringDecrypt(stringtoD) { //加密和解密采用相同的key,具体值自己填,但是必须为32位// byte[]keyArray=UTF8Encoding.UTF8.GetBytes("12348578902223367877723456789012"); RijndaelManagedrDel=newRijndaelManaged(); rDel.Key=keyArray; rDel.Mode=CipherMode.ECB; rDel.Padding=PaddingMode.PKCS7; ICryptoTransformcTransform=rDel.CreateDecryptor(); byte[]toEncryptArray=Convert.FromBase64String(toD); byte[]resultArray=cTransform.TransformFinalBlock(toEncryptArray,toEncryptArray.Length); returnUTF8Encoding.UTF8.GetString(resultArray); } publicstringSerializeObject(objectpObject,System.Typety) { stringXmlizedString=null; MemoryStreammemoryStream=newMemoryStream(); XmlSerializerxs=newXmlSerializer(ty); XmlTextWriterxmlTextWriter=newXmlTextWriter(memoryStream,Encoding.UTF8); xs.Serialize(xmlTextWriter,pObject); memoryStream=(MemoryStream)xmlTextWriter.BaseStream; XmlizedString=UTF8ByteArrayToString(memoryStream.ToArray()); returnXmlizedString; } publicobjectDeserializeObject(stringpXmlizedString,System.Typety) { XmlSerializerxs=newXmlSerializer(ty); MemoryStreammemoryStream=newMemoryStream(StringToUTF8ByteArray(pXmlizedString)); XmlTextWriterxmlTextWriter=newXmlTextWriter(memoryStream,Encoding.UTF8); returnxs.Deserialize(memoryStream); } //创建XML文件 publicvoidCreateXML(stringfileName,stringthisData) { stringxxx=Encrypt(thisData); StreamWriterwriter; writer=File.CreateText(fileName); writer.Write(xxx); writer.Close(); } //读取XML文件 publicstringLoadXML(stringfileName) { StreamReadersReader=File.OpenText(fileName); stringdataString=sReader.ReadToEnd(); sReader.Close(); stringxxx=Decrypt(dataString); returnxxx; } //判断是否存在文件 publicboolhasFile(StringfileName) { returnFile.Exists(fileName); } publicstringUTF8ByteArrayToString(byte[]characters) { UTF8Encodingencoding=newUTF8Encoding(); stringconstructedString=encoding.GetString(characters); return(constructedString); } publicbyte[]StringToUTF8ByteArray(StringpXmlString) { UTF8Encodingencoding=newUTF8Encoding(); byte[]byteArray=encoding.GetBytes(pXmlString); returnbyteArray; } }