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(反向動力學)

相關文章
相關標籤/搜索