通过Script看Unreal3的完整流程

UnrealScript Game Flow通过ScriptUnreal3的完整流程

 

注,此篇转自UDN,谨以学习之用,俗话说,好记性不如烂笔头,多码码字,加上实践,效果远胜于纸上谈兵~

通过Script脚本的流程分析Unreal3游戏的整体流程,及配合前一篇《Unreal角色技术指南》,通读之后想必一定可以对UN的编程体系会有更加深入的理解~

PSUDN上的CNTutorialEn版比起来还是有相当大的区别的,所以,勤劳些,稍微多费点力,多看原版的~

  • UnrealScript Game Flow

    • Overview

    • Startup Movies

    • Map Load

      • Entry Map

        • Main Menu

      • Loading screen

    • Game Startup

    • Game Init

      • PreBeginPlay

      • PostBeginPlay

      • Player Creation

      • Match Start

    • End Game

Overview综视


The flow of a game in Unreal Engine 3 may be unfamiliar to programmers coming from other disciplines or simply not familiar with how Unreal Engine 3 works. The goal of this document is to outline the flow within the game and point out the important functions that are used to facilitate that flow, and which are useful for customizing the game to fit your needs.

The general flow of events is:

+ The engine is initialized

|--+ The engine loads a map

   |--- The gametype is set

   |--+ Gameplay is initialized

   |  |--- GameInfo:InitGame() is called to initialize the gametype

   |  |--- Actor::PreBeginPlay() is called to initialize all Actors

   |  |--- Actor::PostBeginPlay() is called to initialize all Actors

   |--+ A Player joins

      |--- GameInfo::Login() is called on the gametype to handle spawning the player

      |--- GameInfo::PostLogin() is called on the gametype to handle the new player

事件的一般流程如下所示:

+ 初始化引擎<?xml:namespace prefix = o />
|--+ 引擎加载地图<?xml:namespace prefix = o />
   |--- 设置游戏类型<?xml:namespace prefix = o />
   |--+ 初始化游戏性<?xml:namespace prefix = o />
   |  |--- 调用 GameInfo:InitGame() 初始化游戏类型<?xml:namespace prefix = o />
   |  |--- 调用 Actor::PreBeginPlay() 初始化所有 Actor<?xml:namespace prefix = o />
   |  |--- 调用 Actor::PostBeginPlay() 初始化所有 Actor<?xml:namespace prefix = o />
   |--+ 玩家加入<?xml:namespace prefix = o />
      |--- 在游戏类型上调用 GameInfo::Login(),控制生成该玩家。<?xml:namespace prefix = o />
      |--- 在游戏类型上调用 GameInfo::PostLogin(),控制这个新玩家<?xml:namespace prefix = o />

clip_image002

Startup Movies开始动画


When the engine starts up, it displays a series of startup movies. These generally include the "Powered by Unreal" movie, the "Epic Games" movie, etc., and additional movies can be added as well. The startup movies are fullscreen videos (.bik) specified by the StartupMovies array specified in the FullScreenMovie] section of the DefaultEngine.ini file.

[FullScreenMovie]

+StartupMovies=UDKFrontEnd.udk_loading

Map Load家在地图


All gameplay and interaction in Unreal Engine 3 takes place within a map. When the engine starts up, it always loads a map. The process of loading a map kicks off a series of events that not only opens a new map, but also loads and initializes a new gametype and then starts the match.

虚幻引擎 3 中的所有游戏性和交互活动都在地图中进行。引擎启动后,它通常会加载一个地图。加载地图的过程会触发一系列事件,这些事件不只会打开一个新的地图,还会加载并初始化一个新的游戏类型,然后开始比赛。

Entry Map 初始地图

The map that loads up when the game starts can be specified on the command line or, if no map is specified, a default map is loaded. In general, no map will be specified, allowing the default map, or entry map, to load.

The default map is specified in the DefaultEngine.ini file in the [URL] section.

在游戏开始时加载的地图可以通过命令行指定,如果没有指定要加载的地图,那么加载默认地图。通常,不会指定地图,允许加载默认地图或入口地图。

默认地图在 [URL] 部分的 DefaultEngine.ini 文件中指定。

 

[URL]

Map=UDKFrontEndMap.udk

This is generally a very simple map with a player start that is not meant to host gameplay, but to load the main menu for the game. The entirety of the UDKFrontEndMap.udk map is shown below:

clip_image003

Main Menu 主菜单

There is no special functionality that forces the game to force a specific menu to be used as the main menu or to force the game startup into a main menu. As was mentioned briefly above, it is the job of the map that is loaded at startup to load the main menu.

This allows for great flexibility and control over how the game starts up. For example, one game may simply startup and show the main menu immediately, while another game could startup showing a cinematic that transitions into the main menu, and yet another game may allow a brief bit of gameplay preceding the displaying of the menu. In fact, the game could even skip the idea of a main menu altogether if that was desired.

The menu is opened using Kismet. An example of Kismet for loading the main menu from the UDKFrontEndMap.udk map is show here:

主菜单

这里没有可以强制游戏强行将指定菜单作为主菜单使用或强制游戏启动进入主菜单的特殊功能。正如上面简明描述的一样,启动时加载的地图就是为了加载主菜单。

它的灵活性非常强,可以控制游戏的启动方式。例如,一个游戏可以轻松启动,然后立即显示主菜单,而另一个游戏可以在启动的时候显示一个可以转换为主菜单的过场动画,但是另一个游戏可以在显示菜单之前进行一段时间的游戏。事实上,如果需要游戏甚至可以略过主菜单。

使用 Kismet 打开这个菜单。用于加载 UDKFrontEndMap.udk 地图中的主菜单的 Kismet 示例如下所示:

clip_image004

Loading screen加载屏幕

Any transition from one map to another causes a loading screen to be displayed. The loading screen is actually a fullscreen video (.bik) chosen at random from the LoadMapMovies array specified in the FullScreenMovie] section of the DefaultEngine.ini file.

[FullScreenMovie]

+LoadMapMovies=UDKFrontEnd.udk_loading

Game Startup游戏启动


In Unreal, the term "game" gets used a lot to mean different things. In this instance, game refers to the gameplay and events that occur after the loading of a new map.

Game Init游戏初始化

The InitGame() event of the current GameInfo is called before any other scripts are executed, including all Actors' PreBeginplay() events. This is mainly for the gametype to set up its own parameters and spawn any helper classes needed.

event InitGame( string Options, out string ErrorMessage )

在执行任何其他脚本之前调用当前 GameInfo  InitGame() 事件,其中包括所有 Actor  PreBeginplay() 事件。它主要供游戏类型设置它自己的参数并生成需要的任何辅助类。

PreBeginPlay 预载

The PreBeginPlay() event is the first script function called on the Actor after execution of the Actor's script has begin. Its name implies it is called before gameplay begins, which is the case if the Actor exists when the game starts up. If the Actor is spawned during play, this event is still called even though gameplay has already begun. Very specialized initialization could be performed here, but keep in mind that the Actor's components have not been initialized at this point and there is no reliable way to ensure that any external object has been initialized either.

PreBeginPlay() 事件是开始执行 Actor 的脚本之后在 Actor 上调用的第一个脚本函数。它的名称表明它要在游戏开始之前进行调用,如果在游戏启动的时候这个 Actor 存在,那么就会是这种情况。如果在游戏过程中生成 Actor,那么就算游戏已经开始还是会调用该事件。可以在这里进行非常特殊的初始化过程,但是请记住此时还没有初始化该 Actor 的组件,而且没有可靠的方法可以确保所有外部对象已经进行初始化。

event PreBeginPlay()

PostBeginPlay 后置处理

The PostBeginPlay() event is called after all other Actors have been initialized, via their PreBeginPlay() events. This event is generally used to initialize properties, find references to other Actors in the world, and perform any other general initialization. It is fair to consider this event the script equivalent of a constructor for Actors. Even so, there are still some things that require using specialized events available in the Actor to initialize. For instance, initialization having to do with animations and the AnimTree would best be performed in the PostInitAnimTree()event as that is called after the AnimTree is created and initialized. There are many such events provided for doing this type of specialized initialization. It is best to search for these first before adding specific initialization functionality to the PostBeginPlay() event.

在通过所有其他 Actor  PreBeginPlay() 事件初始化它们后调用 PostBeginPlay() 事件。该事件通常用于初始化属性,在世界中查找对其他 Actor 的引用,并执行任何其他通用初始化。我们可以这么认为,这个事件是与 Actor 的构造函数等价的脚本。 即便如此,还是要初始化一些需要使用 Actor 中提供的特殊事件的函数。例如,与动画相关的初始化和 AnimTree 最好在 PostInitAnimTree() 事件中执行,因为在创建并初始化 AnimTree 后会调用它。这里提供了很多这样的事件以进行此类特殊初始化。在将指定初始化功能添加到 PostBeginPlay() 事件前,最好首先搜索这些事件。

event PostBeginPlay()

Player Creation创建玩家

Player creation is handled inside the gametype (e.g., the GameInfo class) through the process of logging in. In the context of networked online multiplayer games, this concept should make perfect sense. Unreal utilizes the same basic process regardless of whether the game is online, offline, multiplayer, or single-player, though obviously there are additional actions being carried out in an online situation.

The login process is broken up into several stages:

  • PreLogin

  • Login

  • PostLogin

The PreLogin() event is called from native code and is responsible for determining whether the player is allowed to join the game. It uses theAccessControl object of the gametype to determine whether the player can join by calling its PreLogin() function.

event PreLogin(string Options, string Address, out string ErrorMessage)

The Login() event is called from native code and is responsible for spawning the player. Any specialized functionality needed for creating new players should be added here.

event PlayerController Login(string Portal, string Options, const UniqueNetID UniqueID, out string ErrorMessage)

The PostLogin() event is called from native code after the player has successfully joined the game. This is a good place to do player initialization and is a safe place to call replicated functions on the PlayerController.

event PostLogin( PlayerController NewPlayer )

Match Start游戏开始

The actual game, as in the gameplay that happens from the time the player is spawned until the game ends, is often referred to as a match. This is just a term and has no bearing on the type of games that can be created with Unreal Engine 3.

The match is begun when the StartMatch() function of the gametype is called from the PostLogin() event (also called from StartMatch() andStartArbitratedMatch() in the PendingMatch state). This function is responsible for spawning the player's Pawns and notifying all of the players that the match has begun.

在从 PostLogin() 事件中调用游戏类型的 StartMatch() 函数(同时可以从 PendingMatch 声明中的 StartMatch()  StartArbitratedMatch() 中进行调用)时开始比赛。整个函数主要负责生成玩家的 Pawns 然后通知所有玩家比赛已经开始。

function StartMatch()

The actual spawning of the players' Pawns occurs in the RestartPlayer() function. This is called from the StartHumans() and StartBots() functions, which are in turn called from the StartMatch() function. In addition to spawning the Pawns, this function locates a starting spot, e.g. a PlayerStartActor, to start the player from.

玩家 Pawns 的实际生成过程是在 RestartPlayer() 函数中进行的。通过 StartHumans()  StartBots() 函数调用它,而这两个函数可以通过 StartMatch() 函数进行调用。除了生成 Pawns 外,这个函数可以定位起点,例如玩家开始的 PlayerStart Actor

function RestartPlayer(Controller NewPlayer)

End Game游戏结束


The gametype is responsible for determining if the game has ended. This is not some automatic check that happens at set intervals or is initiated by the engine, though. It is the responsibility of the game-relevant Actors to notify the gametype when important events occur so that it can check to see if that event should result in the game ending. These checks are usually performed in specialized functions added to subclasses of GameInfo. For example, the UTGame gametype has a CheckScore() function which gets called anytime a player gets killed to check to see if that kill should end the game. When one of these functions determines the game should end, that function then calls the EndGame()function, which in turn calls CheckEndGame(). These functions make sure the game can end and then perform the actions associated with ending the current gametype.

In the example of an adventure role-playing game, when the player is in a dungeon and the boss is defeated or the objective is completed, the boss or the objective would notify the gametype it had been killed or completed, respectively. The gametype would then check to be sure that all end gamed conditions had been completed. If the end game condition have indeed been completed, the gametype calls EndGame() to perform the appropriate actions for ending the game: sending the player back to the main world and recording that the dungeon had been completed in one manner or another. In the main world, the gametype would load the player's progress, which might be the dungeons completed by the player, and then check to see if all end game conditions have been met. If the conditions have been met, that gametype would then call its EndGame() to initiate the appropriate actions for the game being over.

Obviously, this is just an example and every game will have different rules, flow, and conditions for ending the game, but the idea should be clear.

游戏类型主要负责确定游戏是否已经结束。但是它不是固定时间间隔进行或者由引擎初始化的自动检查。游戏相关 Actor 的职责是在重要事件发生的时候通知游戏类型,这样它才可以检查看看该事件是否会使游戏结束。这些检查通常是在添加到 GameInfo 子类的特殊函数中进行。例如, UTGame 游戏类型具有一个 CheckScore()函数,每次玩家死亡的时候都会调用这个函数检查看看这次死亡是否应该结束游戏。其中某个函数可以确定游戏应该结束后,该函数会调用 EndGame() 函数,而它会调用 CheckEndGame() 。这些函数可以确保游戏结束,然后执行与结束当前游戏类型相关的操作。

在这个冒险类角色扮演游戏示例中,当玩家在地下城中击败大怪或完成目标的时候,大怪或目标将会分别通知游戏类型已经击败大怪或完成目标。接下来游戏类型将会检查确保已经满足所有结束游戏的条件。如果结束游戏条件确实已经满足,那么游戏类型会调用 EndGame() 执行相应操作结束游戏: 将玩家送回主要世界并记录已经完成地下城关卡(通过任何方式)。在主要世界中,游戏类型将会加载玩家的进度,可能是玩家完成的地下城关卡,然后检查看看是否满足所有结束游戏的条件。如果条件已经满足,那么该游戏类型会调用它的 EndGame() ,初始化游戏结束时需要进行的相应操作。

显然,这只是个例子,对于结束游戏,每个游戏都会有不同的规则、流程和条件,但是其中的原理应该是一样的。

 

 

posted @ 2012-02-10 11:00  Zephyroal  阅读(1508)  评论(0编辑  收藏  举报