unity3D加密

来源:互联网 发布:java 时间string转date 编辑:程序博客网 时间:2024/05/16 11:08

打包资源,加载资源已经是ungity3d很常见的事了,其中为了自己的资源不被别人抄袭,经常会将已经打包好的“xx.unity3d”机密,一种是在外边加一次“保护膜”(比如建个文件夹,把文件夹加密,这种我没研究过),另一种就是把“.unity3d”包转换成“.byte”文件,把转换好的“.byte”文件用一定的规律乱掉(规律要记好,解密时还要用),然后再把“.byte”文件打包成“.unity3d”文件,这样打包完的“.unity3d”资源包必须经过两次加载和一次生成才能使用,第一次是加载成“.byte”文件,然后将“.byte”文件生成“.unity3d”虚拟资源包,最后再加载生成的虚拟资源包里的真实资源(中间需要解密)。


打包资源我就不谈论了,网上有具体的代码,今天主要说说解密时遇到的问题,把".byte"文件加载成“.unity3d”包需要用到AssetBundle.CreateFromMemory(byte[] bytes)方法,这是一个从内存字节生成资源包的方法,返回的是 AssetBundleCreateRequest类型,同是返回的有一个数据流,这就需要用到协同程序(主要是yield return AssetBundleCreateRequest),而第一次加载也需要用到协同程序,因此网上给了一种协同里面套协同的方法。我试着用了一下,发现这个加载脚本需要继承MonoBehaviour类,但是加载资源的脚本里面不需要用到Start()和Update()方法,只是写了一些公开的方法而已,因此不必继承 MonoBehaviour类,因此StartCoroutine方法就不能使用,所以网上给的协同里面套协同就不合适了,于是我就开始了苦逼的一天。


开始我想在第一次加载的方法(LoadAsset())里面另开个线程,通过线程调用第二次加载(LoadBundle())方法,但是系统报错,说IEnumerator调用必须在主线程中,我郁闷了,所以我就开始查关于AssetBundleCreateRequest的文档,并开始用普通方法调用:因为IEnumerator返回的肯定是IEnumerator类,所以我声明了一个IEnumerator类型的ie变量接受IEnumerator的返回值,然后调用IEnumerator.MoveNext()方法,这样就把AssetBundleCreateRequest类返回给我了,我开始很高兴,因为得到AssetBundleCreateRequest后就可以通过AssetBundleCreateRequest.progress和AssetBundleCreateRequest.isDown查看进度,等到AssetBundleCreateRequest.progress >=1就表明“.unity3d”包创建完成(这是虚拟包,可以直接加载),然后我就可以加载,最后实例化,这就完成了,但是事实没有我想的那么完美,出现了一个意想不到事情,AssetBundleCreateRequest.progress和AssetBundleCreateRequest.isDown竟然不同步,progress显示的是1,按说isDown应该是true,但事实却是false,这很让我费解,然后我就去查这两个到底代表了什么意思,最后发现progress确实是下载进度,但isDown确是是否完成操作,也就是AssetBundleCreateRequest这个异步操作是否完成,这就坑爹了,AssetBundleCreateRequest是继承了AsyncOperation 类,但是这是unity3d自己封装的,不是c#封装的,官网上也没明确给出AsyncOperation 异步操作的终止方法,等于说打了个死结了。就在我以为只能认命时(脚本继承MonoBehaviour)时,突然发现自己脑残了,你妹的别人博客上把二个协同写成一个套一个,我可以把两个协同写在一起啊,一个yield return WWW,一个yield return AssetBundleCreateRequest。完全可以解决不必继承MonoBehaviour的事情,至于为什么这么做,下次再说吧,下面我将代码传上。



  1. public class ResourceManager
  2. {
  3.     bool isloadfromCache = true;//是否从缓存加载
  4.     private static ResourceManager resourceManager;
  5.     int m_CacheVersion = 5;//版本号


  6. //实例化
  7.     public static ResourceManager getInstance()
  8.     {
  9.         if(resourceManager == null)
  10.       {
  11.            resourceManager = new ResourceManager(); 
  12.        }
  13.         return resourceManager; 
  14.     } 

  15. //构造方法
  16.     public ResourceManager()
  17.     {
  18. //我用的是本地加载,网络需要用“http://”
  19.         mResourcePath = "file://" + Application.dataPath;
  20.     }

  21.     //协同程序,需要用StartCoroutine()方法调用,可以外部调用
  22.      public IEnumerator LoadAsset(string fileName)
  23.     {
  24.         string fullurl = mResourcePath + "/" + "Unity3d/"+fileName+".unity3d"; //加载路径
  25.           WWW m_Download;
  26.           if(isloadfromCache){
  27.            m_Download = WWW.LoadFromCacheOrDownload(fullurl,m_CacheVersion); 
  28.           }else{
  29.            m_Download = new WWW(fullurl);
  30.           }
  31.         //第一次协同
  32.           yield return m_Download; 
  33.         if(m_Download.error != null)
  34.           {
  35.             //   Debug.LogError(m_Download.error);
  36.            Debug.Log("Warning errow"+fileName);
  37.            yield break;
  38.              } 
  39.             //第一次加载
  40.             TextAsset txt = m_Download.assetBundle.Load(fileName,typeof(TextAsset)) as TextAsset;
  41.             byte[]  data = txt.bytes;
  42.             byte[] decryptedData = Decryption(data);
  43.             //打成虚拟包
  44.             AssetBundleCreateRequest acr = AssetBundle.CreateFromMemory(decryptedData);
  45.             //原本要第二次协同
  46.              yield return acr;
  47.             AssetBundle bundle = acr.assetBundle;   
  48.             //第二次加载
  49.              bundle .LoadAll();
  50.             Instantiate(bundle.mainAsset); 
  51.     } 
  52.     byte[] Decryption(byte[] data){
  53.         //解密算法,这个要自己写,你加密时是怎样,这里反过来
  54.     }

  55. }