Epic Verse 语法介绍 

认真看了一下 Inside Unreal:2020 Year In Review 里展示的 Epic Verse 代码,看起来新的脚本语言很像 pascal 和Python的结合体,而且还有点 ruby 味,Verse 具有静态类型,某些语法与 SkookumScript 非常像。

2019 年初 Epic 收购了Agog Labs (and SkookumScript),应该是要来打造 UE5 的脚本语言,所以 UE5 的语法结构和 SkookumScript 比较像应该是比较合理的,根据视频里的展示情况,我认为 UE5 的脚本语言应该就是 Agog Labs 做的。

但是这场展示中并没有展示该脚本语言如何与引擎进行交互,也没有展示引擎中的符号信息,与 C++ 的交互方式目前只能观望。目前介绍一下视频里有展示的语言内容。

视频展示的代码如下:




手敲了遍文本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# This is a BoxFight prototype game.
BoxFight=class(FortGameScriptBase):
    GameStarted^: bool=false 
    GameEnded^: bool=false 
    CurrentRound^: int=0
    RunGame()
        # Pause until all players in the matchmaking session
        # have connected to the server.
        MaitForPlayersToJoin()

        # Start the game.
        GameStarted := true 
        for(i = 1..NumberofRounds):

            # Perform round setup.
            currentRound := i
            EnableBarriers()
            SetBuildingDisallowed()
            if(!SetupPlayersAndSpawnPoints()?):

                # We hit an error and are unable to start the round.
                ShutdownGame()
                return

            else:
                # Begin the round start countdown.
                Players.PutAllInStasisAllowEmotes()
                Players.SetAllInvulnerable(true)
                SimpleUI.ShowcountDown(7)
                Wait(2)

                # Enable building at the end of the countdown.
                SimpleUI.ShowMessage("Building Enabled")
                SetBuildingAllowed()
                Players.RemoveAllFromStasis()
                Players.SetAllInRound()
                # Wait for the start countdown to complete.
                Wait(4.7)
                SimpleUI.HideMessage()
                # Begin combat and initialize the storm.

                Players.SetAllInvulnerable(false)
                DisableBarriers()

                # Hide the round start after it's had a second to display.
                Wait(1.3)
                simpleUI.HideCountDown()
                Storm.Startstorm(60.0, CurrentRound^)

                #Wait for the round end conditions 
                if(IsSoloGame()?):
                    race:
                        #Setup Solo specific end conditions for testing
                        WaitForZeroRemaining()
                        WaitForRoundTimeout()
                else:
                    race:
                        # Setup Solo specific end conditions for testing
                        WaitForOneRemaining()
                        WaitForZeroRemaining()
                        WaitForRoundTimeout()
                
                # Handle round complete.
                # Give everyone a quick completion message.
                SimpleUI.ShowMessage("Round Complete")
                Wait(2.0)

                # Disable combat and the storm.
                SimpleUI.HideMessage()
                Players.PutAllInstasisAllowEmotes()
                Players.SetAllInvulnerable(true)
                SetBuildingDisallowed()
                Storm.stopstorm()
                Players.SetAllEndRound()
                
                # Display the scoreboard.

class 定义 

首先是 class 定义(暂且标记为继承形式):

1
BoxFight = class(FortGameScriptBase):

变量声明

具有静态类型,并且无需;

1
2
GameStarted^: bool = false
CurrentRound^: int = 0

变量赋值

类似与 pascal 语言(SkookumScript 也是如此)

1
GameStarted := 1

代码块 

类似于 Python 的缩进,需要使用 : 标识:

1
2
3
4
5
6
7
8
if(!SetupPlayerAndSpwanPoints()?):
    ShutdownGame()
    return
else:
    Players.PutAllInStasisAllowEmotes()
    Players.SetAllInvulnerable(true)
    SimpleUI.ShowcountDown(7)
    Wait(2)

?在 SkookumScript 是谓词,只能够应用到 boolean 的对象。在 SkookumScript 的文档中介绍是可选的,用于标识返回值为布尔类型:

Optional ‘?’ used as convention to indicate predicate variable or method of return type Boolean (true or false). 

循环语句 

整型迭代:

1
for(i = 1..NumberOfRounds):

这个形式有点类似于 ruby 语言里的 for:

1
for i in 0..100 do

函数调用 

使用 . 来调用成员函数:

1
Players.SetAllInRound()

具有类似协程的形式

1
2
3
4
5
6
7
8
9
if(IsSoloGame()?):
    race:
        WaitForZeroRemaining()
        WairForRoundTimeout()
else:
    race:
        WaitForOntRemaining()
        WaitForZeroRemaining()
        WaitForRoundTimeout()

这里代码的含义上类似于 UE 的行为树中的 Sequences 的节点,只有当它的所有子节点都执行成功(完毕)了,它才执行成功。