EpicVerse:UE5 新的脚本语言

UE5 可能的脚本语言简介

在 Epic 的 Inside Unreal:2020 Year In Review 中介绍了一个全新的脚本语言,有可能被称作Epic Verse

reddit 上关于该脚本语言的讨论:Epic showed off their new Unreal Verse scripting language that will probably end up in UE5

UE4 的蓝图极大地降低了非专业开发者的上手门槛,图形化编程的方式从线性角度很容易理解,但是也会造成混乱。上了一定规模的项目还是需要文本化的脚本语言的,主要解决以下几个问题:

  1. 文本化方便协同开发,不会造成资源的冲突(BP 是资源)
  2. 方便直观地进行 diff
  3. 方便迁移引擎版本,而没有资源的升 / 降级问题

而且我认为,脚本语言最好是强类型语言,写惯了 C++ 这种静态强类型语言,其实对 Lua 这种弱类型语言还是挺不习惯的,之前有一种语言叫做 AngelScript 的静态强类型脚本语言,和 C++ 非常像,被第三方集成到了 UE 中,但是目前只支持 PC 和主机平台,不支持移动端。

对于 UE4 中目前在手游开发中主流的脚本语言支持,为腾讯开源的 UnLuaSLua两款插件,都是以反射形式集成的,有一些实现上的缺点和社区支持不够,希望 Epic 能出一款官方支持的脚本工具,原本以为 Python 有比较大的可能,因为 UE 在编辑器下对 Python 的支持已经挺好了,而且 Python 有比较大的用户群体,上手难度也不高。

如果引入一门新的脚本语言,在 UE 中可以使用的编程方式:

  1. C++
  2. 蓝图
  3. Python(编辑器)
  4. Epic Verse

处理不同的需求有不同的语言,有些过于复杂了。

目前还不知道 UE 出的这个新脚本具体表现和语法形式怎么样,其实新增一门语言大大增加了用户的学习成本,也不知道 UE 是如何设计 BP 和新脚本语言的关联的,等最新的消息再看。

两年前 Tim 在 Reddit 上有一些相关的回复和讨论:It seems people at Epic are considering adding some intermediate script language between C++ and Blueprints

Epic Verse 语法介绍

认真看了一下 Inside Unreal:2020 Year In Review 里展示的 Epic Verse 代码,看起来新的脚本语言很像 pascalPython的结合体,而且还有点 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 的节点,只有当它的所有子节点都执行成功(完毕)了,它才执行成功。

这门脚本语言看起来更像是以 SkookumScript 为基础,糅合了数种编程语言的集合体,目前展示的代码还太少,不好说具体的上手表现怎么样,持续关注。