iT邦幫忙

2025 iThome 鐵人賽

DAY 11
0

今天要做的是,在執行攻擊動畫時,增加傷害判定 (Collision)。

1. 前置準備

  • 新增 Animation 資料夾 (或你習慣的整理方式)
  • 新增 iThomeAnimNotifyState_DoAttackTrace.h.cpp

Notify 跟 NotifyState 差在前者只能判斷進入notify 的時候,後者可以判斷 開始 過程 結束

  • iThomeAnimNotifyState_DoAttackTrace.h
#pragma once

#include "CoreMinimal.h"
#include "Animation/AnimNotifies/AnimNotifyState.h"
#include "iThomeAnimNotifyState_DoAttackTrace.generated.h"

UCLASS()
class UiThomeAnimNotifyState_DoAttackTrace : public UAnimNotifyState
{
	GENERATED_BODY()
	
protected:

	// Trace 開頭 - 骨頭/Socket 名稱
	UPROPERTY(EditAnywhere, Category="Attack")
	FName TraceSocketStart;
	// Trace 結尾 - 骨頭/Socket 名稱
	UPROPERTY(EditAnywhere, Category="Attack")
	FName TraceSocketEnd;
    // Trace 半徑
	UPROPERTY(EditAnywhere, Category="Attack")
	float Radius=20.0f;
    // Trace 類別
	UPROPERTY(EditAnywhere, Category="Attack")
	TArray<TEnumAsByte<EObjectTypeQuery>> CollideObjectType;
	
public:

	// 在 Notify State 範圍內每禎觸發
	virtual void NotifyTick(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float FrameDeltaTime, const FAnimNotifyEventReference& EventReference) override;

	// Get the notify name
	virtual FString GetNotifyName_Implementation() const override;
};
  • iThomeAnimNotifyState_DoAttackTrace.cpp
#include "iThomeAnimNotifyState_DoAttackTrace.h"
#include "Components/SkeletalMeshComponent.h"
#include "iThome30daysCharacter.h"

void UiThomeAnimNotifyState_DoAttackTrace::NotifyTick(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float FrameDeltaTime, const FAnimNotifyEventReference& EventReference)
{
    // 試著呼叫使用這 NotifyState 的人(?) 的 DoAttackTrace 功能 
	if (AiThome30daysCharacter* Character = Cast<AiThome30daysCharacter>(MeshComp->GetOwner()))
	{
		Character->DoAttackTrace(TraceSocketStart, TraceSocketEnd, Radius, CollideObjectType);
	}
}

FString UiThomeAnimNotifyState_DoAttackTrace::GetNotifyName_Implementation() const
{
	return FString("Do Attack Trace");
}

2. Code

  • iThome30daysCharacter.h
public:
    virtual void DoAttackTrace(FName TraceSocketStart, FName TraceSocketEnd, float Radius, TArray<TEnumAsByte<EObjectTypeQuery>> CollideObjectType);
  • iThome30daysCharacter.cpp
void AiThome30daysCharacter::DoAttackTrace(FName TraceSocketStart, FName TraceSocketEnd, float Radius, TArray<TEnumAsByte<EObjectTypeQuery>> CollideObjectType)
{
	GEngine->AddOnScreenDebugMessage((uint64)GetTypeHash(FString("wada")), 1, FColor::Orange, TraceSocketStart.ToString());

	AActor* HitActor;

    // 取得 Socket 的位置
	const FVector Start = GetMesh()->GetSocketLocation(TraceSocketStart);
	const FVector End = (TraceSocketEnd!=NAME_None) ? GetMesh()->GetSocketLocation(TraceSocketEnd) : Start;
	
	TArray<AActor*> IgnoreActors;
	IgnoreActors.Add(this);  
	
	FHitResult HitResult;

	bool bHit = UKismetSystemLibrary::SphereTraceSingleForObjects(
		this,
		Start,
		End,
		Radius,
		CollideObjectType,
		false,
		IgnoreActors,
		EDrawDebugTrace::ForDuration,
		HitResult,
		true,
		FColor::Red,
		FColor::Green,
		1.0f
		);
	
	if (bHit)
	{
		HitActor = HitResult.GetActor();
		GEngine->AddOnScreenDebugMessage((uint64)GetTypeHash(FString("atkhit12312")), 1, FColor::Red, UKismetSystemLibrary::GetDisplayName(HitActor));
	}
}

3. 使用

  • 在 Animation Montage 新增一個 Track,右鍵 > Add Notify State > 剛剛的那個
    https://ithelp.ithome.com.tw/upload/images/20250925/20171036AZLlUJbxNg.png

  • 修改參數
    https://ithelp.ithome.com.tw/upload/images/20250925/20171036jmIGIER8af.png

然後就完成了!
這裡用了2個 Socket 是為了之後可以用在武器上像是棍棒、劍之類的

這個。。做完之後覺得這個動畫 Notify 用藍圖做就好了,C++ 的 API 實在是太難找了,效率不會差太多,官網也寫不完全 = = ;

明天就可以讓他裝備武器了!


上一篇
# Day 10|增加Combo系統
下一篇
# Day 12|加武器
系列文
30 天用 Unreal Engine 5 C++ 開發遊戲15
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言