基于AOP思想的音频注入解耦方案及其使用C#反射技术的实现

需求产生:

团队开发过程中,需要给预制节点绑定音效,但音效团队和开发团队之间的沟通协作存在延迟,很容易导致多方编辑同一个预制节点从而产生冲突。因此需要设计并实现一个让音频数据从预制体中独立出来的方案,使得两方工作不会相互干扰。

设计思路:

使用额外的文件专门存储音频配置,并与预制节点一一对应;运行时读取音频配置,给配置中列出的节点挂载音频控制组件,触发对应的操作后,根据组件保存的内容播放相应的音频。由于GameObject.Instantiate拷贝节点时,会同样拷贝其挂载的组件,所以不用担心运行过程中新拷贝的节点丢失音频的问题。

实现:

分为音频编辑器和运行时读取两个部分:

音频编辑器:本文使用Lua脚本作为音频配置文件,通过配置名称与预制节点同名来进行映射(人为规定不要对不同预制体使用相同名称);将操作事件【单击、拖拽、勾选等】对应的脚本名称与音频名称作为LuaTable的k,v值存储在LuaTable中,作为事件列表;将根节点到需要绑定事件的节点路径上的全称【方便调用Find方法】和事件列表打包,以序号为k值保存到LuaTable,最后加上return,确保在require时直接返回该节点的配置。

运行时读取:根据预制体的名称,从指定路径下读取同名lua配置文件,遍历获取到的LuaTable,使用Find查找到绑定了事件的节点,遍历该节点的操作事件列表,K值即需要绑定的控件名称,V值传入该控件作为对应的音频。控件在对应操作事件触发的回调内,添加播放当前控件保存的音频的代码。

具体实现中的技术点:

1.通过反射获取到项目支持的所有操作控件名称

首先,将所有操作控件放到同一个命名空间下,此处为namespace Extension.TouchEvent

以下代码从运行的程序域中查找所有处于指定namespace下的类型,并返回其Type对象

var ass = (
    from assembly in AppDomain.CurrentDomain.GetAssemblies () 
    where!(assembly.ManifestModule is System.Reflection.Emit.ModuleBuilder) 
    from type in assembly.GetExportedTypes () 
    where type.Namespace != null && type.Namespace.CompareTo ("Extension.TouchEvent") == 0     
    select type
);

随后遍历ass,读取每个Type的name即可。【获取名称接口详见:C# Type类型参考手册

2.在自定义程序集中通过反射执行默认程序集Assembly-CSharp中的某个函数

需要注意的是,自定义程序集无法直接访问默认程序集,会报找不到的错误,此外,也无法直接通过在Unity中修改当前程序集的Assembly Definition Referances的办法增加对默认程序集的支持(因为不支持默认程序集的添加)

仍然是通过反射的办法,从当前运行的程序域内找到默认程序集Assembly-CSharp,然后在该程序集下拿到函数所在的类。

foreach (var asm in AppDomain.CurrentDomain.GetAssemblies ()) {
    if (asm.GetName ().Name == "Assembly-CSharp") {
        foreach (var type in asm.ExportedTypes) {
            if (type.Name.CompareTo ("xxx_my_class") == 0) {
                return type;
            }
        }
    }
}

上文提到了Type的参考手册,其中有一个GetMethod的方法可以通过字符串的方法名称获取对应的方法xxFunction,然后调用xxFunction.Invoke(params),传入该方法所需的参数params,即可执行该方法。

本文通过此方法获取默认程序集中的音频管理类,并调用其音频播放代码播放播放音频。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值