单击游戏交流网

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 91|回复: 0

ue5 Lyra初学者游戏包-L_ShooterTest_AutoRun关卡

[复制链接]

3

主题

4

帖子

10

积分

新手上路

Rank: 1

积分
10
发表于 2023-4-9 21:44:15 | 显示全部楼层 |阅读模式

Plugins/ShooterTests内容/Maps/L_ShooterTest_AutoRun.umap以及L_ShooterTest_FireWeapon.umap-关卡蓝图空的
关卡功能


  • 单人角色B_Hero_ShooterMannequin0在PlayerStart1生成,可进行武器射击。
  • UI部分,15分得分显示,12分支倒计时,血量显示,炸弹,武器123,子弹-当前/总。
  • 武器准星显示
  • 世界场景设置里Default Gameplay Experience=B_BasicShooterTest(父类是LyraExperienceDefinition-PrimaryDataAsset),这个正常项目是没有的
编辑-项目设置-地图和模式


  • 默认模式=B_LyraGameMode-父类是c++的LyraGame.LyraGameMode
  • 默认pawn类=LyraCharacter
  • HUD类=LyraHUD
  • 玩家控制器类=LyraPlayerController
  • 游戏状态类=LyraGameState
  • 玩家状态类=LyraPlayerState
  • 旁观者类=SpectatorPawn
按键输入wasd

同初始关卡
代码逻辑

先加载资源B_BasicShooterTest,加载完成后
角色生成:gamemode设置pawn=LyraCharacter,但是生成了B_Hero_ShooterMannequin0,查引用-HeroData_ShooterGame.Pawn Class-B_BasicShooterTest.Default Pawn Data


void ALyraGameMode::InitGameState()
ExperienceComponent->CallOrRegister_OnExperienceLoaded(FOnLyraExperienceLoaded::FDelegate::CreateUObject(this, &ThisClass::OnExperienceLoaded));
void ALyraGameMode::OnExperienceLoaded(const ULyraExperienceDefinition* CurrentExperience)
RestartPlayer(PC);

void AGameModeBase::RestartPlayer(AController* NewPlayer)
RestartPlayerAtPlayerStart(NewPlayer, StartSpot);
void AGameModeBase::RestartPlayerAtPlayerStart(AController* NewPlayer, AActor* StartSpot)
APawn* NewPawn = SpawnDefaultPawnFor(NewPlayer, StartSpot);

UFUNCTION(BlueprintNativeEvent, Category=Game)
APawn* SpawnDefaultPawnFor(AController* NewPlayer, AActor* StartSpot);

APawn* AGameModeBase::SpawnDefaultPawnFor_Implementation(AController* NewPlayer, AActor* StartSpot)
return SpawnDefaultPawnAtTransform(NewPlayer, Transform);

UFUNCTION(BlueprintNativeEvent, Category=Game)
APawn* SpawnDefaultPawnAtTransform(AController* NewPlayer, const FTransform& SpawnTransform);

//角色pawn生成
APawn* ALyraGameMode::SpawnDefaultPawnAtTransform_Implementation(AController* NewPlayer, const FTransform& SpawnTransform)
{
        FActorSpawnParameters SpawnInfo;
        SpawnInfo.Instigator = GetInstigator();
        SpawnInfo.ObjectFlags |= RF_Transient;        // Never save the default player pawns into a map.
        SpawnInfo.bDeferConstruction = true;

        if (UClass* PawnClass = GetDefaultPawnClassForController(NewPlayer))
        {
                if (APawn* SpawnedPawn = GetWorld()->SpawnActor<APawn>(PawnClass, SpawnTransform, SpawnInfo))
                {
                        if (ULyraPawnExtensionComponent* PawnExtComp = ULyraPawnExtensionComponent::FindPawnExtensionComponent(SpawnedPawn))
                        {
                                if (const ULyraPawnData* PawnData = GetPawnDataForController(NewPlayer))
                                {
                                        PawnExtComp->SetPawnData(PawnData);
                                }
                                else
                                {
                                        UE_LOG(LogLyra, Error, TEXT("Game mode was unable to set PawnData on the spawned pawn [%s]."), *GetNameSafe(SpawnedPawn));
                                }
                        }

                        SpawnedPawn->FinishSpawning(SpawnTransform);

                        return SpawnedPawn;
                }
                else
                {
                        UE_LOG(LogLyra, Error, TEXT("Game mode was unable to spawn Pawn of class [%s] at [%s]."), *GetNameSafe(PawnClass), *SpawnTransform.ToHumanReadableString());
                }
        }
        else
        {
                UE_LOG(LogLyra, Error, TEXT("Game mode was unable to spawn Pawn due to NULL pawn class."));
        }

        return nullptr;
}

//HeroData_ShooterGame.Pawn Class
UClass* ALyraGameMode::GetDefaultPawnClassForController_Implementation(AController* InController)
{
        if (const ULyraPawnData* PawnData = GetPawnDataForController(InController))
        {
                if (PawnData->PawnClass)
                {
                        return PawnData->PawnClass;
                }
        }

        return Super::GetDefaultPawnClassForController_Implementation(InController);
}

//B_BasicShooterTest.Default Pawn Data
const ULyraPawnData* ALyraGameMode::GetPawnDataForController(const AController* InController) const
{
        // See if pawn data is already set on the player state
        if (InController != nullptr)
        {
                if (const ALyraPlayerState* LyraPS = InController->GetPlayerState<ALyraPlayerState>())
                {
                        if (const ULyraPawnData* PawnData = LyraPS->GetPawnData<ULyraPawnData>())
                        {
                                return PawnData;
                        }
                }
        }

        // If not, fall back to the the default for the current experience
        check(GameState);
        ULyraExperienceManagerComponent* ExperienceComponent = GameState->FindComponentByClass<ULyraExperienceManagerComponent>();
        check(ExperienceComponent);

        if (ExperienceComponent->IsExperienceLoaded())
        {
                const ULyraExperienceDefinition* Experience = ExperienceComponent->GetCurrentExperienceChecked();
                if (Experience->DefaultPawnData != nullptr)
                {
                        return Experience->DefaultPawnData;
                }

                // Experience is loaded and there's still no pawn data, fall back to the default for now
                return ULyraAssetManager::Get().GetDefaultPawnData();
        }

        // Experience not loaded yet, so there is no pawn data to be had
        return nullptr;
}
gamestate也有个类似的,比gamemode先调用


void ALyraPlayerState::PostInitializeComponents()
ExperienceComponent->CallOrRegister_OnExperienceLoaded(FOnLyraExperienceLoaded::FDelegate::CreateUObject(this, &ThisClass::OnExperienceLoaded));
void ALyraPlayerState::OnExperienceLoaded(const ULyraExperienceDefinition* /*CurrentExperience*/)
if (const ULyraPawnData* NewPawnData = LyraGameMode->GetPawnDataForController(GetOwningController()))
SetPawnData(NewPawnData);
UI生成:

  • 利用控件反射器找到W_ScoreWidget_Elimination,引用查看器找到B_BasicShooterTest-Actions-(TagName="HUD.Slot.TeamScore")
  • 查c++ Actions成员,断点ActivateListOfActions(CurrentExperience->Actions);


void ULyraExperienceManagerComponent::OnGameFeaturePluginLoadComplete(const UE::GameFeatures::FResult& Result)
OnExperienceFullLoadCompleted();

void ULyraExperienceManagerComponent::OnExperienceFullLoadCompleted()
auto ActivateListOfActions = [&Context](const TArray<UGameFeatureAction*>& ActionList)
        {
                for (UGameFeatureAction* Action : ActionList)
                {
                        if (Action != nullptr)
                        {
                                //@TODO: The fact that these don't take a world are potentially problematic in client-server PIE
                                // The current behavior matches systems like gameplay tags where loading and registering apply to the entire process,
                                // but actually applying the results to actors is restricted to a specific world
                                Action->OnGameFeatureRegistering();
                                Action->OnGameFeatureLoading();
                                Action->OnGameFeatureActivating(Context);
                        }
                }
        };

        ActivateListOfActions(CurrentExperience->Actions);

//断点Action->OnGameFeatureActivating(Context);
Action->OnGameFeatureActivating(Context);

void UGameFeatureAction_AddAbilities::OnGameFeatureActivating(FGameFeatureActivatingContext& Context)
Super::OnGameFeatureActivating(Context);

//这里完成了蓝图控件的加载FWorldDelegates::OnStartGameInstance.AddUObject
void UGameFeatureAction_WorldActionBase::OnGameFeatureActivating(FGameFeatureActivatingContext& Context)
{
        GameInstanceStartHandles.FindOrAdd(Context) = FWorldDelegates::OnStartGameInstance.AddUObject(this,
                &UGameFeatureAction_WorldActionBase::HandleGameInstanceStart, FGameFeatureStateChangeContext(Context));

        // Add to any worlds with associated game instances that have already been initialized
        for (const FWorldContext& WorldContext : GEngine->GetWorldContexts())
        {
                if (Context.ShouldApplyToWorldContext(WorldContext))
                {
                        AddToWorld(WorldContext, Context);
                }
        }
}

if (Context.ShouldApplyToWorldContext(WorldContext))
if (WorldContext.ContextHandle == WorldContextHandle)
        {
                return true;
        }

//不同类跳转到不同方法
void UGameFeatureAction_AddComponents::OnGameFeatureActivating(FGameFeatureActivatingContext& Context)
{
        FContextHandles& Handles = ContextHandles.FindOrAdd(Context);

        Handles.GameInstanceStartHandle = FWorldDelegates::OnStartGameInstance.AddUObject(this,
                &UGameFeatureAction_AddComponents::HandleGameInstanceStart, FGameFeatureStateChangeContext(Context));

        ensure(Handles.ComponentRequestHandles.Num() == 0);

        // Add to any worlds with associated game instances that have already been initialized
        for (const FWorldContext& WorldContext : GEngine->GetWorldContexts())
        {
                if (Context.ShouldApplyToWorldContext(WorldContext))
                {
                        AddToWorld(WorldContext, Handles);
                }
        }
}

void UGameFeatureAction_WorldActionBase::OnGameFeatureActivating(FGameFeatureActivatingContext& Context)
{
        GameInstanceStartHandles.FindOrAdd(Context) = FWorldDelegates::OnStartGameInstance.AddUObject(this,
                &UGameFeatureAction_WorldActionBase::HandleGameInstanceStart, FGameFeatureStateChangeContext(Context));

        // Add to any worlds with associated game instances that have already been initialized
        for (const FWorldContext& WorldContext : GEngine->GetWorldContexts())
        {
                if (Context.ShouldApplyToWorldContext(WorldContext))
                {
                        AddToWorld(WorldContext, Context);
                }
        }
}




角色射击:
断点ALyraGameMode::InitGame

  • 获取ExperienceId
void ALyraGameMode::HandleMatchAssignmentIfNotExpectingOne()
FPrimaryAssetId ExperienceId;
// see if the world settings has a default experience
        if (!ExperienceId.IsValid())
        {
                if (ALyraWorldSettings* TypedWorldSettings = Cast<ALyraWorldSettings>(GetWorldSettings()))
                {
                        ExperienceId = TypedWorldSettings->GetDefaultGameplayExperience();
                        ExperienceIdSource = TEXT("WorldSettings");
                }
        }

  • 服务器设置Experience
void ALyraGameMode::OnMatchAssignmentGiven(FPrimaryAssetId ExperienceId, const FString& ExperienceIdSource)
{
#if WITH_SERVER_CODE
        if (ExperienceId.IsValid())
        {
                UE_LOG(LogLyraExperience, Log, TEXT("Identified experience %s (Source: %s)"), *ExperienceId.ToString(), *ExperienceIdSource);

                ULyraExperienceManagerComponent* ExperienceComponent = GameState->FindComponentByClass<ULyraExperienceManagerComponent>();
                check(ExperienceComponent);
                ExperienceComponent->ServerSetCurrentExperience(ExperienceId);
        }
        else
        {
                UE_LOG(LogLyraExperience, Error, TEXT("Failed to identify experience, loading screen will stay up forever"));
        }
#endif
}
LogLyraExperience日志
LogLyraExperience: Identified experience LyraExperienceDefinition:B_BasicShooterTest (Source: WorldSettings)
LogLyraExperience: EXPERIENCE: StartExperienceLoad(CurrentExperience = LyraExperienceDefinition:B_BasicShooterTest, Server)
LogLyraExperience: EXPERIENCE: OnExperienceLoadComplete(CurrentExperience = LyraExperienceDefinition:B_BasicShooterTest, Server)最开始的日志
目录
Engine\Plugins\Experimental\BackChannel\Source\BackChannel\Private\Transport\BackChannelConnection.cpp
LogBackChannel: Listening on FBackChannelConnection Client Socket (localport: 2049)
Engine\Plugins\Experimental\RemoteSession\Source\RemoteSession\Private\RemoteSessionModule.cpp
LogRemoteSession: Started listening on port 2049断点UE_LOG(LogBackChannel, Log, TEXT("Listening on %s (localport: %d)")



  • 在Engine\Plugins\Experimental\RemoteSession\Source\RemoteSession\Public\RomoteSession.h中定义了virtual void InitHost(const int16 Port=0) = 0;
  • 查引用看堆栈dll-void FRemoteSessionModule::OnPIEStarted(bool bSimulating)-InitHost();
  • void FRemoteSessionModule::StartupModule()-PostPieDelegate = FEditorDelegates::PostPIEStarted.AddRaw(this, &FRemoteSessionModule::OnPIEStarted);
  • 2049是默认端口DefaultPort
断点void ULyraExperienceManagerComponent::StartExperienceLoad()-堆栈在dll里


将解决方案配置development edit改成DebugGame,启动报错-改成debuggame edit-可直接断点进入dll


//加载方法
const TSharedPtr<FStreamableHandle> BundleLoadHandle = AssetManager.ChangeBundleStateForPrimaryAssets(BundleAssetList.Array(), BundlesToLoad, {}, false, FStreamableDelegate(), FStreamableManager::AsyncLoadHighPriority);
//设置加载完成回调
FStreamableDelegate OnAssetsLoadedDelegate = FStreamableDelegate::CreateUObject(this, &ThisClass::OnExperienceLoadComplete);

TSharedPtr<FStreamableHandle> UAssetManager::ChangeBundleStateForPrimaryAssets
if (ReturnHandle->HasLoadCompleted())
                {
                        FStreamableHandle::ExecuteDelegate(DelegateToCall);
                }
加载插件
void ULyraExperienceManagerComponent::OnExperienceLoadComplete()
UGameFeaturesSubsystem::Get().LoadAndActivateGameFeaturePlugin(PluginURL, FGameFeaturePluginLoadComplete::CreateUObject(this, &ThisClass::OnGameFeaturePluginLoadComplete));
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|单击游戏交流网

Copyright © 2001-2013 Comsenz Inc.Template by Comsenz Inc.All Rights Reserved.

Powered by Discuz!X3.4

快速回复 返回顶部 返回列表