1.Unity Mono加密解决方案
2.Cpp 相关插件集成Unity C# 和 C++ 互调 「0x01」
3.研究快速修改Unity构建包内的源码资源文件
4.IL2CPP简介以及打包分析
5.如何防止unity3d代码被反编译?
6.怎么看unity2021.2在编辑器工作流上的改进?
Unity Mono加密解决方案
Unity Mono是Unity引擎的脚本运行时环境,提供跨平台的源码开源.NET框架实现,支持C#等编程语言编写游戏逻辑。源码然而,源码Mono模式下,源码游戏的源码c 源码 accessC#代码容易被专业反编译软件分析逆向,导致安全性低。源码为解决此问题,源码Unity Mono加密方案经历了三代演进。源码
第一代加密方式是源码整体加密,修改mono源码以对DLL脚本进行加密。源码这种方法缺点是源码加载前进行一次性解密,内存中存在完整的源码DLL,可用工具获取。源码搜索PE文件Dos头特征码即可获取DLL信息。源码
第二代加密方式为函数加密,仅在使用方法时进行解密,减少内存中完整DLL的存在。但解析工具仍可见函数名及部分函数,存在安全隐患。
第三代加密方案是DLL结构虚拟化,重构文件结构并高强度加密数据,工具无法解析数据,即使是专业破解人员也难以解密结构数据。使用Editor解析正常PE结构,但使用DLL结构虚拟化后,无法正常解析。
针对Unity Mono的加密方案,FairGuard游戏加固提供了成熟方案,能对mono DLL、global-metadata.dat、libil2cpp.so等文件进行高强度加密,并研发了Unity Assetbundle资源加密方案。此外,还提供多项安全功能,如反内存修改、反调试、文件完整性校验等,有效解决游戏安全问题。
Cpp 相关插件集成Unity C# 和 C++ 互调 「0x」
近期,我们正在尝试将内部技术应用到外部内容产出中,查询商品溯源码特别关注的是如何将C++ SDK与Unity的C#交互。由于项目涉及底层美颜处理和实时流媒体,涉及纹理和二进制数据传输,我们面临着C++与Unity的互调挑战。本章节将着重介绍Windows环境下构建基本的Unity与C++互调步骤,暂未涉及跨平台。
首先,创建一个新的Dll项目,命名为DllSimple,接着创建工程并添加DllInterface类。对于Unity开发者,新建项目后,只需创建两个C#脚本即可。对于C++开发者,需确保STBoot组件正确配置。
在C#中,当考虑性能时,可能使用C++编写战斗系统,如计算实体间的距离。为此,我们需要在DllInterface.h中声明导出接口,并在DllInterface.cpp中实现相关功能。接着,导出Dll库并将其放置在Unity的Plugins目录下。
在Unity中,我们需要完善STDllInterface.cs文件,使其能够调用C++的函数。例如,为解决SDK的Log输出问题,我们修改DllInterface.h以支持C#函数的回调。在Unity端,创建函数并调用C++的Log函数。
这个例子展示了基础的C#调用C++,并展示了如何处理SDK的问题。尽管目前实现了基本交互,但在实践中遇到了小问题,即Dll在Unity编辑器中被占用。未来会探索更复杂的功能,并解决这个临时问题。
总结,自动上传源码这只是Unity与C++交互的一个起点,我们还会继续更新和优化。源码已分享,欢迎各位贡献和关注。
研究快速修改Unity构建包内的资源文件
本文将探讨如何实现快速修改Unity构建包内资源文件的方法,目标是使整个操作耗时控制在分钟级别,且无需依赖Unity引擎。以一个Resource目录下的空节点Prefab为例,首先,找到其构建后对应的资源文件。预制体构建后,文件以prefab的guid命名,存放在名为Data的二进制文件中。要对这个Data文件进行修改,需了解其格式,但Unity官方文档并未提供详细的二进制文件格式定义,也没有提供将Prefab资源转化为Data二进制文件的API。因此,我们借助开源工具AssetStudio查看Unity Data二进制文件格式,并从源码中找到解析二进制文件的逻辑。
我们得知,Prefab的二进制Data资源是SerializedFile格式,其解析逻辑位于SerializedFile.cs代码文件中。SerializedFile包含文件头和数据部分,文件头格式在Unity版本中如下所示。
文件头格式包含了多个字段,部分字段含义可以通过测试推断。例如,当给Prefab挂载自定义脚本时,发现localSerializedFileIndex和localIdentifierInFile字段表示引用文件1中的第个对象,即全局游戏管理器文件中的第个MonoScript对象。通过对全局游戏管理器文件的分析,我们发现第个对象正是创建的脚本。
了解SerializedFile的结构后,接下来需要解决如何根据Editor中编辑的Prefab替换构建好的包内对应Prefab的二进制内容。Prefab文件在Editor中以文本格式存储,格式为Unity修改后的YAML格式。我们发现,YAML格式与SerializedFile相似,都将树形结构的源码分析与策略对象平铺化,并使用文件内的唯一索引进行引用。
然而,YAML中的信息与SerializedFile格式并非完全对应,比如自定义脚本的信息,YAML中使用脚本的guid,而SerializedFile中使用的是全局游戏管理器文件中的脚本对象索引。为了解决guid到全局游戏管理器文件中脚本对象的映射关系,我们采取了以下思路:通过类型信息作为关联键,建立guid与文件内对象索引的映射关系。首先,编写脚本从Editor中获取所有类型信息,建立guid到类型信息的映射。然后,解析全局游戏管理器文件获取类型信息到文件内索引的映射。这样一来,就可以将YAML中的脚本引用guid序列化为localFileID。
在替换构建好的包内Prefab的二进制内容时,头信息描述了每个对象数据的起始位置和大小。我们接下来关注对象是如何序列为二进制数据的。不同的对象类型具有不同的序列化格式,我们以GameObject类型为例进行介绍。
每个Prefab节点包含一个GameObject对象,Inspector面板显示的名字、Tag等信息来源于GameObject对象。GameObject的序列化格式相对简单。在从YAML到SerializedFile的对应关系中,我们看到一些Editor环境下使用的数据在构建中不需要序列化。在SerializedFile中,挂载的组件对象使用Component指针数组表示,包含PathID和FileID信息。PathID表示对象的索引,FileID为0表示是内部文件对象。
Transform对象也包含在每个节点中,其中包含Vector3和Quaternion数据类型,这些数据在YAML中以多维浮点数保存,在SerializedFile中同样以这种方式保存。
在介绍更多的Unity内置组件类型之前,我们先关注最常用的自定义组件类型,即MonoBehaviour类的子类。MonoBehaviour对象在YAML中结构清晰,我叫高达源码首先引用自定义脚本类文件,然后是所有可序列化字段的数据。在SerializedFile格式中,首先是指向自定义组件类的引用数据,接着是所有可序列化字段数据。组件类引用数据结构包括PathID和FileID。
在测试序列化简单字段时,我们发现序列化的字段都是4字节对齐的。要实现YAML中MonoBehaviour字段的序列化写入,我们采取了一种方法,即通过反射从Unity工程中找到对应的类型,然后使用Mono Cecil库静态分析Assembly-CSharp.dll以提取类型信息。有了类型信息后,我们就需要考虑如何序列化。
序列化过程有两种方向,其中一种需要了解Unity支持的字段序列化规则,筛选出类型的可序列化字段。然而,考虑到实现目标是脱离Unity工程的独立工具,我们选择另一种方案,即从构建好的包体中寻找类型信息。通过Il2CppDumper从globalmetadata中静态提取类型信息,我们查看Assembly-CSharp.dll以确认包含类型的字段信息。
在处理其他Native Component时,除了GameObject和Transform之外,Unity还提供了丰富的原生组件。一些常见组件的YAML和SerializedFile映射关系如下所示。对于其他几十种原生组件的映射关系,需要通过耐心测试来摸索清楚。
此外,Prefab可能引用贴图、字体、材质以及其他Prefab等外部依赖资源。构建包的测试表明,如果一个Prefab通过脚本引用了其他Prefab,如TestPrefab和TestPrefab,那么在构建的序列化文件中,头信息的externals会包含TestPrefab和TestPrefab的guid。序列化的脚本引用字段分别指向这两个资源。
对于引用的内置资源,如字体文件,构建包内的资源文件为unity default resources。序列化的脚本资源值为特定格式,如{ fileID:2, pathID:},对应的YAML引用信息为。
对于内置资源,其type为0,且fileID为序列化后的文件内对象索引。因此,需要解决guid到内置资源路径的映射问题。由于内置资源数量有限且固定,我们选择先人工维护映射关系。
在处理图集资源时,遇到困难,因为它没有将图集Prefab作为externals引用,而是引用了sharedassets0.assets文件。项目中存在大量sharedassetsXXX.assets文件,不知道如何从图集Prefab的guid关联到sharedassets0.assets文件。我们推测,Unity在构建过程中会擦除一些项目资源文件的guid信息,转而使用externals依赖形式。
至此,研究暂时陷入困境。我们希望后续能有其他方法解决这个问题。本文使用Zhihu On VSCode创作并发布。
IL2CPP简介以及打包分析
IL2CPP简介与打包分析
在Unity的未来发展中,IL2CPP扮演着关键角色。它是一种将C#编译后的Intermediate Language (IL)代码通过IL2CPP翻译器转换为C++源代码的过程。这种转换使得代码能够被不同平台的编译器编译,从而实现跨平台兼容性。 尽管C++本身强大,但在IL2CPP中,依然需要一个VM(虚拟机)的原因在于,它能够更好地管理和优化C#代码的执行效率。这使得游戏开发者能利用IL2CPP的优势,提高性能,尤其是在Windows打包中。 IL2CPP打包策略下,游戏中的自定义或第三方程序集会被整合到GameAssembly.dll中,这简化了游戏发布的流程。只需要少数关键文件,例如核心dll,而其他文件夹通常会被缓存检查。如果这些dll在后续打包中没有更新,整个过程将非常迅速,节省了时间和资源。 在打包过程中,有一个名为XXXXXXXXXX_BackUpThisFolder_ButDontShipItWithYourGame的文件夹,它包含了C#编译后的cpp源文件以及cpp编译后的dll。这些内容是IL2CPP编译生成的中间结果,对于调试和理解C#到C++的转换过程十分重要。 另一个名为XXXXXXXXXXXXX_BurstDebugInformation_DoNotShip的文件是Unity Burst编译器的详细编译信息,这部分内容对游戏性能优化有帮助,但对于常规发布并不需要包含在发布的包中。如何防止unity3d代码被反编译?
防止Unity3D代码被反编译是手游安全中常见的破解风险。Unity的破解风险主要体现在Unity mono脚本解密、Unity il2cpp脚本解析、Assetbundle资源篡改三项。mono脚本文件的二进制形式及源码转换图示,展示了如何对mono脚本进行解密。Il2cpp脚本解析则需要使用Il2CppDumper工具,解析后能获得类名、函数名以及对应偏移信息。尽管iOS中还无法解析为源码,但Android的有效脚本加密对于防止破解尤为重要。Assetbundle资源篡改,如修改材质属性,可实现透视效果,同时还有资源被竞品**、分析的风险。存档数据被修改也是安全问题,如果数据不进行服务端校验或为单机游戏,游戏属性修改风险巨大。保护Unity安全时,自研保护系统面临高成本、兼容性问题、对抗破解的持续升级和第三方服务兼容性挑战。网易云易盾提供了Unity mono DLL脚本加密、IL2CPP加密、Assetbundle加密等解决方案,通过修改或HOOK mono_image_open_from_data_with_name函数,实现对CSharp DLL脚本的加密,以防止其被解密。Unity mono DLL脚本加密经历了从直接文件加密到抹掉PE头、再到方法级加密的三代技术演进。IL2CPP加密则需结合global-metadata.dat文件内的符号信息进行解析,通过SO加壳保护libil2cpp.so来实现。Assetbundle加密后,Unity Studio无法解析资源。网易易盾保护方案特点包括纯Native保护、对引擎SO做加壳、兼容性和稳定性高、性能影响小,支持多平台加固。在选择保护方案时,应考虑DEX加壳的兼容性和安全性问题,而网易易盾提供的纯Native保护方案为手游提供了一种更加安全和兼容性强的解决方案。
怎么看unity.2在编辑器工作流上的改进?
Unity编辑器的最新动态带来了核心功能的优化,这些改进覆盖了从资源导入到游戏构建与部署的全过程,显著加快了开发流程的迭代速度。Unity编辑器在处理资源时,需要将原始文件转换为适用于游戏或实时应用的格式,并将这些转换后的文件与相关数据存储在Asset Database(资源数据库)中。数据库的刷新与脚本的重新加载影响了编辑器的迭代时间。在项目部署时,Unity的构建系统负责将项目打包成可在目标平台运行的二进制文件。
在Unity编辑器的性能优化中,Asset Database的核心技术得到了改进,通过优化代码和测试框架,成功减少了项目启动时间。通过并行处理资源导入和启用快速压缩选项,项目启动时间大大缩短。模型和纹理的导入速度显著提升,导入活动窗口的开发有助于直观显示资源导入原因、耗时和依赖资源。通过减少内存分配、实现并行处理和优化内存分配程序,模型导入速度得到了提升。纹理导入优化包括更新压缩程序和使用快速压缩选项,以减少导入时间并允许用户根据需求调整纹理质量。
对于大型、扁平层级的场景,Unity编辑器通过优化场景根目录的存储方式,将加载和合并场景的时间减少了%,从秒缩短到1.秒。编辑器内部的性能优化包括对大型场景对象拖拽与选取流程的优化、更快的新建材质、场景对象全选、复制/粘贴游戏对象操作,以及支持增量式版本构建和脚本编译。此外,全新的IL2CPP源码加密功能显著减少了构建耗时和可执行文件体积,提高了构建速度。这些改进和优化旨在加速游戏开发流程,提升编辑器的性能和效率。
Unity编辑器在.2版本中的改进和优化为开发者带来了显著的性能提升和便捷性增强,不仅加快了开发速度,还提高了资源管理和构建流程的效率。这些改进和优化不仅改善了编辑器的核心功能,也为大型项目的开发提供了更好的支持。随着Unity在构建流程和编辑器性能上的持续优化,开发者将能更高效地进行游戏开发工作,为用户提供更加丰富和流畅的游戏体验。
Unity将来时:IL2CPP怎么用?
版本准备
IL2CPP的引入为Unity游戏开发带来了诸多便利与挑战。本文通过实际例子,详细介绍了Unity3D中的IL2CPP如何应用于WebGL平台以及iOS 位版,解释了其为游戏一键部署至浏览器以及支持全新位CPU所做贡献。
IL2CPP的两个主要应用领域包括WebGL与iOS 位版。在Unity5.0 Beta版中提供了WebGL测试支持,而iOS 位版则需使用Unity 4.6.1 p5、4.6.2与4.6.2 p1版本。通过创建项目并加入两个cs文件,我们得以深入探索IL2CPP的应用。
通过IL2CPPCompatible.cs与IL2CPPStudy.cs文件,我们能够测试代码在IL2CPP中的兼容性并生成C++代码,用于对比分析。具体文件内容涉及线程与SSL认证函数的测试,以及CoconutClassStudy类中的构造函数、Add函数与IOTest函数。
在生成XCode项目后,我们能够观察到IL2CPP转换出的文件,并分析其在CPP文件中的实现方式。如类的表达、IO操作、new关键字的使用、线程创建以及cc.GetType()行为的翻译。这些实现方式为理解IL2CPP转换提供了宝贵洞见。
在分析过程中,我们发现IL2CPP将C#类转换为Struct,并将类函数转换为全局函数。此外,new关键字的实现展示了IL2CPP在堆上分配内存的机制。线程创建与Type的转换同样提供了对IL2CPP实现的深入理解。
值得注意的是,IL2CPP转换带来了速度提升、内存占用减少等优势,同时提供了C++源码级调试选项。然而,转换过程也引入了额外的编译时间、可能存在的Bug以及动态代码支持的限制。面对这些问题,开发者应提前准备并进行兼容性测试,以确保项目顺利过渡。
总的来说,IL2CPP是Unity进化的关键一步,旨在提升性能与支持新平台。面对其挑战,开发者应积极适应并利用其优势,以确保项目成功过渡至新编译方式。通过实践与学习,开发者能够充分利用IL2CPP带来的改进,为游戏开发注入更多活力。