原文地址:https://blog.maide.ca/2016/02/26/ue4-persisting-users-across-disconnects/
虽然现代互联网允许游戏玩家在世界各地相互连接,但互联网有时并不像我们希望的那样稳定。在基于互联网的游戏过程中会出现断线,如果您在游戏中没有计划,那么您的玩家就会受到影响。值得庆幸的是,UE4有你的支持,并且非常容易支持在重新连接后大致恢复中断状态。它并不完美,但对大多数游戏来说可能都足够好。让我们深入探讨如何为您的游戏设置此功能。在本节中,假设您在下一节中已经基本掌握了C ++,但是通过在PlayerState的EventGraph中实现列出的函数的覆盖,可以在Blueprint中实现大多数这些系统。
当玩家从游戏服务器断开连接时,他们的PlayerState对象将从PlayerArray
GameState上移除,然后创建一个副本并将其添加到GameMode 1直观上叫做InactivePlayerArray
的数组中。完成此复制后,将销毁原始PlayerState。
当同一玩家重新连接时,UE4将尝试匹配2它们与存储在一个PlayerState InactivePlayerArray
。如果匹配,UE4将使用存储的PlayerState而不是使用创建新的玩家的PlayerState。
你还记得当我提到UE4在播放器断开连接时制作PlayerState的副本吗?嗯,这只是片面的。默认情况下,UE4只会复制一些变量,例如PlayerName
,PlayerId
,Score
,UniqueNetId
等等。不幸的是,这个过程不会处理你的游戏的自定义变量。值得庆幸的是,我们有办法深入了解这个过程并复制我们想要保留的变量。
让我们假设我们已经使用一些自定义成员变量为我们的游戏定义了自己的PlayerState:
// MyPlayerState.h
UCLASS()
class AMyPlayerState: public APlayerState
{
GENERATED_BODY()
public:
/** The amount of kills this player has */
UPROPERTY(Transient, Replicated, BlueprintReadWrite)
int32 Kills;
/** The amount of deaths this player has */
UPROPERTY(Transient, Replicated, BlueprintReadWrite)
int32 Deaths;
/** The amount of money this player has */
UPROPERTY(Transient, Replicated, BlueprintReadWrite)
int32 Money;
/** The hero the player has selected to (re)spawn as */
UPROPERTY(Transient, Replicated, BlueprintReadWrite)
TSubclassOf<APawn> SelectedHero;
public:
// Class methods Here...
};
默认情况下,播放器断开连接后,这些属性都不会保留。要解决此问题,我们需要在头文件MyPlayerState.h
中定义一个叫CopyProperties(APlayerState*)
的函数。
virtual void CopyProperties(APlayerState* NewPlayerState) override;
一旦我们在头文件中定义了它,我们就必须在我们的MyPlayerState.cpp
文件中添加我们的实现。这可能类似于以下内容:
// MyPlayerState.cpp
void AMyPlayerState::CopyProperties(APlayerState* NewPlayerState)
{
Super::CopyProperties(NewPlayerState);
AMyPlayerState* MyNewPlayerState = Cast<AMyPlayerState>(NewPlayerState);
if (MyNewPlayerState)
{
MyNewPlayerState->Kills = Kills;
MyNewPlayerState->Deaths = Deaths;
MyNewPlayerState->Money = Money;
}
}
在这个例子中,我们复制最开始的三个成员,Kills
,Deaths
,和Money
,但没有复制SelectedHero
属性,所以玩家将需要设置以下正常游戏流程。
我们需要确保遵循更多步骤,否则我们将在服务器决定更改地图时遇到问题。在无缝服务器传输期间,PlayerState值将被复制并保留到下一个映射。为此,它使用我们先前覆盖的相同的函数,CopyProperties(APlayerState*)
。根据您的游戏,您可能希望其中一些值保持不变,但您可能希望至少其中一些值被重置,并且我们将重置!
我们将定义另一种方法,在SeamlessTravel过程中调用,命名Reset()
。在我们的头文件中MyPlayerState.h
,它将如下所示:
virtual void Reset() override;
我们MyPlayerState.cpp
文件中的实现将如下所示:
void AMyPlayerState::Reset()
{
Super::Reset();
Kills = 0;
Deaths = 0;
Money = 800;
SelectedHero = nullptr;
}
这会将我们的所有值重置为默认值,并允许我们在新地图上重新开始。
值得注意的是,InactivePlayerArray
will只存储每个PlayerState一段特定的时间。在GameMode基类中的这个时间的默认值为300秒,但您可以通过设置GameMode中InactivePlayerStateLifeSpan
的值来将这个时间设置为您期望的任何值。该值是PlayerState从断线开始到设置为非活动状态的秒数。您还可以将此值设置为“0”以禁用此行为。如果玩家过后依然未重新连接,则其存储状态将自动销毁。
好吧,关于这个问题。如果您有任何问题或意见,请随时在下面发表评论。谢谢阅读!
笔记