iT邦幫忙

2025 iThome 鐵人賽

DAY 10
0

昨天修改完近戰功能後就可以加入聯擊功能了!
我這裡使用 UE5.6 模板的 AM_ComboAttack 來製作,裡面使用 Sections 來分開三個不同的攻擊動畫。也是我第一次用這種方式來做 Combo,不然之前都是直接拿三個動畫檔案做 Combo,比較浪費儲存資源。

1. 程式碼

iThome30daysCharacter.h

用到的函式:

protected:
    virtual void BeginPlay() override;
    void AttackMontageEnded(UAnimMontage* Montage, bool bInterrupted);
	FOnMontageEnded OnAttackMontageEnded;
    UFUNCTION()
	void OnAttackNotifyBegin(FName NotifyName, const FBranchingPointNotifyPayload& BranchingPointPayload);

public:
    UFUNCTION(BlueprintCallable, Category="Input")
	virtual void DoAttack(UAnimMontage* AnimMontage, FName ComboNotify);

變數:

public:
    UPROPERTY(Category="Character: State", EditAnywhere, BlueprintReadWrite)
	bool bIsAttacking;
	
	bool bCanQueCombo=false;

	FName NComboCheckNotify=FName("ComboCheck");
	
	UPROPERTY(Category="Character: Attack", VisibleAnywhere, BlueprintReadOnly)
	int ComboCount=0;
	
	UPROPERTY(Category="Character: Attack", EditAnywhere)
	UAnimMontage* AttackAnimMontage;

	TArray<FName> AttackSectionNames;

iThome30daysCharacter.cpp

設定初始功能:

AiThome30daysCharacter::AiThome30daysCharacter()
{
    OnAttackMontageEnded.BindUObject(this, &AiThome30daysCharacter::AttackMontageEnded);
}
void AiThome30daysCharacter::BeginPlay()
{
	Super::BeginPlay();

	if (UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance())
	{
		AnimInstance->OnPlayMontageNotifyBegin.AddDynamic(this, &AiThome30daysCharacter::OnAttackNotifyBegin);
	}
}

攻擊 (按下按鍵):

void AiThome30daysCharacter::DoAttack(UAnimMontage* AnimMontage, FName ComboNotify)
{
    // 第一次攻擊 
	if (!bIsAttacking)
	{
		NComboCheckNotify = ComboNotify;
		AttackSectionNames.Empty();
		for (int i=0; i<AnimMontage->GetNumSections(); i++)
		{
            // 新增 Section 的名字 到 AttackSectionNames
			AttackSectionNames.Add(AnimMontage->GetSectionName(i));
		}
		bIsAttacking = true;
		bCanQueCombo = false;
		ComboCount = 0;
		if (UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance())
		{
            // 播放 Montage
			AnimInstance->Montage_Play(AnimMontage);
            // 設定 Montage 結束後呼叫的功能
			AnimInstance->Montage_SetEndDelegate(OnAttackMontageEnded, AnimMontage);
		}
	}
	
	if (bCanQueCombo)
	{
		++ComboCount;
		if (ComboCount < AttackSectionNames.Num())
		{
			bCanQueCombo = false; // 防止亂切
			if (UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance())
			{
				//GEngine->AddOnScreenDebugMessage(FCString::Atoi(TEXT("combo")), 2, FColor::Green, AttackSectionNames[ComboCount].ToString());
				AnimInstance->Montage_JumpToSection(AttackSectionNames[ComboCount], AnimMontage);
			}
		}
	}
	
	
}

當 Combo Notify 開始:

void AiThome30daysCharacter::OnAttackNotifyBegin(FName NotifyName, const FBranchingPointNotifyPayload& BranchingPointPayload)
{
	if (NotifyName == NComboCheckNotify)
	{
		bCanQueCombo = true;
	}
}

當 攻擊 Montage 結束:

void AiThome30daysCharacter::AttackMontageEnded(UAnimMontage* Montage, bool bInterrupted)
{	
	bIsAttacking = false;
	bCanQueCombo = false;
	ComboCount = 0;
	//GEngine->AddOnScreenDebugMessage(FCString::Atoi(TEXT("attak11")), 1.0f, FColor::Yellow, TEXT("ComboEnded"));
}

2.Blueprint 及 動畫設定

Blueprint:

https://ithelp.ithome.com.tw/upload/images/20250924/20171036vDSk7ihVPp.png

AM_ComboAttack Notify 設定:

Notifies 點 Add Track,然後在 右邊 Track > 右鍵 > Add Notify > Montage Notify
接著選擇 Notify 後 在 右方 Detail 介面寫上 Notify name
https://ithelp.ithome.com.tw/upload/images/20250924/20171036wKdd54o7If.png
https://ithelp.ithome.com.tw/upload/images/20250924/20171036o8ODUzGRww.png

完成 !


到這裡就完成了!
可以進行 Combo 囉,但你會看到 Combo 之間是一瞬間變換的,如果是風格化的遊戲可能還行,但其他的就看起來怪怪的,下次再來看能不能修正這個問題。


上一篇
# Day 9|修復近戰功能 (邏輯+動畫)
下一篇
# Day 11|為攻擊增加判定
系列文
30 天用 Unreal Engine 5 C++ 開發遊戲15
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言