一、......
1.在PlayerController类通过UGameplayStatics::GetGameState可以获得游戏状态AGameState类和子类,通过GetPlayerState可以获得APlayerState和子类
2.在GameMode类中通过GetGameState获得GameState和子类
3.在GameMode类中存在比赛状态的命名控件namespace MatchState,想添加新的比赛状态在GameMode的子类中模仿GameMode类在头文件和源文件添加方式添加
4.PlayerState中GetPlayerName函数获得的时Steam上的名字
二、添加GameState类
1.新建类
2. 代码
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameState.h"
#include "BlasterGameState.generated.h"
/**
*
*/
UCLASS()
class BLASTER_API ABlasterGameState : public AGameState
{
GENERATED_BODY()
public:
virtual void GetLifetimeReplicatedProps(TArray< FLifetimeProperty >& OutLifetimeProps) const override;
void UpdateTopScore(class ABlasterPlayerState* ScoringPlayer);
UPROPERTY(Replicated)
TArray<ABlasterPlayerState*> TopScoringPlayers;
private:
float TopScore;
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "BlasterGameState.h"
#include "Net/UnrealNetwork.h"
#include "Blaster/PlayerState/BlasterPlayerState.h"
void ABlasterGameState::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(ABlasterGameState, TopScoringPlayers);
}
void ABlasterGameState::UpdateTopScore(ABlasterPlayerState* ScoringPlayer)
{
if (TopScoringPlayers.Num() == 0)
{
TopScoringPlayers.Add(ScoringPlayer);
TopScore = ScoringPlayer->GetScore();
}
else if (ScoringPlayer->GetScore() == TopScore)
{
TopScoringPlayers.AddUnique(ScoringPlayer);
}
else if (ScoringPlayer->GetScore() > TopScore)
{
TopScoringPlayers.Empty();
TopScoringPlayers.AddUnique(ScoringPlayer);
TopScore = ScoringPlayer->GetScore();
}
}
三、创建游戏结束的界面
2. 代码
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Announcement.generated.h"
/**
*
*/
UCLASS()
class BLASTER_API UAnnouncement : public UUserWidget
{
GENERATED_BODY()
public:
UPROPERTY(meta = (Bindwidget))
class UTextBlock* AnnouncementText;
UPROPERTY(meta = (Bindwidget))
UTextBlock* InfoText;
UPROPERTY(meta = (Bindwidget))
UTextBlock* WarmupTime;
};
3. 在HUD类中添加新界面类的变量和函数
UPROPERTY(EditAnywhere, Category = "Announcements")
TSubclassOf<UUserWidget> AnnouncementClass;
UPROPERTY()
class UAnnouncement* Announcement;
void AddAnnouncement();
void AABasterHUD::AddAnnouncement()
{
APlayerController* PlayController = GetOwningPlayerController();
if (PlayController && AnnouncementClass)
{
Announcement = CreateWidget<UAnnouncement>(PlayController, AnnouncementClass);
Announcement->AddToViewport();
}
}
4.在PlayerController中实现HandleCool函数中实现在界面上显示的功能
private:
UPROPERTY(ReplicatedUsing = OnRep_MatchState)
FName MatchState;
UFUNCTION()
void OnRep_MatchState();
void ABlasterPlayerController::OnMatchStateSet(FName State)
{
MatchState = State;
if (MatchState == MatchState::InProgress)
{
HandleMatchHasStarted();
}
else if (MatchState == MatchState::Cooldown)
{
HandleCooldown();
}
}
void ABlasterPlayerController::OnRep_MatchState()
{
if (MatchState == MatchState::InProgress)
{
HandleMatchHasStarted();
}
else if (MatchState == MatchState::Cooldown)
{
HandleCooldown();
}
}
void ABlasterPlayerController::HandleMatchHasStarted()
{
BlasterHUD = BlasterHUD == nullptr ? Cast<AABasterHUD>(GetHUD()) : BlasterHUD;
if (BlasterHUD)
{
BlasterHUD->AddCharacterOverlay();
if (BlasterHUD->Announcement)
{
BlasterHUD->Announcement->SetVisibility(ESlateVisibility::Hidden);
}
}
}
void ABlasterPlayerController::HandleCooldown()
{
BlasterHUD = BlasterHUD == nullptr ? Cast<AABasterHUD>(GetHUD()) : BlasterHUD;
if (BlasterHUD)
{
BlasterHUD->CharacterOverlay->RemoveFromParent();
bool bHUDValid = BlasterHUD->Announcement&&
BlasterHUD->Announcement->AnnouncementText&&
BlasterHUD->Announcement->InfoText;
if (bHUDValid)
{
BlasterHUD->Announcement->SetVisibility(ESlateVisibility::Visible);
FString AnnouncementText("New Match Starts In:");
BlasterHUD->Announcement->AnnouncementText->SetText(FText::FromString(AnnouncementText));
ABlasterGameState* BlasterGameState = Cast<ABlasterGameState>(UGameplayStatics::GetGameState(this));
ABlasterPlayerState* BlasterPlayerState = GetPlayerState<ABlasterPlayerState>();
if (BlasterGameState && BlasterPlayerState)
{
TArray<ABlasterPlayerState*> TopPlayers = BlasterGameState->TopScoringPlayers;
FString InfoTextString;
if (TopPlayers.Num() == 0)
{
InfoTextString = FString("There is no Winner");
}
else if (TopPlayers.Num() == 1 && TopPlayers[0] == BlasterPlayerState)
{
InfoTextString = FString("You are Winner");
}
else if(TopPlayers.Num() == 1)
{
InfoTextString = FString::Printf(TEXT("Winner: \n%s"),*TopPlayers[0]->GetPlayerName());
}
else if(TopPlayers.Num() > 1)
{
InfoTextString = FString::Printf(TEXT("Winner: \n%s"), *TopPlayers[0]->GetPlayerName());
for (auto TiedPlayer : TopPlayers)
{
InfoTextString.Append(FString::Printf(TEXT("%s\n"),*TiedPlayer->GetPlayerName()));
}
}
BlasterHUD->Announcement->InfoText->SetText(FText::FromString(InfoTextString));
}
}
}
ABlasterCharacter* BasterCharacter = Cast<ABlasterCharacter>(GetPawn());
if (BasterCharacter && BasterCharacter->GetCombat())
{
BasterCharacter->bDisableGameplay = true;
BasterCharacter->GetCombat()->FireButtonPressed(false);
}
}
5.重新启动游戏如果当前状态时Cooldown判断当前比赛时间是否结束,重新启动游戏
namespace MatchState
{
extern BLASTER_API const FName Cooldown;// 到达了比赛持续时间,展示获胜者并开始冷却时间
}
else if (MatchState == MatchState::Cooldown)
{
CountdownTime = CooldownTime + WarmupTime + MatchTime - GetWorld()->GetTimeSeconds() + LevelStartintTime;
if (CountdownTime < 0.f)
{
RestartGame();
}
}
namespace MatchState
{
const FName Cooldown = FName(TEXT("Cooldown"));
}