2.4 本机到托管的桥接

1.本机到托管的桥接简介

2.桥接的性能影响

3.减轻桥接性能影响的优化策略

4.桥接代码的判断


1.本机到托管的桥接

1).本机到托管的桥接简介

本机到托管的桥接表示"unity引擎底层代码(通常是c/c++)与托管代码(c#)之间的交互机制"

a.本地代码(Native Code)

- 主要是用c++编写的

- 包括unity引擎的核心部分: 渲染引擎, 物理引擎, 音频系统等

- 直接编译成机器码, 运行效率高

- 与操作系统和硬件直接交互

b.托管代码(Managed Code)

- 主要是开发者编写的c#脚本

- Unity IL2CPP模式下的C# 运行在 .net虚拟机(mono或il2cpp)

- 有垃圾回收, 内存自动管理等特性
本机代码和托管代码

a.本机代码(Native)

- 本质特性: 编译为目标平台原生机器码(无托管依赖)

- 常见载体: Unity引擎核心(C/C++)、原生插件(C/C++)、平台SDK(iOS/Android 原生代码)

- 执行环境: 直接运行在操作系统上

b.托管代码(Managed)

- 本质特性: 非直接机器码, 依赖托管运行时解释/编译

- 常见载体: Unity开发者编写的C#代码、Unity C# API

- 执行环境: 运行在 Mono虚拟机或IL2CPP托管运行时上, 有自动 GC、类型安全校验			

在这里插入图片描述


2).为什么需要桥接

在这里插入图片描述

当执行CreatePrimitive时:

a.c#层: 接收你的调用

b.桥接层: 将调用和参数转换成c++能理解的形式

c.c++: 实际执行创建网格, 设置材质, 配置渲染等复杂操作

d.桥接层: 将结果返回给c#

e.c#层: 你得到一个可以操作的GameObject引用

没有这个桥接, 你的c#代码就无法驱动底层的c++引擎

3).桥接的具体实现方式

a.Mono运行时

在这里插入图片描述

b.IL2CPP

- 将C# IL代码转换为C++代码

- 生成更直接的桥接代码

2.桥接的性能影响

Unity 本机 - 托管桥接存在不可避免的性能开销, 但单次开销通常较小(纳秒 / 微秒级), 高频调用会导致开销累积, 成为

性能瓶颈; 同时, 开销大小与数据类型、调用方式强相关; 用一个例子来说明两个不同公司的团队协作, 难免有额外开销,这

些开销就是桥接对性能的损耗, 具体分3:
1).影响最大: 数据交接的"格式转换 + 复印"成本(对应: "数据封送开销")

A公司和B公司的文件格式不一样(比如A用Excel统计数据, B只认Word表格; A用中文标注, B只认英文), 要传递数据, 必须

做两件事, 这两件事都费时间:

a.格式转换: 把A的Excel转成B能看懂的Word, 把中文翻译成英文

对应: 托管代码和原生代码的数据类型/编码/内存布局不一致, 需要转换, 比如C# string(UTF-16)转C++ char*(UTF-8)

b.复印拷贝: A不能把自己的原件直接给B(怕B弄丢/改乱, 影响自己后续使用), 只能复印一份给B

对应: 托管数据不能直接给原生代码操作, 怕被破坏, 只能拷贝一份原生代码能识别的纯数据

这个"转换 + 拷贝"的时间, 就是最大的性能开销:

小数据(比如一张写着"数字5"的小纸条): 转换 + 复印几乎不费时间, 影响可以忽略

大数据(比如一本1000页的客户档案、一个装满数据的大文件夹): 转换要半天, 复印要几小时, 耗时巨大

-> 对应: 大数组、长字符串传递, 拷贝/转换开销会成为性能瓶颈

复杂数据(比如带附件、带批注的复杂报告): 转换起来更麻烦, 还容易出错, 耗时更久

-> 对应: 自定义复杂类/对象传递, 封送开销极高
2).高频累积: 来回沟通的"跑腿"成本(对应: "上下文切换开销")

A公司员工要找B公司员工办事, 不能直接隔空传话, 必须走流程:

a.放下自己手里的活记好自己做到哪一步了(比如"我刚整理完第3页档案", 对应: 保存当前代码的执行状态)

跑到B公司(对应: 切换到原生代码执行环境)

b.办完事, 再跑回A公司, 回忆自己之前做到哪了, 继续干活(对应: 恢复托管代码的执行状态)

单次跑腿的时间很短(比如: 1分钟)但架不住次数多

- 一天跑1: 几乎不影响工作(对应: 低频桥接调用, 比如游戏启动时调用1次原生插件初始化)

- 一天跑1000: 光跑腿就花了1000分钟, 根本没时间干正事

对应: Update/FixedUpdate每帧调用上千次桥接函数, 跑腿成本累积, 导致帧率下降、程序卡顿

3).额外隐患: 协作产生的"垃圾没人清" (对应: GC压力 + 内存泄漏)

A和B协作时, 会产生一些临时垃圾

a.临时复印纸: 交接数据时, 打印的临时拷贝(对应: 桥接时创建的临时托管对象, 比如数组副本、字符串包装器)堆在办公

室没人清, 越堆越多, 最后需要花时间集中打扫(对应: GC回收, 打扫时所有人都要停工, 就是GC卡顿)

b.废弃文件没扔: 有些复印纸/文件用完后, 随手扔在走廊里

-> 对应: 手动分配的原生内存没释放, 比如Marshal.AllocHGlobal分配的内存没Free

越积越多, 最后走廊都堵死了

-> 对应: 内存泄漏, 程序占用内存越来越高, 最终崩溃

3.减轻桥接性能影响的优化策略

1).减少跨边界调用次数(核心优化)

批量处理数据:"高频单次调用"改为"低频批量调用", 比如每帧不是调用1000次获取单个数据, 而是1次调用获取1000条批

量数据, 大幅减少上下文切换次数

避免热路径调用: 不在Update、FixedUpdate、LateUpdate等每帧执行的热路径中进行桥接调用; 若必须调用,尽量降低调用

频率(如每10帧调用1)

在这里插入图片描述

2).优化数据封送(降低核心开销)

a.优先使用Blittable类型: 尽量用intfloatbyte、 blittable结构体(仅包含 Blittable 类型的结构体)作为参数/返

回值, 避免非Blittable类型和引用类型

b.手动控制内存, 避免拷贝

使用fixed关键字固定托管数组内存, 直接传递指针给本机代码(无需拷贝数组)

c.复用非托管内存缓冲区: 提前分配固定大小的本机内存, 重复使用, 避免频繁申请/释放

d.避免字符串传递: 尽量用byte[](UTF-8)代替string传递文本数据, 减少编码转换和内存拷贝开销
3).减少GC压力与内存泄漏

a.手动释放非托管内存: 使用Marshal.AllocHGlobal分配的内存, 必须用Marshal.FreeHGlobal释放; 原生插件分配的内存

需提供释放接口并在C#中调用

b.避免临时对象创建: 复用托管对象/缓冲区, 减少桥接过程中临时对象的生成, 降低GC触发频率

4.桥接代码的判断

1).很多Unity公开的C#API, 底层其实是C++引擎核心实现的, C#调用这些API时, 会隐式触发桥接
using UnityEngine;

public class ImplicitBridgeTest : MonoBehaviour
{
    void Update()
    {
        // 示例1:修改Transform组件属性(隐式桥接)
        // C#的transform.position是托管封装,底层是Unity C++引擎的Transform模块
        // 调用时触发:C#托管代码 → Unity C++引擎核心(桥接)
        transform.position += new Vector3(0, 0.1f, 0);

        // 示例2:加载AssetBundle资源(隐式桥接)
        // AssetBundle加载逻辑底层是C++实现,C# API只是托管封装
        if (Input.GetKeyDown(KeyCode.Space))
        {
            AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/test.ab");
            GameObject prefab = ab.LoadAsset<GameObject>("TestObj");
            Instantiate(prefab);
            ab.Unload(false);
        }

        // 示例3:渲染相关API(隐式桥接)
        // Renderer、Material等API底层是C++渲染引擎(URP/HDRP/内置渲染管线)
        GetComponent<Renderer>().material.color = Color.red;
    }
}

2).在iOS/Android移动端开发中, Unity常需要与平台原生代码交互(如获取设备信息、调用原生支付 / 分享), 这种交互必

然触发桥接

a.iOS原生代码是Objective-C(基于C/C++), Unity通过UnitySendMessage或自定义桥接接口交互

b.Android原生代码是Java, 底层通过JNI(Java Native Interface)与C/C++交互, Unity与Android原生交互时, 会触发多

层桥接(C# → Java → C++)
源码来自:https://pan.quark.cn/s/a3a3fbe70177 AppBrowser(Application属性查看器,不需要越狱! ! ! ) 不需要越狱,调用私有方法 --- 获取完整的已安装应用列表、打开和删除应用操作、应用运行时相关信息的查看。 支持iOS10.X 注意 目前AppBrowser不支持iOS11应用查看, 由于iOS11目前还处在Beta版, 系统API还没有稳定下来。 等到Private Header更新了iOS11版本,我也会进行更新。 功能 [x] 已安装的应用列表 [x] 应用的详情界面 (打开应用,删除应用,应用的相关信息展示) [x] 应用运行时信息展示(LSApplicationProxy) [ ] 定制喜欢的字段,展示在应用详情界面 介绍 所有已安装应用列表(应用icon+应用名) 为了提供思路,这里只用伪代码,具体的私有代码调用请查看: 获取应用实例: 获取应用名和应用的icon: 应用列表界面展示: 应用列表 应用运行时详情 打开应用: 卸载应用: 获取info.plist文件: 应用运行时详情界面展示: 应用运行时详情 右上角,从左往右第一个按钮用来打开应用;第二个按钮用来卸载这个应用 INFO按钮用来解析并显示出对应的LSApplicationProxy类 树形展示LSApplicationProxy类 通过算法,将LSApplicationProxy类,转换成了字典。 转换规则是:属性名为key,属性值为value,如果value是一个可解析的类(除了NSString,NSNumber...等等)或者是个数组或字典,则继续递归解析。 并且会找到superClass的属性并解析,superClass如...
基于遗传算法辅助异构改进的动态多群粒子群优化算法(GA-HIDMSPSO)的LSTM分类预测研究(Matlab代码实现)内容概要:本文研究了一种基于遗传算法辅助异构改进的动态多群粒子群优化算法(GA-HIDMSPSO),并将其应用于LSTM神经网络的分类预测中,通过Matlab代码实现。该方法结合遗传算法的全局搜索能力与改进的多群粒子群算法的局部优化特性,提升LSTM模型在分类任务中的性能表现,尤其适用于复杂非线性系统的预测问题。文中详细阐述了算法的设计思路、优化机制及在LSTM参数优化中的具体应用,并提供了可复现的Matlab代码,属于SCI级别研究成果的复现与拓展。; 适合人群:具备一定机器学习和优化算法基础,熟悉Matlab编程,从事智能算法、时间序列预测或分类模型研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①提升LSTM在分类任务中的准确性与收敛速度;②研究混合智能优化算法(如GA与PSO结合)在神经网络超参数优化中的应用;③实现高精度分类预测模型,适用于电力系统故障诊断、电池健康状态识别等领域; 阅读建议:建议读者结合Matlab代码逐步调试运行,理解GA-HIDMSPSO算法的实现细节,重点关注种群划分、异构策略设计及与LSTM的集成方式,同时可扩展至其他深度学习模型的参数优化任务中进行对比实验。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值