ue4音效、动画结合实例

在游戏中,许多音效须要在动画恰当的时机出现,例如行走、奔跑,就须要刚好在足部落地瞬间播放。数组

而AnimNotify就能很是方便地处理此类问题。并发

AnimNotify,顾名思义就是动画通知,能在特定的动画片断播放到特定进度时“发出消息”。socket

目前咱们的工程有前、后、左、右、左前、右前、左后、右后八向的跑动动画。ide

先以向前跑为例,用右键添加通知的方式,分别在右脚、左脚落地时添加了lfoot_touchground与rfoot_touchground的两个自定义通知函数

固然直接添加playsound通知也是能够的,能很方便地直接设置声音,但为了功能的可扩展性咱们仍是使用自定义通知。动画

然而咱们如何才能获取这些通知呢?this

if (mesh) {
        UAnimInstance* anim=mesh->GetAnimInstance();
        if (anim) {
            TArray<const struct FAnimNotifyEvent*> AnimNotifies=anim->NotifyQueue.AnimNotifies;
            range(i,0,AnimNotifies.Num()) {
                FString NotifyName=AnimNotifies[i]->NotifyName.ToString();
                /*GEngine->A/ddOnScreenDebugMessage
                (-1, 5.f, FColor::Red, FString::FromInt(i)+" "+ NotifyName);*/
                if (NotifyName=="lfoot_touchground") {
                    audio_lfoot->SetSound(sb_walks[0]);
                    audio_lfoot->Play();
                }
                else if (NotifyName == "rfoot_touchground") {
                    audio_rfoot->SetSound(sb_walks[1]);
                    audio_rfoot->Play();
                }
                else {

                }
            }
        }
    }

 

没错,就是这么简单anim->NotifyQueue即为动画通知队列,AnimNotifies就能获取当前全部通知事件,上述代码去掉注释便可打印当前帧全部动画通知名称。spa

为了实现播放音效,咱们还须要绑定在左右脚的AudioComponent,若是当前通知队列中有对应的通知,就先SetSound设置将要播放的声音资源后再Play。code

我把全部须要绑定在Chracter的Mesh上的AudioComponent“打包装入“了一个叫AudioController的类,在Character的构造函数中进行了AudioController的构造,并将AudioController中的各音效组件绑定到对应的socket上。component

 

AudioController.h文件

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "Components/ActorComponent.h"
#include "Components/AudioComponent.h"
#include "Components/SkeletalMeshComponent.h"
#include "AudioController.generated.h"


UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class MYSOUNDANDEFFECTS_API UAudioController : public UActorComponent
{
    GENERATED_BODY()

public:    
    // Sets default values for this component's properties
    UAudioController();
    //UAudioController(USkeletalMeshComponent* mesh_);

protected:
    // Called when the game starts
    virtual void BeginPlay() override;

public:    
    // Called every frame
    virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;

    UPROPERTY(Category = Audio, VisibleDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
        UAudioComponent* audio_lfoot = NULL;
    UPROPERTY(Category = Audio, EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
        FString bonename_lfoot = "Bip01-L-Foot";

    UPROPERTY(Category = Audio, VisibleDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
        UAudioComponent* audio_rfoot = NULL;
    UPROPERTY(Category = Audio, EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
        FString bonename_rfoot = "Bip01-R-Foot";

    USkeletalMeshComponent* mesh = NULL;

    void my_init(USkeletalMeshComponent* mesh_);

    UPROPERTY(Category = Audio, EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
        TArray<class USoundBase*> sb_walks;
    
    
};

AudioController.cpp文件

// Fill out your copyright notice in the Description page of Project Settings.

#include "MySoundAndEffects.h"
#include "Animation/AnimInstance.h"
#include "AudioController.h"


// Sets default values for this component's properties
UAudioController::UAudioController()
{
    // Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
    // off to improve performance if you don't need them.
    PrimaryComponentTick.bCanEverTick = true;
    // ...
    audio_lfoot = CreateDefaultSubobject<UAudioComponent>("audio_lfoot");
    audio_rfoot = CreateDefaultSubobject<UAudioComponent>("audio_rfoot");

}

//UAudioController::UAudioController(USkeletalMeshComponent* mesh_)
//{
//    // Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
//    // off to improve performance if you don't need them.
//    PrimaryComponentTick.bCanEverTick = true;
//
//    // ...
//    
//
//    
//}


void UAudioController::my_init(USkeletalMeshComponent* mesh_) {
    this->mesh = mesh_;
    //UAudioController();
    audio_lfoot->SetupAttachment(mesh_, FName(*bonename_lfoot));
    audio_rfoot->SetupAttachment(mesh_, FName(*bonename_rfoot));
}


// Called when the game starts
void UAudioController::BeginPlay()
{
    Super::BeginPlay();

    // ...
    
}


// Called every frame
void UAudioController::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
    Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

    // ...
    if (mesh) {
        UAnimInstance* anim=mesh->GetAnimInstance();
        if (anim) {
            TArray<const struct FAnimNotifyEvent*> AnimNotifies=anim->NotifyQueue.AnimNotifies;
            range(i,0,AnimNotifies.Num()) {
                FString NotifyName=AnimNotifies[i]->NotifyName.ToString();
                /*GEngine->A/ddOnScreenDebugMessage
                (-1, 5.f, FColor::Red, FString::FromInt(i)+" "+ NotifyName);*/
                if (NotifyName=="lfoot_touchground") {
                    audio_lfoot->SetSound(sb_walks[0]);
                    audio_lfoot->Play();
                }
                else if (NotifyName == "rfoot_touchground") {
                    audio_rfoot->SetSound(sb_walks[1]);
                    audio_rfoot->Play();
                }
                else {

                }
            }
        }
    }
    else {
        throw std::exception("mesh not exist!!");
    }

}

 

还有character类中audiocontroller的定义和建立:

AAimPraticeHuman::AAimPraticeHuman()
{
#ifdef AudioController_h
	audiocontroller = CreateDefaultSubobject<UAudioController>("audiocontroller");
	audiocontroller->my_init(GetMesh());
#endif
}

 

UPROPERTY(Category = Audio, VisibleDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
  class UAudioController* audiocontroller = NULL;

 

最后就是音效导入,看似简单其实有不少细节。

建议直接拖入wav格式文件,若是导入失败应该是wav文件具体参数的问题。

(我用Audition把一长串的跑步音效分割出了两声脚碰地的声音,直接导入ue4报错,然而先用格式工厂转一下就ok了)

 

固然如今的音效还不能直接用于游戏脚步,还须要先设置并发和立体效果。

Concurrency项勾选override便可,使用”先远后旧“的并发中止策略问题也不大。

Attenuation项我新建了一个叫SceneSoundAttenuation蓝图,设置以下:

这些选项看字面都比较好理解,3D Stereo Spread的意思其实就是左右耳间距。

 

最后别忘了设置character蓝图的sb_walks数组的值,以及左右脚的socketname

 

 

大功告成啦!

具体效果。。。反正大家也听不到。。。

 

------------------------------------------------

下期预告:美妙的IK(反向动力学)

相关文章
相关标签/搜索