【转】两步实现超实用的XML存档 易使用,跨平台,防作弊(内容加密 + 防拷贝)

转载自风宇冲Unity3D教程学院

两步实现超实用的XML存档

本套存档的优点:易使用,跨平台,防作弊(内容加密 + 防拷贝)

脚本下载地址

使用方法非常简单:
把GameDataManager和XmlSaver两个脚本添加至工程后
(1)新建一个GameObject,起名GameDataManager并将GameDataManager脚本拖到上面。
(2)在GameDataManager里的GameData类中添加需要储存的数据
OK,跨平台防破解防拷贝的存档就搞定了!之后每次存档调用GameDataManager的Save函数,读档调用GameDataManager的Load函数。每次启动后GameDataManager会自动调用Load读档。如果玩家拿外来存档来覆盖本地存档,则游戏启动后数据清零,任何一次存档后作弊档被自动覆盖。注意:请勿放入二维以上数组,一般一维数据,枚举,自定义类 等等数据类型可放心添加。

PS:风宇冲自己的U3d单机游戏和公司的单机游戏都用的这个XML存档,iOS,Android,PC,MAC都使用过的。放心使用吧。密钥的设定根据平台而定。

附:脚本代码
                                    GameDataManager.cs的内容

  1. //=========================================================================================================
  2. //Note: Data Managing.
  3. //Date Created: 2012/04/17 by 风宇冲
  4. //Date Modified: 2012/12/14 by 风宇冲
  5. //=========================================================================================================
  6. using UnityEngine;
  7. using System.Collections;
  8. using System.IO;
  9. using System.Collections.Generic;
  10. using System;
  11. using System.Text;
  12. using System.Xml;
  13. using System.Security.Cryptography;
  14. //GameData,储存数据的类,把需要储存的数据定义在GameData之内就行//
  15. public class GameData
  16. {
  17. //密钥,用于防止拷贝存档//
  18. public string key;
  19. //下面是添加需要储存的内容//
  20. public string PlayerName;
  21. public float MusicVolume;
  22. public GameData()
  23. {
  24. PlayerName = "Player";
  25. MusicVolume = 0.6f;
  26. }
  27. }
  28. //管理数据储存的类//
  29. public class GameDataManager:MonoBehaviour
  30. {
  31. private string dataFileName ="tankyWarData.dat";//存档文件的名称,自己定//
  32. private  XmlSaver xs = new XmlSaver();
  33. public  GameData gameData;
  34. public void Awake()
  35. {
  36. gameData = new GameData();
  37. //设定密钥,根据具体平台设定//
  38. gameData.key = SystemInfo.deviceUniqueIdentifier;
  39. Load();
  40. }
  41. //存档时调用的函数//
  42. public  void Save()
  43. {
  44. string gameDataFile = GetDataPath() + "/"+dataFileName;
  45. string dataString= xs.SerializeObject(gameData,typeof(GameData));
  46. xs.CreateXML(gameDataFile,dataString);
  47. }
  48. //读档时调用的函数//
  49. public  void Load()
  50. {
  51. string gameDataFile = GetDataPath() + "/"+dataFileName;
  52. if(xs.hasFile(gameDataFile))
  53. {
  54. string dataString = xs.LoadXML(gameDataFile);
  55. GameData gameDataFromXML = xs.DeserializeObject(dataString,typeof(GameData)) as GameData;
  56. //是合法存档//
  57. if(gameDataFromXML.key == gameData.key)
  58. {
  59. gameData = gameDataFromXML;
  60. }
  61. //是非法拷贝存档//
  62. else
  63. {
  64. //留空:游戏启动后数据清零,存档后作弊档被自动覆盖//
  65. }
  66. }
  67. else
  68. {
  69. if(gameData != null)
  70. Save();
  71. }
  72. }
  73. //获取路径//
  74. private static string GetDataPath()
  75. {
  76. // Your game has read+write access to /var/mobile/Applications/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/Documents
  77. // Application.dataPath returns ar/mobile/Applications/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/myappname.app/Data
  78. // Strip "/Data" from path
  79. if(Application.platform == RuntimePlatform.IPhonePlayer)
  80. {
  81. string path = Application.dataPath.Substring (0, Application.dataPath.Length - 5);
  82. // Strip application name
  83. path = path.Substring(0, path.LastIndexOf(‘/‘));
  84. return path + "/Documents";
  85. }
  86. else
  87. //    return Application.dataPath + "/Resources";
  88. return Application.dataPath;
  89. }
  90. }

XmlSaver.cs的内容

    1. //=========================================================================================================
    2. //Note: XML processcing,  can not save multiple-array!!!
    3. //Date Created: 2012/04/17 by 风宇冲
    4. //Date Modified: 2012/04/19 by 风宇冲
    5. //=========================================================================================================
    6. using UnityEngine;
    7. using System.Collections;
    8. using System.Xml;
    9. using System.Xml.Serialization;
    10. using System.IO;
    11. using System.Text;
    12. using System.Security.Cryptography;
    13. using System;
    14. public class XmlSaver
    15. {
    16. //内容加密
    17. public string Encrypt(string toE)
    18. {
    19. //加密和解密采用相同的key,具体自己填,但是必须为32位//
    20. byte[] keyArray = UTF8Encoding.UTF8.GetBytes("12348578902223367877723456789012");
    21. RijndaelManaged rDel = new RijndaelManaged();
    22. rDel.Key = keyArray;
    23. rDel.Mode = CipherMode.ECB;
    24. rDel.Padding = PaddingMode.PKCS7;
    25. ICryptoTransform cTransform = rDel.CreateEncryptor();
    26. byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toE);
    27. byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray,0,toEncryptArray.Length);
    28. return Convert.ToBase64String(resultArray,0,resultArray.Length);
    29. }
    30. //内容解密
    31. public string Decrypt(string toD)
    32. {
    33. //加密和解密采用相同的key,具体值自己填,但是必须为32位//
    34. byte[] keyArray = UTF8Encoding.UTF8.GetBytes("12348578902223367877723456789012");
    35. RijndaelManaged rDel = new RijndaelManaged();
    36. rDel.Key = keyArray;
    37. rDel.Mode = CipherMode.ECB;
    38. rDel.Padding = PaddingMode.PKCS7;
    39. ICryptoTransform cTransform = rDel.CreateDecryptor();
    40. byte[] toEncryptArray = Convert.FromBase64String(toD);
    41. byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray,0,toEncryptArray.Length);
    42. return UTF8Encoding.UTF8.GetString(resultArray);
    43. }
    44. public string SerializeObject(object pObject,System.Type ty)
    45. {
    46. string XmlizedString   = null;
    47. MemoryStream memoryStream  = new MemoryStream();
    48. XmlSerializer xs  = new XmlSerializer(ty);
    49. XmlTextWriter xmlTextWriter  = new XmlTextWriter(memoryStream, Encoding.UTF8);
    50. xs.Serialize(xmlTextWriter, pObject);
    51. memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
    52. XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());
    53. return XmlizedString;
    54. }
    55. public object DeserializeObject(string pXmlizedString , System.Type ty)
    56. {
    57. XmlSerializer xs  = new XmlSerializer(ty);
    58. MemoryStream memoryStream  = new MemoryStream(StringToUTF8ByteArray(pXmlizedString));
    59. XmlTextWriter xmlTextWriter   = new XmlTextWriter(memoryStream, Encoding.UTF8);
    60. return xs.Deserialize(memoryStream);
    61. }
    62. //创建XML文件
    63. public void CreateXML(string fileName,string thisData)
    64. {
    65. string xxx = Encrypt(thisData);
    66. StreamWriter writer;
    67. writer = File.CreateText(fileName);
    68. writer.Write(xxx);
    69. writer.Close();
    70. }
    71. //读取XML文件
    72. public string LoadXML(string fileName)
    73. {
    74. StreamReader sReader = File.OpenText(fileName);
    75. string dataString = sReader.ReadToEnd();
    76. sReader.Close();
    77. string xxx = Decrypt(dataString);
    78. return xxx;
    79. }
    80. //判断是否存在文件
    81. public bool hasFile(String fileName)
    82. {
    83. return File.Exists(fileName);
    84. }
    85. public string UTF8ByteArrayToString(byte[] characters  )
    86. {
    87. UTF8Encoding encoding  = new UTF8Encoding();
    88. string constructedString  = encoding.GetString(characters);
    89. return (constructedString);
    90. }
    91. public byte[] StringToUTF8ByteArray(String pXmlString )
    92. {
    93. UTF8Encoding encoding  = new UTF8Encoding();
    94. byte[] byteArray  = encoding.GetBytes(pXmlString);
    95. return byteArray;
    96. }
    97. }
时间: 2024-08-06 07:55:42

【转】两步实现超实用的XML存档 易使用,跨平台,防作弊(内容加密 + 防拷贝)的相关文章

U3D教程宝典之两步实现超实用的XML存档

两步实现超实用的XML存档 本套存档的优点:易使用,跨平台,防作弊(内容加密 + 防拷贝) 脚本下载地址 使用方法非常简单:把GameDataManager和XmlSaver两个脚本添加至工程后(1)新建一个GameObject,起名GameDataManager并将GameDataManager脚本拖到上面.(2)在GameDataManager里的GameData类中添加需要储存的数据OK,跨平台防破解防拷贝的存档就搞定了!之后每次存档调用GameDataManager的Save函数,读档调

vi应用:使用v和s命令两步提取出想要的内容

本文以提出spring中配置文件applicationContext.xml中所有bean的id为例,讲解如何使用vi的v和s命令两步提取出想要的内容. applicationContext.xml文件内容如下: <?xml version = "1.0" encoding = "UTF-8" ?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns

只需两步!Eclipse+Maven快速构建第一个Spring Boot项目

随着使用Spring进行开发的个人和企业越来越多,Spring从一个单一简洁的框架变成了一个大而全的开源软件,最直观的变化就是Spring需要引入的配置也越来越多.配置繁琐,容易出错,让人无比头疼,简化Spring配置简直可以说是民心所向. Spring Boot是由Pivotal团队提供的一个基于Java的全新的开源框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.如今,Spring Boot逐渐成为快

挑子学习笔记:两步聚类算法(TwoStep Cluster Algorithm)——改进的BIRCH算法

转载请标明出处:http://www.cnblogs.com/tiaozistudy/p/twostep_cluster_algorithm.html 两步聚类算法是在SPSS Modeler中使用的一种聚类算法,是BIRCH层次聚类算法的改进版本.可以应用于混合属性数据集的聚类,同时加入了自动确定最佳簇数量的机制,使得方法更加实用.本文在学习文献[1]和“IBM SPSS Modeler 15 Algorithms Guide”的基础上,融入了自己的理解,更详尽地叙述两步聚类算法的流程和细节.

华为机试题 N阶楼梯的走法,每次走一步或者两步

在Stairs函数中实现该功能: 一个楼梯有N阶,从下往上走,一步可以走一阶,也可以走两阶,有多少种走法? (0<n<=30)<> 例如3阶楼梯有3种走法: 1.1.1 1.2 2.1 输入样例: 3 返回值样例: 3 思路:这是最典型的类似斐波那契数列的变型.N阶楼梯,第一步有两种走法,1.走一步,则剩下N-1级      2,走两步,剩下N-2级      所以f(n)=f(n-1)+f(n-2) public static int ways(int n){ if(n==1)

100个台阶,一次走一步,走两步,走三步,有多少种可能

分析 第一个台阶  1第二个台阶  11 2    //走两次1步或者走1次两步第三个台阶  111 12 21 3 第四个台阶  1111 112 121 211 22 13 31f(n)=f(n-1)+f(n-2)+f(n-3)  第n个台阶的可能 = n-1台阶的可能+n-2台阶的可能+n-3台阶的可能 我这里采用了递归算法 //param x 台阶数目 int goadd(int x) { if (x == 1){ return 1; } else if (x == 2){ return

两步修改CentOS主机名称

在CentOS系统中,修改主机名称的步骤如下: 1. 修改network文件 编辑network文件,配置如下: vi /etc/sysconfig/network 配置 NETWORKING=yes HOSTNAME=Hadoop-cluster 2 加载配置 hostname Hadoop-cluster hostname Hadoop-cluster 两步修改CentOS主机名称,布布扣,bubuko.com

链接器的“两步链接”

"两部链接"(Two-pass linking),是指链接的过程分为两步:地址分配 -> 重定向. 地址分配:扫描输入的目标文件,分配各目标文件内各段的地址,并收集全局符号定义和引用,放入一个全局符号表.完成这一步后,所有的符号地址都被确定了. 重定向:重定向各输入文件中引用的全局符号到其实际的地址. 参考:<程序员的自我修养>,第 4 章 1 ~ 2 节.

混血妆容教程 妆前两步排水肿不脱妆

混血妆容教程 妆前两步排水肿不脱 http://baozoumanhua.com/users/13998545/forum_articleshttp://baozoumanhua.com/users/13998544/forum_articleshttp://baozoumanhua.com/users/13998551/forum_articleshttp://baozoumanhua.com/users/13998554/forum_articleshttp://baozoumanhua.c