异步加载基本OK

This commit is contained in:
2023-07-20 01:29:36 +08:00
parent 5917dd3f59
commit 0bdfb318fe
59 changed files with 735 additions and 4 deletions

View File

@@ -0,0 +1,267 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "AT_PlayMontageAndWaitForEvent.h"
#include "AbilitySystemComponent.h"
#include "AbilitySystemGlobals.h"
#include "TGAbilitySystemComponent.h"
#include "GameFramework/Character.h"
UAT_PlayMontageAndWaitForEvent::UAT_PlayMontageAndWaitForEvent(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
Rate = 1.f;
bStopWhenAbilityEnds = true;
}
UAbilitySystemComponent* UAT_PlayMontageAndWaitForEvent::GetTargetASC()
{
return Cast<UAbilitySystemComponent>(AbilitySystemComponent);
}
void UAT_PlayMontageAndWaitForEvent::OnMontageBlendingOut(UAnimMontage* Montage, bool bInterrupted)
{
if (Ability && Ability->GetCurrentMontage() == MontageToPlay)
{
if (Montage == MontageToPlay)
{
AbilitySystemComponent->ClearAnimatingAbility(Ability);
// Reset AnimRootMotionTranslationScale
ACharacter* Character = Cast<ACharacter>(GetAvatarActor());
if (Character && (Character->GetLocalRole() == ROLE_Authority ||
(Character->GetLocalRole() == ROLE_AutonomousProxy && Ability->GetNetExecutionPolicy() == EGameplayAbilityNetExecutionPolicy::LocalPredicted)))
{
Character->SetAnimRootMotionTranslationScale(1.f);
}
}
}
if (bInterrupted)
{
if (ShouldBroadcastAbilityTaskDelegates())
{
OnInterrupted.Broadcast(FGameplayTag(), FGameplayEventData());
}
}
else
{
if (ShouldBroadcastAbilityTaskDelegates())
{
OnBlendOut.Broadcast(FGameplayTag(), FGameplayEventData());
}
}
}
void UAT_PlayMontageAndWaitForEvent::OnAbilityCancelled()
{
if (StopPlayingMontage())
{
// Let the BP handle the interrupt as well
if (ShouldBroadcastAbilityTaskDelegates())
{
OnCancelled.Broadcast(FGameplayTag(), FGameplayEventData());
}
}
}
void UAT_PlayMontageAndWaitForEvent::OnMontageEnded(UAnimMontage* Montage, bool bInterrupted)
{
if (!bInterrupted)
{
if (ShouldBroadcastAbilityTaskDelegates())
{
OnCompleted.Broadcast(FGameplayTag(), FGameplayEventData());
}
}
EndTask();
}
void UAT_PlayMontageAndWaitForEvent::OnGameplayEvent(FGameplayTag EventTag, const FGameplayEventData* Payload)
{
if (ShouldBroadcastAbilityTaskDelegates())
{
FGameplayEventData TempData = *Payload;
TempData.EventTag = EventTag;
EventReceived.Broadcast(EventTag, TempData);
}
}
UAT_PlayMontageAndWaitForEvent* UAT_PlayMontageAndWaitForEvent::PlayMontageAndWaitForEvent(UGameplayAbility* OwningAbility,
FName TaskInstanceName, UAnimMontage* MontageToPlay, FGameplayTagContainer EventTags, float Rate, FName StartSection, bool bStopWhenAbilityEnds, float AnimRootMotionTranslationScale)
{
UAbilitySystemGlobals::NonShipping_ApplyGlobalAbilityScaler_Rate(Rate);
UAT_PlayMontageAndWaitForEvent* MyObj = NewAbilityTask<UAT_PlayMontageAndWaitForEvent>(OwningAbility, TaskInstanceName);
MyObj->MontageToPlay = MontageToPlay;
MyObj->EventTags = EventTags;
MyObj->Rate = Rate;
MyObj->StartSection = StartSection;
MyObj->AnimRootMotionTranslationScale = AnimRootMotionTranslationScale;
MyObj->bStopWhenAbilityEnds = bStopWhenAbilityEnds;
return MyObj;
}
void UAT_PlayMontageAndWaitForEvent::Activate()
{
if (Ability == nullptr)
{
return;
}
bool bPlayedMontage = false;
UAbilitySystemComponent* GDAbilitySystemComponent = GetTargetASC();
if (GDAbilitySystemComponent)
{
const FGameplayAbilityActorInfo* ActorInfo = Ability->GetCurrentActorInfo();
UAnimInstance* AnimInstance = ActorInfo->GetAnimInstance();
if (AnimInstance != nullptr)
{
// Bind to event callback
EventHandle = GDAbilitySystemComponent->AddGameplayEventTagContainerDelegate(EventTags, FGameplayEventTagMulticastDelegate::FDelegate::CreateUObject(this, &UAT_PlayMontageAndWaitForEvent::OnGameplayEvent));
if (GDAbilitySystemComponent->PlayMontage(Ability, Ability->GetCurrentActivationInfo(), MontageToPlay, Rate, StartSection) > 0.f)
{
// Playing a montage could potentially fire off a callback into game code which could kill this ability! Early out if we are pending kill.
if (ShouldBroadcastAbilityTaskDelegates() == false)
{
return;
}
CancelledHandle = Ability->OnGameplayAbilityCancelled.AddUObject(this, &UAT_PlayMontageAndWaitForEvent::OnAbilityCancelled);
BlendingOutDelegate.BindUObject(this, &UAT_PlayMontageAndWaitForEvent::OnMontageBlendingOut);
AnimInstance->Montage_SetBlendingOutDelegate(BlendingOutDelegate, MontageToPlay);
MontageEndedDelegate.BindUObject(this, &UAT_PlayMontageAndWaitForEvent::OnMontageEnded);
AnimInstance->Montage_SetEndDelegate(MontageEndedDelegate, MontageToPlay);
ACharacter* Character = Cast<ACharacter>(GetAvatarActor());
if (Character && (Character->GetLocalRole() == ROLE_Authority ||
(Character->GetLocalRole() == ROLE_AutonomousProxy && Ability->GetNetExecutionPolicy() == EGameplayAbilityNetExecutionPolicy::LocalPredicted)))
{
Character->SetAnimRootMotionTranslationScale(AnimRootMotionTranslationScale);
}
bPlayedMontage = true;
}
}
else
{
UE_LOG(LogTemp, Warning, TEXT("UGDAbilityTask_PlayMontageAndWaitForEvent call to PlayMontage failed!"));
}
}
else
{
UE_LOG(LogTemp, Warning, TEXT("UGDAbilityTask_PlayMontageAndWaitForEvent called on invalid AbilitySystemComponent"));
}
if (!bPlayedMontage)
{
UE_LOG(LogTemp, Warning, TEXT("UGDAbilityTask_PlayMontageAndWaitForEvent called in Ability %s failed to play montage %s; Task Instance Name %s."), *Ability->GetName(), *GetNameSafe(MontageToPlay), *InstanceName.ToString());
if (ShouldBroadcastAbilityTaskDelegates())
{
//ABILITY_LOG(Display, TEXT("%s: OnCancelled"), *GetName());
OnCancelled.Broadcast(FGameplayTag(), FGameplayEventData());
}
}
SetWaitingOnAvatar();
}
void UAT_PlayMontageAndWaitForEvent::ExternalCancel()
{
//check(AbilitySystemComponent);
OnAbilityCancelled();
Super::ExternalCancel();
}
void UAT_PlayMontageAndWaitForEvent::OnDestroy(bool AbilityEnded)
{
// Note: Clearing montage end delegate isn't necessary since its not a multicast and will be cleared when the next montage plays.
// (If we are destroyed, it will detect this and not do anything)
// This delegate, however, should be cleared as it is a multicast
if (Ability)
{
Ability->OnGameplayAbilityCancelled.Remove(CancelledHandle);
if (AbilityEnded && bStopWhenAbilityEnds)
{
StopPlayingMontage();
}
}
UAbilitySystemComponent* GDAbilitySystemComponent = GetTargetASC();
if (GDAbilitySystemComponent)
{
GDAbilitySystemComponent->RemoveGameplayEventTagContainerDelegate(EventTags, EventHandle);
}
Super::OnDestroy(AbilityEnded);
}
bool UAT_PlayMontageAndWaitForEvent::StopPlayingMontage()
{
const FGameplayAbilityActorInfo* ActorInfo = Ability->GetCurrentActorInfo();
if (!ActorInfo)
{
return false;
}
UAnimInstance* AnimInstance = ActorInfo->GetAnimInstance();
if (AnimInstance == nullptr)
{
return false;
}
// Check if the montage is still playing
// The ability would have been interrupted, in which case we should automatically stop the montage
//if (AbilitySystemComponent && Ability)
if ( Ability)
{
if (AbilitySystemComponent->GetAnimatingAbility() == Ability
&& AbilitySystemComponent->GetCurrentMontage() == MontageToPlay)
{
// Unbind delegates so they don't get called as well
FAnimMontageInstance* MontageInstance = AnimInstance->GetActiveInstanceForMontage(MontageToPlay);
if (MontageInstance)
{
MontageInstance->OnMontageBlendingOutStarted.Unbind();
MontageInstance->OnMontageEnded.Unbind();
}
AbilitySystemComponent->CurrentMontageStop();
return true;
}
}
return false;
}
FString UAT_PlayMontageAndWaitForEvent::GetDebugString() const
{
UAnimMontage* PlayingMontage = nullptr;
if (Ability)
{
const FGameplayAbilityActorInfo* ActorInfo = Ability->GetCurrentActorInfo();
UAnimInstance* AnimInstance = ActorInfo->GetAnimInstance();
if (AnimInstance != nullptr)
{
PlayingMontage = AnimInstance->Montage_IsActive(MontageToPlay) ? MontageToPlay : AnimInstance->GetCurrentActiveMontage();
}
}
return FString::Printf(TEXT("PlayMontageAndWaitForEvent. MontageToPlay: %s (Currently Playing): %s"), *GetNameSafe(MontageToPlay), *GetNameSafe(PlayingMontage));
}

View File

@@ -0,0 +1,86 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "AsyncLoadingFunctionLibrary.h"
#include "Components/TimelineComponent.h"
#include "Engine/AssetManager.h"
#include "Engine/StreamableManager.h"
void UAsyncLoadingFunctionLibrary::TenGenAsyncLoad(TSoftObjectPtr<> PageageLoad,FString& LoadPackagePath,
const FOnAsyncLoadFinished& OnAsyncLoadFinished)
{
LoadPackagePath = FPaths::GetBaseFilename(PageageLoad.ToString(), false);
//打印loadpackagepath
// GEngine->AddOnScreenDebugMessage(-1, 20.0f, FColor::Green, LoadPackagePath);
//shu
// UE_LOG(LogTemp, Warning, TEXT("String: %s"), *LoadPackagePath);
LoadPackageAsync(LoadPackagePath,FLoadPackageAsyncDelegate::CreateLambda([=](const FName& PackageName, UPackage* LoadedPackage, EAsyncLoadingResult::Type Result)
{
if (Result == EAsyncLoadingResult::Failed)
{
UE_LOG(LogTemp, Warning, TEXT("Load Failed"));
}
else if (Result == EAsyncLoadingResult::Succeeded)
{
UE_LOG(LogTemp, Warning, TEXT("Load Succeeded"));
OnAsyncLoadFinished.ExecuteIfBound(LoadPackagePath);
}
}), 0, PKG_ContainsMap);
}
void UAsyncLoadingFunctionLibrary::AsyncLoadWithStreamableManager(TSoftObjectPtr<UObject> AssetPtr, FString& LoadPackagePath, const FOnAsyncLoadFinished& OnAsyncLoadFinished)
{
LoadPackagePath = FPaths::GetBaseFilename(AssetPtr.ToString(), false);
//异步加载
FStreamableManager& Streamable = UAssetManager::GetStreamableManager();
Streamable.RequestAsyncLoad(AssetPtr.ToSoftObjectPath(), FStreamableDelegate::CreateLambda([=]()
{
OnAsyncLoadFinished.ExecuteIfBound(LoadPackagePath);
}));
}
float UAsyncLoadingFunctionLibrary::GetLoadProgress(FString LoadPackagePath)
{
//取得加载进度,压缩到0-1之间
float FloatPercentage = GetAsyncLoadPercentage(*LoadPackagePath) / 100.0f;
// FString ResultStr = FString::Printf(TEXT("Percentage: %f"), FloatPercentage);
// GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Green, ResultStr);
// UE_LOG(LogTemp, Warning, TEXT("Percentage: %f"), FloatPercentage);
return FloatPercentage;
}

View File

@@ -0,0 +1,115 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "OSBlueprintFunctionLibrary.h"
#include "GameFramework/PlayerState.h"
//#include "Animation/WidgetAnimation.h"
//#include "Components/WidgetComponent.h"
//设置SceneComponent的朝向为面向当前摄像机
void UOSBlueprintFunctionLibrary::FaceActorToCamera(USceneComponent* SceneComponent)
{
if (SceneComponent)
{
//获取当前摄像机的位置
FVector CameraLocation = GEngine->GetFirstLocalPlayerController(GWorld)->PlayerCameraManager->GetCameraLocation();
//获取SceneComponent的位置
FVector SceneComponentLocation = SceneComponent->GetComponentLocation();
//计算朝向
FVector Direction = CameraLocation - SceneComponentLocation;
//设置朝向
SceneComponent->SetWorldRotation(Direction.Rotation());
}
}
//输入一个actor数组求出其中距离自身最近的actor,并且检查结果与上一帧的结果是否一致如果不一致则输出一个bool值用于判断是否需要更新最近的actor.
AActor* UOSBlueprintFunctionLibrary::GetNearestActor(TArray<AActor*> Actors, AActor* SelfActor,AActor* LastNearestActor, bool& bIsNeedUpdate)
{
AActor* NearestActor = nullptr;
float MinDistance = 0.0f;
for (auto Actor : Actors)
{
if (Actor != SelfActor)
{
float Distance = FVector::Distance(Actor->GetActorLocation(), SelfActor->GetActorLocation());
if (MinDistance == 0.0f)
{
MinDistance = Distance;
NearestActor = Actor;
}
else
{
if (Distance < MinDistance)
{
MinDistance = Distance;
NearestActor = Actor;
}
}
}
}
if (NearestActor != nullptr)
{
//如果最近的actor与上一帧的最近actor不一致或者最近actor是null的时候则需要更新
if (NearestActor != LastNearestActor || LastNearestActor == nullptr)
{
bIsNeedUpdate = true;
}
else
{
bIsNeedUpdate = false;
}
}
else
{
if (LastNearestActor != nullptr)
{
bIsNeedUpdate = true;
}
bIsNeedUpdate = false;
}
return NearestActor;
}

View File

@@ -0,0 +1,84 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Abilities/Tasks/AbilityTask.h"
#include "AT_PlayMontageAndWaitForEvent.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FPlayMontageAndWaitForEventDelegate,FGameplayTag,EventTag,FGameplayEventData,EventData);
/**
*
*/
UCLASS()
class TG_ARPG_API UAT_PlayMontageAndWaitForEvent : public UAbilityTask
{
GENERATED_BODY()
public:
UAT_PlayMontageAndWaitForEvent(const FObjectInitializer& ObjectInitializer);
virtual void Activate() override;
virtual void ExternalCancel() override;
virtual FString GetDebugString() const override;
virtual void OnDestroy(bool AbilityEnded) override;
UPROPERTY(BlueprintAssignable)
FPlayMontageAndWaitForEventDelegate OnCompleted;
UPROPERTY(BlueprintAssignable)
FPlayMontageAndWaitForEventDelegate OnBlendOut;
UPROPERTY(BlueprintAssignable)
FPlayMontageAndWaitForEventDelegate OnInterrupted;
UPROPERTY(BlueprintAssignable)
FPlayMontageAndWaitForEventDelegate OnCancelled;
UPROPERTY(BlueprintAssignable)
FPlayMontageAndWaitForEventDelegate EventReceived;
UFUNCTION(BlueprintCallable, Category = "Ability|Tasks", meta = (HidePin = "OwningAbility", DefaultToSelf = "OwningAbility", BlueprintInternalUseOnly = "TRUE"))
static UAT_PlayMontageAndWaitForEvent* PlayMontageAndWaitForEvent(
UGameplayAbility* OwningAbility,
FName TaskInstanceName,
UAnimMontage* MontageToPlay,
FGameplayTagContainer EventTags,
float Rate = 1.f,
FName StartSection = NAME_None,
bool bStopWhenAbilityEnds = true,
float AnimRootMotionTranslationScale = 1.f);
private:
UPROPERTY()
UAnimMontage* MontageToPlay;
UPROPERTY()
FGameplayTagContainer EventTags;
UPROPERTY()
float Rate;
UPROPERTY()
FName StartSection;
UPROPERTY()
float AnimRootMotionTranslationScale;
UPROPERTY()
bool bStopWhenAbilityEnds;
bool StopPlayingMontage();
UAbilitySystemComponent* GetTargetASC();
void OnMontageBlendingOut(UAnimMontage* Montage, bool bInterrupted);
void OnAbilityCancelled();
void OnMontageEnded(UAnimMontage* Montage, bool bInterrupted);
void OnGameplayEvent(FGameplayTag EventTag, const FGameplayEventData* Payload);
FOnMontageBlendingOutStarted BlendingOutDelegate;
FOnMontageEnded MontageEndedDelegate;
FDelegateHandle CancelledHandle;
FDelegateHandle EventHandle;
};

View File

@@ -0,0 +1,53 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintAsyncActionBase.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "AsyncLoadingFunctionLibrary.generated.h"
DECLARE_DYNAMIC_DELEGATE_OneParam(FOnAsyncLoadFinished, FString, LoadPackagePath);
//注册委托,回调一个float,用于进度条
DECLARE_DYNAMIC_DELEGATE_OneParam(FOnAsyncLoadProgress, float, LoadProgress);
/**
*
*/
UCLASS()
class TG_ARPG_API UAsyncLoadingFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
/**
* 普通异步加载
* @param PageageLoad 要加载的资源
*/
UFUNCTION(BlueprintCallable,Category = "AsyncLoad")
static void TenGenAsyncLoad(TSoftObjectPtr<UObject> PageageLoad ,FString& LoadPackagePath,const FOnAsyncLoadFinished& OnAsyncLoadFinished);
/**
* 使用SteamableManger的异步加载
* @param AssetPtr 要加载的资源
*/
UFUNCTION(BlueprintCallable,Category = "AsyncLoad")
static void AsyncLoadWithStreamableManager(TSoftObjectPtr<UObject> AssetPtr, FString& LoadPackagePath, const FOnAsyncLoadFinished& OnAsyncLoadFinished);
//一个函数,用于加载进度条
UFUNCTION(BlueprintCallable, Category = "AsyncLoad")
static float GetLoadProgress(FString LoadPackagePath);
};

View File

@@ -0,0 +1,46 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "OSBlueprintFunctionLibrary.generated.h"
/**
*
*/
//一个数据结构,用于储存一个数组的值用来做执行引脚
UENUM(BlueprintType)
enum class EBlueprintExecNodePin : uint8
{
False1,
True1
};
UCLASS()
class TG_ARPG_API UOSBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
UFUNCTION(BlueprintCallable,Category="OSBlueprintFunctionLibrary")
static void FaceActorToCamera(USceneComponent* SceneComponent);
//
UFUNCTION(BlueprintCallable,Category="OSBlueprintFunctionLibrary")
static AActor* GetNearestActor(TArray<AActor*> Actors, AActor* SelfActor, AActor* LastNearestActor,bool& bIsNeedUpdate);
};

View File

@@ -4,6 +4,11 @@
#include "TG_ARPGCharacter.h"
#include "UObject/ConstructorHelpers.h"
ATG_ARPGGameMode::ATG_ARPGGameMode()
{
// set default pawn class to our Blueprinted character
@@ -13,3 +18,7 @@ ATG_ARPGGameMode::ATG_ARPGGameMode()
DefaultPawnClass = PlayerPawnBPClass.Class;
}
}

View File

@@ -6,6 +6,8 @@
#include "GameFramework/GameMode.h"
#include "TG_ARPGGameMode.generated.h"
UCLASS(minimalapi)
class ATG_ARPGGameMode : public AGameMode
{
@@ -13,6 +15,7 @@ class ATG_ARPGGameMode : public AGameMode
public:
ATG_ARPGGameMode();
};