六一的部落格


关关难过关关过,前路漫漫亦灿灿。



Kills & Deaths


说明

输出游戏角色击杀和死亡次数的统计数据


调整代码实现


移动STUGameModeBase源码路径

新路径
STUGameModeBase.cpp Private
STUGameModeBase.h Public



STUBaseWeapon中的GetPlayerController

  • 在STURifleWeapon::MakeDamage中调用过, 上一节中已屏蔽

    ShootThemUp: Weapon/STURifleWeapon.cpp
  • 在ASTUBaseWeapon::GetPlayerViewPoint中调用过, 改写

    ShootThemUp: Weapon/STUBaseWeapon.cpp
    1if (STUCharacter->IsPlayerController())
    2{
    3    // const auto Controller = GetPlayerController();
    4    const auto Controller = STUCharacter->GetController<APlayerController>();
    5    // ...
    6}

屏蔽GetPlayerController的声明与定义

ShootThemUp: Weapon/STUBaseWeapon.h

ShootThemUp: Weapon/STUBaseWeapon.cpp


在STURifleWeapon添加GetController接口

private

ShootThemUp: Weapon/STURifleWeapon.h

1AController* GetController() const;

ShootThemUp: Weapon/STURifleWeapon.cpp

1AController *ASTURifleWeapon::GetController() const
2{
3    const auto Pawn = Cast<APawn>(GetOwner());
4    return Pawn ? Pawn->GetController() : nullptr;
5}

在MakeDamage中使用

ShootThemUp: Weapon/STURifleWeapon.cpp

1/*
2  const auto Pawn = Cast<APawn>(GetOwner());
3  const auto Controller = Pawn->Controller;
4
5  DamagedActor->TakeDamage(DamageAmount, FDamageEvent(), Controller, this);
6*/
7
8DamagedActor->TakeDamage(DamageAmount, FDamageEvent(), GetController(), this);

每个游戏角色拥有击杀和死亡计数器

  1. 添加属性

    private

    ShootThemUp: Player/STUPlayerState.h
    1int32 KillsNum = 0;
    2int32 DeathsNum = 0;
  2. 添加计数和Get接口

    public

    ShootThemUp: Player/STUPlayerState.h
    1void AddKill() { ++KillsNum; }
    2void AddDeath() { ++DeathsNum; }
    3
    4int32 GetKillsNum() const { return KillsNum; }
    5int32 GetDeathsNum() const { return DeathsNum; }          
    
  3. 添加日志输出

    public

    ShootThemUp: Player/STUPlayerState.h
    1void LogInfo() const;
    ShootThemUp: Player/STUPlayerState.cpp
    1DEFINE_LOG_CATEGORY_STATIC(LogSTUPlayerState, All, All);
    2
    3void ASTUPlayerState::LogInfo() const
    4{
    5    UE_LOG(LogSTUPlayerState, Display, TEXT("TeamID: %i, Kills: %i, Deaths: %i"), TeamID, KillsNum, DeathsNum);
    6}

STUGameModeBase提供计数接口

  1. 击杀和死亡计数都由游戏角色死亡事件触发: 被击杀者增加死亡次数, 击杀者增加击杀次数
  2. 接口参数接受2个控制器: 来自击杀者和被击杀者

public

ShootThemUp: STUGameModeBase.h

1void Killed(AController *KillerController, AController *VictimController);

ShootThemUp: STUGameModeBase.cpp

 1void ASTUGameModeBase::Killed(AController *KillerController, AController *VictimController)
 2{
 3    if (!KillerController || !VictimController) return;
 4
 5    const auto KillerPlayerState = Cast<ASTUPlayerState>(KillerController->PlayerState);
 6    const auto VictimPlayerState = Cast<ASTUPlayerState>(VictimController->PlayerState);
 7
 8    if (KillerPlayerState)
 9    {
10        KillerPlayerState->AddKill();
11    }
12
13    if (VictimPlayerState)
14    {
15        VictimPlayerState->AddDeath();
16    }
17}

STUGameModeBase提供日志输出

一局结束后调用, 输出所有游戏角色击杀和死亡次数

private

ShootThemUp: STUGameModeBase.h

1void LogPlayerInfo();

ShootThemUp: STUGameModeBase.cpp

 1void ASTUGameModeBase::LogPlayerInfo()
 2{
 3    if (!GetWorld()) return;
 4
 5    for (auto It = GetWorld()->GetControllerIterator(); It; ++It)
 6    {
 7        const auto Controller = It->Get();
 8        if (!Controller) continue;
 9
10        const auto PlayerState = Cast<ASTUPlayerState>(Controller->PlayerState);
11        if (!PlayerState) continue;
12
13        PlayerState->LogInfo();
14    }
15}

一局结束后调用

ShootThemUp: STUGameModeBase.cpp

1// GameTimerUpdate
2
3UE_LOG(LogSTUGameModeBase, Display, TEXT("======= GAME OVER ======="));
4LogPlayerInfo();

健康组件添加辅助接口

private

ShootThemUp: Components/STUHealthComponent.h

1void Killed(AController *KillerController);

游戏角色死亡时调用: 需要伤害源Controller信息

ShootThemUp: Components/STUHealthComponent.cpp

1// OnTakeAnyDamage
2
3if (IsDead())
4{
5    Killed(InstigatedBy);
6    // ...
7}

实现

ShootThemUp: Components/STUHealthComponent.cpp

 1#include "STUGameModeBase.h"
 2
 3void USTUHealthComponent::Killed(AController *KillerController)
 4{
 5    const auto GameMode = Cast<ASTUGameModeBase>(GetWorld()->GetAuthGameMode());
 6    if (!GameMode) return;
 7
 8    const auto Pawn = Cast<APawn>(GetOwner());
 9    if (!Pawn) return;
10
11    GameMode->Killed(KillerController, Pawn->Controller);
12}

查看

  1. 设置关卡

    玩家个数为4, 回合时长为10s
  2. 设置步枪伤害为10

    BP_STURifleWeapon > Damage Amount

击杀和死亡计数


Kills & Deaths


说明

输出游戏角色击杀和死亡次数的统计数据


调整代码实现


移动STUGameModeBase源码路径

新路径
STUGameModeBase.cpp Private
STUGameModeBase.h Public



STUBaseWeapon中的GetPlayerController

  • 在STURifleWeapon::MakeDamage中调用过, 上一节中已屏蔽

    ShootThemUp: Weapon/STURifleWeapon.cpp
  • 在ASTUBaseWeapon::GetPlayerViewPoint中调用过, 改写

    ShootThemUp: Weapon/STUBaseWeapon.cpp
    1if (STUCharacter->IsPlayerController())
    2{
    3    // const auto Controller = GetPlayerController();
    4    const auto Controller = STUCharacter->GetController<APlayerController>();
    5    // ...
    6}

屏蔽GetPlayerController的声明与定义

ShootThemUp: Weapon/STUBaseWeapon.h

ShootThemUp: Weapon/STUBaseWeapon.cpp


在STURifleWeapon添加GetController接口

private

ShootThemUp: Weapon/STURifleWeapon.h

1AController* GetController() const;

ShootThemUp: Weapon/STURifleWeapon.cpp

1AController *ASTURifleWeapon::GetController() const
2{
3    const auto Pawn = Cast<APawn>(GetOwner());
4    return Pawn ? Pawn->GetController() : nullptr;
5}

在MakeDamage中使用

ShootThemUp: Weapon/STURifleWeapon.cpp

1/*
2  const auto Pawn = Cast<APawn>(GetOwner());
3  const auto Controller = Pawn->Controller;
4
5  DamagedActor->TakeDamage(DamageAmount, FDamageEvent(), Controller, this);
6*/
7
8DamagedActor->TakeDamage(DamageAmount, FDamageEvent(), GetController(), this);

每个游戏角色拥有击杀和死亡计数器

  1. 添加属性

    private

    ShootThemUp: Player/STUPlayerState.h
    1int32 KillsNum = 0;
    2int32 DeathsNum = 0;
  2. 添加计数和Get接口

    public

    ShootThemUp: Player/STUPlayerState.h
    1void AddKill() { ++KillsNum; }
    2void AddDeath() { ++DeathsNum; }
    3
    4int32 GetKillsNum() const { return KillsNum; }
    5int32 GetDeathsNum() const { return DeathsNum; }          
    
  3. 添加日志输出

    public

    ShootThemUp: Player/STUPlayerState.h
    1void LogInfo() const;
    ShootThemUp: Player/STUPlayerState.cpp
    1DEFINE_LOG_CATEGORY_STATIC(LogSTUPlayerState, All, All);
    2
    3void ASTUPlayerState::LogInfo() const
    4{
    5    UE_LOG(LogSTUPlayerState, Display, TEXT("TeamID: %i, Kills: %i, Deaths: %i"), TeamID, KillsNum, DeathsNum);
    6}

STUGameModeBase提供计数接口

  1. 击杀和死亡计数都由游戏角色死亡事件触发: 被击杀者增加死亡次数, 击杀者增加击杀次数
  2. 接口参数接受2个控制器: 来自击杀者和被击杀者

public

ShootThemUp: STUGameModeBase.h

1void Killed(AController *KillerController, AController *VictimController);

ShootThemUp: STUGameModeBase.cpp

 1void ASTUGameModeBase::Killed(AController *KillerController, AController *VictimController)
 2{
 3    if (!KillerController || !VictimController) return;
 4
 5    const auto KillerPlayerState = Cast<ASTUPlayerState>(KillerController->PlayerState);
 6    const auto VictimPlayerState = Cast<ASTUPlayerState>(VictimController->PlayerState);
 7
 8    if (KillerPlayerState)
 9    {
10        KillerPlayerState->AddKill();
11    }
12
13    if (VictimPlayerState)
14    {
15        VictimPlayerState->AddDeath();
16    }
17}

STUGameModeBase提供日志输出

一局结束后调用, 输出所有游戏角色击杀和死亡次数

private

ShootThemUp: STUGameModeBase.h

1void LogPlayerInfo();

ShootThemUp: STUGameModeBase.cpp

 1void ASTUGameModeBase::LogPlayerInfo()
 2{
 3    if (!GetWorld()) return;
 4
 5    for (auto It = GetWorld()->GetControllerIterator(); It; ++It)
 6    {
 7        const auto Controller = It->Get();
 8        if (!Controller) continue;
 9
10        const auto PlayerState = Cast<ASTUPlayerState>(Controller->PlayerState);
11        if (!PlayerState) continue;
12
13        PlayerState->LogInfo();
14    }
15}

一局结束后调用

ShootThemUp: STUGameModeBase.cpp

1// GameTimerUpdate
2
3UE_LOG(LogSTUGameModeBase, Display, TEXT("======= GAME OVER ======="));
4LogPlayerInfo();

健康组件添加辅助接口

private

ShootThemUp: Components/STUHealthComponent.h

1void Killed(AController *KillerController);

游戏角色死亡时调用: 需要伤害源Controller信息

ShootThemUp: Components/STUHealthComponent.cpp

1// OnTakeAnyDamage
2
3if (IsDead())
4{
5    Killed(InstigatedBy);
6    // ...
7}

实现

ShootThemUp: Components/STUHealthComponent.cpp

 1#include "STUGameModeBase.h"
 2
 3void USTUHealthComponent::Killed(AController *KillerController)
 4{
 5    const auto GameMode = Cast<ASTUGameModeBase>(GetWorld()->GetAuthGameMode());
 6    if (!GameMode) return;
 7
 8    const auto Pawn = Cast<APawn>(GetOwner());
 9    if (!Pawn) return;
10
11    GameMode->Killed(KillerController, Pawn->Controller);
12}

查看

  1. 设置关卡

    玩家个数为4, 回合时长为10s
  2. 设置步枪伤害为10

    BP_STURifleWeapon > Damage Amount