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

两步实现超实用的XML存档

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

脚本下载地址

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

iOS,Android,PC,MAC都使用过的。密钥的设定根据平台而定。

GameDataManager.cs的内容

//=========================================================================================================
//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
{
    //密钥,用于防止拷贝存档//
    public string key; 

    //下面是添加需要储存的内容//
    public string PlayerName;
    public float MusicVolume;
    public GameData()
    {
        PlayerName = "Player";
        MusicVolume = 0.6f;
    }
}
//管理数据储存的类//
public class GameDataManager:MonoBehaviour
{
    private string dataFileName ="tankyWarData.dat";//存档文件的名称,自己定//
    private  XmlSaver xs = new XmlSaver(); 

    public  GameData gameData; 

    public void Awake()
    {
        gameData = new GameData(); 

        //设定密钥,根据具体平台设定//
        gameData.key = SystemInfo.deviceUniqueIdentifier;
        Load();
    } 

    //存档时调用的函数//
    public  void Save()
    {
        string gameDataFile = GetDataPath() + "/"+dataFileName;
        string dataString= xs.SerializeObject(gameData,typeof(GameData));
        xs.CreateXML(gameDataFile,dataString);
    } 

    //读档时调用的函数//
    public  void Load()
    {
        string gameDataFile = 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();
        }
    } 

    //获取路径//
    private static string GetDataPath()
    {
        // Your game has read+write access to /var/mobile/Applications/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/Documents
        // Application.dataPath returns ar/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);
            // Strip application name
            path = path.Substring(0, path.LastIndexOf(‘/‘));
            return path + "/Documents";
        }
        else
        //    return Application.dataPath + "/Resources";
            return Application.dataPath;
    }
} 

XmlSaver.cs

//=========================================================================================================
//Note: XML processcing,  can not save multiple-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
{
    //内容加密
    public string Encrypt(string toE)
    {
        //加密和解密采用相同的key,具体自己填,但是必须为32位//
        byte[] keyArray = UTF8Encoding.UTF8.GetBytes("12348578902223367877723456789012");
        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,0,toEncryptArray.Length); 

        return Convert.ToBase64String(resultArray,0,resultArray.Length);
    } 

    //内容解密
    public string Decrypt(string toD)
    {
        //加密和解密采用相同的key,具体值自己填,但是必须为32位//
        byte[] keyArray = UTF8Encoding.UTF8.GetBytes("12348578902223367877723456789012"); 

        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,0,toEncryptArray.Length); 

        return UTF8Encoding.UTF8.GetString(resultArray);
    } 

    public string SerializeObject(object pObject,System.Type ty)
    {
       string XmlizedString   = null;
       MemoryStream memoryStream  = new MemoryStream();
       XmlSerializer xs  = new XmlSerializer(ty);
       XmlTextWriter xmlTextWriter  = new XmlTextWriter(memoryStream, Encoding.UTF8);
       xs.Serialize(xmlTextWriter, pObject);
       memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
       XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());
       return XmlizedString;
    } 

    public object DeserializeObject(string pXmlizedString , System.Type ty)
    {
       XmlSerializer xs  = new XmlSerializer(ty);
       MemoryStream memoryStream  = new MemoryStream(StringToUTF8ByteArray(pXmlizedString));
       XmlTextWriter xmlTextWriter   = new XmlTextWriter(memoryStream, Encoding.UTF8);
       return xs.Deserialize(memoryStream);
    } 

    //创建XML文件
    public void CreateXML(string fileName,string thisData)
    {
       string xxx = Encrypt(thisData);
       StreamWriter writer;
       writer = File.CreateText(fileName);
       writer.Write(xxx);
       writer.Close();
    } 

    //读取XML文件
    public string LoadXML(string fileName)
    {
       StreamReader sReader = File.OpenText(fileName);
       string dataString = sReader.ReadToEnd();
       sReader.Close();
       string xxx = Decrypt(dataString);
       return xxx;
    } 

    //判断是否存在文件
    public bool hasFile(String fileName)
    {
       return File.Exists(fileName);
    }
    public string UTF8ByteArrayToString(byte[] characters  )
    {
       UTF8Encoding encoding  = new UTF8Encoding();
       string constructedString  = encoding.GetString(characters);
       return (constructedString);
    } 

    public byte[] StringToUTF8ByteArray(String pXmlString )
    {
       UTF8Encoding encoding  = new UTF8Encoding();
       byte[] byteArray  = encoding.GetBytes(pXmlString);
       return byteArray;
    }
} 

转载:http://blog.sina.com.cn/s/blog_471132920101d3kh.html

U3D教程宝典之两步实现超实用的XML存档,布布扣,bubuko.com

时间: 2024-12-23 13:26:46

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

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

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

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

混血妆容教程 妆前两步排水肿不脱 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

2Unity3D教程宝典之插件篇:Unity3D插件详细评测及教学下载

转载自风宇冲Unity3D教程学院 http://blog.sina.com.cn/s/blog_471132920101crh3.html 引言:想用Unity3D制作优秀的游戏,插件是必不可少的.工欲善其事必先利其器.本文主旨是告诉使用Unity3D引擎的同学们如何根据需求选择适当的工具.为此我写了插件的经验及理论讲解,涉及插件的 学习/辨别/选择/配合.也写了插件的 评测/教程/下载.关于评测,带有一定的主观性,仅供参考.关于教程,热门插件网上已经有很多教程了,本文提供链接,网上资料少的插

Unity3D教程宝典之光影烘焙:第三讲Light probes

引言:烘焙出来的light map并不能作用于动态物体.如果场景里有动态物体的话,会显得与烘焙好的场景脱离.需要两个部分的效果:影子:(1)使用勾选阴影的实时光.(注意:Dual+deferred Dual+forward Single+forward都有影子   只有Single+deferred,即使光勾选了阴影,也不会有影子.) 明暗变化:(1)使用实时光(2)使用Light Probes(3)使用脚本控制物体处于阴影区域的颜色:(1)(2)都默认是黑色,除非自己在阴影区域再加光源(3)自

Unity3D教程宝典之光影烘焙:第一讲光影烘焙

引言:光影烘焙,英文叫Lightmapping 或 light baking.Unity自带了Lightmapping的功能(是Illuminate Labs出的名为Beast的产品).本系列教程分为4讲:第一讲 光影烘焙第二讲 AreaLight第三讲 Light Probes第四讲 脚本控制其中第三第四讲讲解的是动态物体与烘焙后场景的融合.             光影烘焙 打开方式 Window – Lightmapping有几点需要注意:1.所要烘焙物体的mesh 必须要有合适的ligh

两步验证杀手锏:Java 接入 Google 身份验证器实战

两步验证 大家应该对两步验证都熟悉吧?如苹果有自带的两步验证策略,防止用户账号密码被盗而锁定手机进行敲诈,这种例子屡见不鲜,所以苹果都建议大家开启两步验证的. Google 的身份验证器一般也是用于登录进行两步验证,和苹果的两步验证是同样的道理.只不过 Google 的身份验证器用得更多更广泛,如 GitHub 的两步验证都是基于 Google 身份验证器. Google Authenticator 简介 Google Authenticator 身份验证器是一款基于时间与哈希的一次性密码算法的

只需两步快速获取微信小程序源码

只需两步快速获取微信小程序源码 第一次在掘金这样高大上的社区写文章,忐忑地敲下我获取小程序源码过程中的经验分享. 最近在学习微信小程序开发,半个月学习下来,很想实战一下踩踩坑,于是就仿写了某个小程序的前端实现,过程一言难尽,差不多两周时间过去了,发现小程序的坑远比想象的要多的多!!在实际练手中,完全是黑盒的,纯靠推测,部分效果在各种尝试后能能做出大致的实现,但是有些细节,实在不知道如何去实现.这种时候,真的很想一窥源码,查看究竟,看看大厂的前端大神们是如何规避了小程序的一些比较奇葩的坑. 于是就

两步快速获取小程序源码

最近在学习微信小程序开发,半个月学习下来,很想实战一下踩踩坑,于是就仿写了某个小程序的前端实现,在实际练手中,完全是黑盒的,纯靠推测,部分效果在各种尝试后能能做出大致的实现,但是有些细节,实在不知道如何去实现.这种时候,真的很想一窥源码,查看究竟,看看大厂的前端大神们是如何规避了小程序的一些比较奇葩的坑. 于是就想到获取到小程序地源文件,然后尝试对其进行反编译还原为源代码,来作为学习参考.我百度了各种关于小程序地反编译教程,但是感觉都不太适合像我这样地初学小白,踩了挺多坑.在这里把我重新简化好的

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

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