插件打包错误ue_UE集成WWise:概念与代码分析

本文深入探讨了如何解决在UE4中集成WWise时遇到的插件打包错误,详细分析了WWise资源、与UE4的交互方式,包括PlaySoundAtLocation、PostEvent等功能,并介绍了Bank生成的代码细节。此外,还讨论了远程构建iOS的解决方案和WWise在UE4中的局限性。
摘要由CSDN通过智能技术生成

本篇文章搬运自我自己的博客,原文链接: UE集成WWise:概念与代码分析 作者: ZhaLiPeng

WWise是Audiokinetic的跨平台音频引擎,可以与游戏引擎很好地进行交互,负责音频的同事可以只在WWise中处理音频,把游戏业务和音频的制作与管理分离,提供事件和参数给游戏引擎使用,实现与业务的解耦和对音频更精确的控制。 本篇文章主要介绍WWise与UE4的集成、远程构建、资源分析、文档收录,WWise与UE的控制交互以及Bank生成的代码分析。

集成至UE4

WWise是全平台支持的,对Linux/Lumin/PS4/Switch/XboxOne/Windows/Android/iOS/Mac都支持。 但是多数游戏不需要支持这么多平台,WWise链接库很大,所以我在官方版本支持的多平台基础上做了裁剪,去掉了以下平台的支持:

  • Linux
  • Lumin
  • PS4
  • Switch
  • XboxOne

对Android和Windows平台做了以下裁剪:

  • 移除arm64-v8a和android_x86/x86_64的链接库支持
  • 移除Win32的所有链接库/移除vc140/vc150的支持

对iOS做了以下裁剪:

  • 移除所有的iphonesimulator,节省空间2.31G

对Mac的支持:

目前的项目是不需要支持Mac的(使用iOS远程出包),但是为了避免想要在Mac上跑工程编译不过的问题,保留了Mac链接库和模块支持,保留它不会对Android/iOS的打包有任何影响。

链接库

我在裁剪版本中支持以下平台:

  • Android_armabi_v7a
  • iOS
  • Mac
  • Win vc160

每个平台均支持Debug/Profile/Release的支持,分别对应UE的Debug/Development/Shipping的Configuration配置。

在打包Android Development的配置下,包含WWise的链接库,APK增大约30M.

WWise版本的问题

Wwise版本为Wwise 2019.1.9.7221

AkAudio_Android.build.cs中对Android的的链接库支持在UE_4_25_OR_LATER下路径错误。

原始路径:

Path.Combine(ThirdPartyFolder, "Android", "armeabi-v7a", akConfigurationDir, "lib")

实际的路径:

Path.Combine(ThirdPartyFolder, "Android_armeabi-v7a", akConfigurationDir, "lib")

远程构建iOS

在我之前的笔记中写到过,远程构建iOS实际就是要把文件上传的Mac上执行编译,但是这就有一个问题,如果需要参与编译的文件没有被上传到Mac上,就会出现错误,很不巧在WWise中就会出现这个问题,解决的办法自然是要把编译WWise依赖的文件给上传到Mac上。

因为UE使用RSync来同步构建机和本地的文件传输,在我之前的文章UE4开发笔记:Mac/iOS篇#配置远程构建有讲到,可以创建<ProjectDir>/Build/Rsync/RsyncProject.txt文件,来写入RSync的文件同步规则,把需要的文件上传到Mac中。

WWise需要的规则如下:

+ /Plugins/Wwise/ThirdParty/include/**
+ /Plugins/Wwise/ThirdParty/iOS/**

其实就是指定WWise的链接库和Include目录全上传到Mac上。

WWise资源

WWise在UE中有两种资源格式,一种是UAkAudioEvent用来执行WWise中指定的Event,还有一种是UAkAudioBank,用来记录Bank中包含哪些Event,用在生成时标记把属于相同Bank的Event打包到一起。

UAkAudioEvent

  • AudioEvent

UAkAudioEvent:主要作用是指定当前Event的Bank,它唯一的函数就是LoadBank来加载当前Event所指定的Bank(看到有用到的地方就是获取它的名字),WWise集成到UE的插件也是通过拿到UAkAudioEvent对象的名字来与UAkAudioBank做绑定之后去WWise端生成bnk等文件的,这也是要求UE中资源的命名要和WWise中Event的命名完全一致的原因。

UCLASS(meta=(BlueprintSpawnableComponent))
class AKAUDIO_API UAkAudioEvent : public UObject
{
    
    GENERATED_UCLASS_BODY()

public:
    /** Bank to which this event should be added. */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Bank")
    class UAkAudioBank * RequiredBank;

    /** Maximum attenuation radius for this event */
    UPROPERTY(BlueprintReadOnly, Category="AkAudioEvent")
    float MaxAttenuationRadius;

    /** Whether this event is infinite (looping) or finite (duration parameters are valid) */
    UPROPERTY(BlueprintReadOnly, Category = "AkAudioEvent")
    bool IsInfinite;

    /** Minimum duration */
    UPROPERTY(BlueprintReadOnly, Category = "AkAudioEvent")
    float MinimumDuration;

    /** Maximum duration */
    UPROPERTY(BlueprintReadOnly, Category = "AkAudioEvent")
    float MaximumDuration;

#if CPP
    /**
     * Load the required bank.
     *
     * @return true if the bank was loaded, otherwise false
     */
    bool LoadBank();
#endif

};

通过获取Event的名字再传递给更深层次的PostEvent:

int32 UAkGameplayStatics::PostEvent(
      class UAkAudioEvent* AkEvent
    , class AActor* Actor
    , int32 CallbackMask
    , const FOnAkPostEventCallback& PostEventCallback
    , const TArray<FAkExternalSourceInfo>& ExternalSources
    , bool bStopWhenAttachedToDestroyed
    , FString EventName
)
{
    
    if (AkEvent == NULL && EventName.IsEmpty())
    {
    
        UE_LOG(LogScript, Warning, TEXT("UAkGameplayStatics::PostEvent: No Event specified!"));
        return AK_INVALID_PLAYING_ID;
    }

    if (Actor == NULL)
    {
    
        UE_LOG(LogScript, Warning, TEXT("UAkGameplayStatics::PostEvent: NULL Actor specified!"));
        return AK_INVALID_PLAYING_ID;
    }

    AkDeviceAndWorld DeviceAndWorld(Actor);
    if (DeviceAndWorld.IsValid())
    {
    
        AkCallbackType AkCallbackMask = AkCallbackTypeHelpers::GetCallbackMaskFromBlueprintMask(CallbackMask);
        if (ExternalSources.Num() > 0)
        {
    
            FAkSDKExtrernalSourceArray SDKExternalSrcInfo(ExternalSources);
            return DeviceAndWorld.AkAudioDevice->PostEvent(GET_AK_EVENT_NAME(AkEvent, EventName), Actor, PostEventCallback, AkCallbackMask, false, SDKExternalSrcInfo.ExternalSourceArray);
        }
        else
        {
    
            return DeviceAndWorld.AkAudioDevice->PostEvent(GET_AK_EVENT_NAME(AkEvent, EventName), Actor, PostEventCallback, AkCallbackMask);
        }
    }

    return AK_INVALID_PLAYING_ID;
}

UAkAudioBank

UAkAudioBank的作用是用来调用AkAudioDevice来加载Bank,如果在UE中开启了AutoLoad,则在UObejct的PostLoad中就会去执行加载。

官方的对于Sound

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值