Skip to content

Commit

Permalink
完善敌人死亡后的效果:死亡后修改碰撞,并应用物理动画。
Browse files Browse the repository at this point in the history
  • Loading branch information
storyoftime66 committed Mar 23, 2023
1 parent 047fb2b commit b09fcf5
Show file tree
Hide file tree
Showing 165 changed files with 102 additions and 17 deletions.
1 change: 1 addition & 0 deletions Config/DefaultGameplayTags.ini
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ InvalidTagCharacters="\"\',"
+GameplayTagRedirects=(OldTagName="SekiroLike.Data.DamageMagnification",NewTagName="SekiroLike.Data.HealthDamageMagnification")
NumBitsForContainerSize=6
NetIndexFirstBitSegment=16
+GameplayTagList=(Tag="GameplayCue.Event.EnemyKatanaBlock",DevComment="Katana的格挡特效")
+GameplayTagList=(Tag="GameplayCue.Event.Hurt",DevComment="受伤时的音效")
+GameplayTagList=(Tag="GameplayCue.Event.Parry",DevComment="")
+GameplayTagList=(Tag="GameplayCue.Event.PlayerBlock",DevComment="玩家格挡住攻击时的游戏效果")
Expand Down
Binary file modified Content/DevMap.umap
Binary file not shown.
Binary file modified Content/DevMap_BuiltData.uasset
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified Content/SekiroLike/Blueprints/Characters/BP_PlayerCharacter.uasset
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed Content/SwordAnimationPack/Maps/TestLevel.umap
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed Content/SwordAnimationPack/Sword/Sword.uasset
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ void UDidItHitActorComponent::ToggleTraceCheck(bool NewCanTrace)
HitActors.Empty();
TempIgnoredActors.Append(IgnoredActors);
}
SetComponentTickEnabled(NewCanTrace);
bCanTrace = NewCanTrace;
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,13 @@ void UBTTask_TryActivateAbility::TickTask(UBehaviorTreeComponent& OwnerComp, uin
{
FBTWaitAbilityEnded* MyMemory = reinterpret_cast<FBTWaitAbilityEnded*>(NodeMemory);

if (MyMemory and IsValid(MyMemory->ASC))
if (MyMemory and MyMemory->ASC.IsValid())
{
MyMemory->bAbilityCancelled = MyMemory->ASC->IsAbilityCancelled(AbilityClass);
if (MyMemory->bAbilityCancelled)
{
FinishLatentAbort(OwnerComp);
// FinishLatentAbort(OwnerComp); // Note: 这句会导致行为树一直不结束执行这个节点,一直卡在这
FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
}

MyMemory->bAbilityEnded = MyMemory->ASC->IsAbilityEnded(AbilityClass);
Expand All @@ -93,7 +94,7 @@ void UBTTask_TryActivateAbility::TickTask(UBehaviorTreeComponent& OwnerComp, uin
void UBTTask_TryActivateAbility::OnTaskFinished(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, EBTNodeResult::Type TaskResult)
{
FBTWaitAbilityEnded* MyMemory = reinterpret_cast<FBTWaitAbilityEnded*>(NodeMemory);
if (MyMemory and IsValid(MyMemory->ASC))
if (MyMemory and MyMemory->ASC.IsValid())
{
MyMemory->ASC->RemoveSelfServiceQueryAbility(AbilityClass);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
void UAbilityTask_WaitTargetDataUsingActor::RemoveTargetActorFromConfirmCancelInputs()
{
// Note: 从TargetActor::EndPlay中抄的
if (TargetActor and TargetActor->GenericDelegateBoundASC)
if (IsValid(TargetActor) and TargetActor->GenericDelegateBoundASC)
{
// We must remove ourselves from GenericLocalConfirmCallbacks/GenericLocalCancelCallbacks, since while these are bound they will inhibit any *other* abilities
// that are bound to the same key.
Expand All @@ -28,6 +28,9 @@ void UAbilityTask_WaitTargetDataUsingActor::RemoveTargetActorFromConfirmCancelIn
}

ensure(TargetActor->GenericDelegateBoundASC == UnboundASC); // Error checking that we have removed delegates from the same ASC we bound them to

// 由于TargetActor 在EndPlay的时候还会去解绑一次,所以在这里解绑后要先置空
TargetActor->GenericDelegateBoundASC = nullptr;
}
}

Expand Down
49 changes: 46 additions & 3 deletions Source/SekiroLike/Private/Characters/BaseCharacter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "Abilities/SLAbilityTypes.h"
#include "Characters/CharAttributeSet.h"
#include "Characters/Components/SLCharacterMovementComponent.h"
#include "Components/CapsuleComponent.h"
#include "GameFramework/CharacterMovementComponent.h"


Expand Down Expand Up @@ -45,6 +46,12 @@ void ABaseCharacter::ReactToHit(FName BoneName, FVector HitImpulse)
ReactToHitTimeline.PlayFromStart();
}

void ABaseCharacter::NotifyDied(AActor* InInstigator)
{
const FTimerDelegate TimerDelegate = FTimerDelegate::CreateUObject(this, &ABaseCharacter::Died, InInstigator);
GetWorldTimerManager().SetTimerForNextTick(TimerDelegate);
}

void ABaseCharacter::ReactToHitFinished()
{
if (GetMesh())
Expand Down Expand Up @@ -110,17 +117,53 @@ void ABaseCharacter::PostInitializeComponents()
}
}

void ABaseCharacter::Died_Implementation(AActor* InInstigator)
{
if (IsValid(GetCapsuleComponent()))
{
GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::PhysicsOnly);
GetCapsuleComponent()->SetCollisionResponseToChannel(ECC_Pawn, ECR_Ignore);
GetCapsuleComponent()->SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore);
}

if (IsValid(GetMesh()))
{
GetMesh()->SetCollisionEnabled(ECollisionEnabled::PhysicsOnly);
GetMesh()->SetAllBodiesBelowSimulatePhysics(FName("root"), true);
GetMesh()->SetAllBodiesBelowPhysicsBlendWeight(FName("root"), 1.0f);
}

if (IsValid(ASC))
{
ASC->CancelAbilities();
ASC->ClearAllAbilities();
}

IsCharacterDead = true;
}

// Called every frame
void ABaseCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);

static FGameplayTagContainer ActiveAbilityTags = FGameplayTagContainer(FGameplayTag::RequestGameplayTag("SekiroLike.Ability.ActiveAbility"));

ReactToHitTimeline.TickTimeline(DeltaTime);

// TODO: 状态有Bug,会导致ASC残留ActiveAbility的 BlockedTag
if (IsValid(ASC))
// TODO: 状态有Bug,会导致ASC残留ActiveAbility的 BlockedTag,但是还找不到原因
if (IsValid(ASC) and ASC->AreAbilityTagsBlocked(ActiveAbilityTags))
{
TimeAccumulation += DeltaTime;
if (TimeAccumulation > 2.0f)
{
TimeAccumulation = 0.0f;
ASC->UnBlockAbilitiesWithTags(ActiveAbilityTags);
}
}
else
{
// if(ASC->GetAnimatingAbility() == nullptr and ASC->) {}
TimeAccumulation = 0.0f;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "DrawDebugHelpers.h"
#include "Blueprint/UserWidget.h"
#include "Characters/AbilityAvatarInterface.h"
#include "Components/WidgetComponent.h"
#include "GameFramework/Character.h"
#include "GameFramework/CharacterMovementComponent.h"
Expand Down Expand Up @@ -96,6 +97,17 @@ void UPlayerFocusComp::TickComponent(float DeltaTime, ELevelTick TickType, FActo
if (FVector::DistSquared(CompOwner->GetActorLocation(), FocusedCharacter->GetActorLocation()) > MaxDistanceSquare)
{
SetFocusedCharacter(nullptr);
return;
}

// 角色死亡解除锁定
if (auto AbilityAvatar = Cast<IAbilityAvatarInterface>(FocusedCharacter))
{
if (AbilityAvatar->IsDead())
{
SetFocusedCharacter(nullptr);
return;
}
}
}
else
Expand Down Expand Up @@ -214,15 +226,14 @@ void UPlayerFocusComp::SetFocusedCharacter(ACharacter* NewCharacter)
{
if (IsValid(ReticleClass))
{
// 移除原来的reticle并添加新的reticle
if (IsValid(FocusedCharacter) and IsValid(ReticleWidgetComp))
{
// 移除原来的reticle
ReticleWidgetComp->DestroyComponent();
ReticleWidgetComp = nullptr;
}
if (IsValid(NewCharacter))
{
// 添加新的reticle
ReticleWidgetComp = NewObject<UWidgetComponent>(NewCharacter, UWidgetComponent::StaticClass());
ReticleWidgetComp->RegisterComponent();
ReticleWidgetComp->AttachToComponent(NewCharacter->GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct FBTWaitAbilityEnded
float RemainingWaitTime;
bool bAbilityEnded;
bool bAbilityCancelled;
USLAbilitySystemComponent* ASC;
TWeakObjectPtr<USLAbilitySystemComponent> ASC;
};

/**
Expand Down
13 changes: 13 additions & 0 deletions Source/SekiroLike/Public/Characters/AbilityAvatarInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class SEKIROLIKE_API IAbilityAvatarInterface
public:
///////////////////////////
/// 技能相关
///////////////////////////
/** 添加角色技能阶段tag(前摇、生效、后摇) */
virtual void AddAbilityStage(const FGameplayTag& AbilityStageTag)
{
Expand All @@ -51,6 +52,7 @@ class SEKIROLIKE_API IAbilityAvatarInterface

//////////////////
/// 动画相关
//////////////////
/** 获取角色移动时在前面的脚
* 左脚在前时返回-1,双脚平行时返回0,右脚在前时返回1 */
UFUNCTION(BlueprintCallable, Category="SekiroLike|AbilityAvatarInterface")
Expand All @@ -74,6 +76,17 @@ class SEKIROLIKE_API IAbilityAvatarInterface
virtual void ReactToHit(FName BoneName, FVector HitImpulse)
{
}

///////////////////////////
/// 其他Gameplay逻辑
///////////////////////////
/** 告知角色已死亡
* @param Instigator 凶手 */
UFUNCTION(BlueprintCallable, Category="SekiroLike|AbilityAvatarInterface")
virtual void NotifyDied(AActor* Instigator) {}
/** 角色是否已死亡 */
UFUNCTION(BlueprintCallable, Category="SekiroLike|AbilityAvatarInterface")
virtual bool IsDead() { return false; }
};


Expand Down
26 changes: 19 additions & 7 deletions Source/SekiroLike/Public/Characters/BaseCharacter.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ class SEKIROLIKE_API ABaseCharacter :
{
GENERATED_BODY()

/** TODO: 临时用于解决BlockTags问题的变量 */
float TimeAccumulation = 0.0f;

////////////////////////////////////////////////////////////
/// 技能系统
////////////////////////////////////////////////////////////
protected:
/** 技能组件和属性集 */
// UPROPERTY()
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
USLAbilitySystemComponent* ASC;
UPROPERTY()
Expand All @@ -47,7 +49,7 @@ class SEKIROLIKE_API ABaseCharacter :
/** 初始效果(包括初始属性) */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="SekiroLike|Ability")
TArray<TSubclassOf<UGameplayEffect>> InitialEffects;

/** 初始激活的技能的SpecHandles */
UPROPERTY()
TArray<FGameplayAbilitySpecHandle> PersistentSpecHandles;
Expand Down Expand Up @@ -96,6 +98,8 @@ class SEKIROLIKE_API ABaseCharacter :
/** 当前姿势类型,分为左手姿势和右手姿势 */
EPostureType PostureType = EPostureType::None;

/** 角色是否已死亡 */
bool IsCharacterDead = false;

/** 物理动画混合权重时间轴函数 */
UFUNCTION()
Expand All @@ -113,17 +117,25 @@ class SEKIROLIKE_API ABaseCharacter :
virtual EPostureType GetPostureType() const override { return PostureType; }
virtual void SetPostureType(EPostureType NewPostureType) override { PostureType = NewPostureType; }
virtual void ReactToHit(FName BoneName, FVector HitImpulse) override;
virtual void NotifyDied(AActor* InInstigator) override;
virtual bool IsDead() override { return IsCharacterDead; }

protected:
virtual void PostInitializeComponents() override;
/** 善后工作 */
UFUNCTION(BlueprintNativeEvent, Category="SekiroLike|Character")
void Died(AActor* InInstigator);

public:
ABaseCharacter(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());

virtual void Tick(float DeltaTime) override;

//~ IGenericTeamAgentInterface
virtual void SetGenericTeamId(const FGenericTeamId& NewTeamID) override;
virtual FGenericTeamId GetGenericTeamId() const override;
virtual ETeamAttitude::Type GetTeamAttitudeTowards(const AActor& Other) const override;

public:
ABaseCharacter(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());

virtual void Tick(float DeltaTime) override;

protected:
virtual void PostInitializeComponents() override;
};

0 comments on commit b09fcf5

Please sign in to comment.