您的位置:首页 > 产品设计 > UI/UE

UE4无尽跑酷游戏制作杂记之二

2015-12-24 14:44 621 查看

UE4无尽跑酷游戏制作杂记之二

在做游戏的过程中,我先后犯了两个很愚蠢的错误,这个在我观看官方的无尽的奔跑者之后我意识到了这个错误。

首先在我原来的设计当中,我使用了一个单例类,或者说一个管理者类(继承自UObject)来管理整个的路途,叫做RoadManager,然后他持有游戏中所有的道路,我们每个道路都是在RoadManger中的道路队列下,每一帧我们窥探队列的首元素,然后判断它与玩家的距离是不是大于了两千,是的话就销毁它并且生成一个新的。这部分我们的代码如下:

代码如下,其余的实现我们在蓝图中继承覆盖。

void URoadManager:: tickTimeRoadCreate (){
AMyRoad * tempOut ;
if ( roadQueue .Peek ( tempOut)){
float distance = ( Owner-> GetActorLocation () - tempOut ->GetActorLocation ()). Size();
if ( distance > 2000){
roadQueue .Dequeue ( tempOut);
tempOut ->Destroy ();
tempOut = randomRoad(); //这里我们条用生成的函数,并且销毁我们之前生成的道路。
setRoadLocation (tempOut );
}


蓝色字体部分是我们对于游戏逻辑的判断是如上所说的,生成部分的代码如下:

AMyRoad * URoadManager :: randomRoad(){
float probability = FMath ::FRandRange ( 0, 1);
if ( probability < 0.8){
return currentWorld -> SpawnActor< AMyRoad >(roadOne );
}
else if (probability < 0.9){
return currentWorld -> SpawnActor< AMyRoad >(roadTwo );
}
else
{
return currentWorld -> SpawnActor< AMyRoad >(roadThree );
}
}


然而这样做无疑是低效的,我需要每一帧都监听我们主角与队列中道路的位置,一但我把主角删除,无疑我的程序一下就会出现很多的BUG

其实正确而高效的做法是我在RoadManager中将我们的生成新路径的代码写好,然后在每一段路线的尽头我都设置一个触发器,走到尽头后出发,通知roadManager调用。

(这里说个题外话,我发现4.92中原来调用OnComponentBeginOverlap的方式没有了,我似乎只会在蓝图中调用)

第二个错误是我没有用好GameMode模块,而是自己写了个管理器,我的管理器的很多操作应该在GameMode中进行的。

GameMode

*“AGameMode”类定义所玩的游戏,并执行游戏规则。“AGameMode”中的一些默认功能包括:

任何设定游戏规则的新函数或变量都应添加在“AGameMode”类的子类中。从玩家以什么库存道具开始,或有多少条命,到时间限制,以及结束游戏所需的分数都属于 GameMode。可以为游戏应包括的每个游戏类型创建“AGameMode”类的子类。一个游戏可以有任何数量的游戏类型,因此有任何数量的“AGameMode”类的子类;然而,在任何特定时间只可以使用一种游戏类型。每次通过“UGameEngine::LoadMap()”函数初始化一个游戏等级时都会实例化一个 GameMode Actor。该 Actor 定义的游戏类型将被用于该等级所持续的时间。

*

比赛状态

GameMode 包含监测比赛状态或整体游戏流程的状态机。要查询当前状态,你可以使用 GetMatchState,或诸如 HasMatchStarted、IsMatchInProgress 和 HasMatchEnded 的包装器。以下是可能的比赛状态:

EnteringMap 是初始状态。Actors 尚未开始计数,并且世界尚未完全初始化。当一切都完全加载后会过渡到下个状态。

WaitingToStart是下个状态,进入时调用 HandleMatchIsWaitingToStart。Actors开始计数,但尚未生成玩家。如果 ReadyToStartMatch 返回true,或如果有人调用 StartMatch,则过渡到下个状态。

InProgress 是下个状态,进入时调用 HandleMatchHasStarted,进而调用所有 Actors的 BeginPlay。普通游戏正在进行中。如果 ReadyToEndMatch 返回true,或如果有人调用 EndMatch,则过渡到下个状态。

WaitingPostMatch 是下个状态,进入时调用 HandleMatchHasEnded。Actors仍在计数,但不接受新玩家。当地图转换开始时过渡到下个状态。

LeavingMap是最后的状态,进入时调用HandleLeavingMap。在转至新地图时比赛停留在该状态。

Aborted 是故障状态,从 AbortMatch 开始。当存在不可恢复的错误时设置成该状态。

默认情况下,比赛状态几乎总为 InProgress。但个别游戏可以覆盖该行为,以构建有更复杂规则的多人游戏。

设置GameMode

有几种方法来设置某一等级的GameMode,以下按照从最低优先级到最高优先级的顺序:

在“DefaultGame.ini”文件中的“/Script/Engine.WorldSettings/”部分设置“GlobalDefaultGameMode”项`将为项目中的所有地图设置默认游戏模式。

[/Script/Engine.WorldSettings]GlobalDefaultGameMode="/Script/MyGame.MyGameGameMode"GlobalDefaultServerGameMode="/Script/MyGame.MyGameGameMode"


然后在GameMode中我可以使用

static ConstructorHelpers:: FClassFinder <APawn > PlayerPawnBPClass ( TEXT( "/Game/ThirdPersonCPP/Blueprints/ThirdPersonCharacter" ));
if ( PlayerPawnBPClass .Class != NULL )
{
DefaultPawnClass = PlayerPawnBPClass. Class ;
}
PlayerControllerClass = ABatteryCollectorPlayerController ::StaticClass ();


如下代码去初始化我们的游戏。

在GameMode 中我们同样有BeginPlay Tick等事件

World -> GetAuthGameMode()这个函数可以得打我们的游戏模式进而进行操纵。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: