我使用UMG和RPC制作了一个简单的聊天Demo。
它的工作方式是使用RPC函数向服务器发送消息,使用GameState在各个客户端同步消息,并动态创建Widget显示消息。
Demo下载
你需要创建或扩展如下几个资源:
MessageInfo结构体
消息本身MyGameState继承自GameState
存储并同步消息MyGameInstance继承自GameInstance
掌控ChatWidgetMyPlayerController继承自PlayerController
使用RPC函数向服务器传递消息MessageRow继承自UserWidget(控件蓝图)
用于显示MessageInfo的控件,将会在接收到新消息的时候动态创建。ChatWidget继承自UserWidget(控件蓝图)
动态创建MessageRow所使用的容器MyGameMode继承自GameMode
使用自己创建的MyGameState,MyPlayerController
具体步骤
1.创建结构体
新建如下两个变量Name和Message
2.创建MyGameState存储并同步消息
创建一个新MessageInfo的数组并将复制设为Replicated。
SwitchHasAuthority的作用是判断是否为服务器,如果是服务器才执行。
3.创建MyGameInstance
在GameInstance中掌控ChatWidget的目的是避免多次Add to Viewport
在项目设置—>地图&模式—>Game Instance Class 中启用它
4.创建MyPlayerController初始化GameInstance中的ChatWidget与处理发送消息的RPC函数
在开始游戏时尝试初始化ChatWidget
当玩家敲回车的时候尝试将键盘焦点设为输入框
发送消息的RPC函数设为仅在服务器运行,勾选可靠函数
5.创建Widget显示结构体
使用一个Horizontal Box作为父控件包含名为Time,Name,Msg的Text控件并将它们的竖立对齐设为居中,启用它们的Is Variable,并把Msg的尺寸设为填充,启用AutoWrapText。
逻辑部分。
新建一个MessageInfo结构体变量并将其设为公有,启用在生成是显示
启用在生成是显示的作用是在我们CreateWidget时会多个这个变量的引脚
接着我们在其构造事件中设置Time,Name,Msg的Text值
Format Text 节点中的参数分别是【[{H}:{M}:{S}]】【{name}:】
6.创建显示消息的容器ChatWidget
在CanvasPanel下添加一个VerticalBox子项,将其锚点设为左下,Alignment的Y设为1。启用ScrollBox的IsVariable。
我们将使用tick检查MyGameState的消息列表是否有更新,所以我们在ChatWidget中创建一个Count整形来判断是否与MyGameState中的消息数值长度一致,不一致则代表有新的消息,调用自定义事件DisplayMessage,输入值设为MessageInfo结构体,动态创建MessageRow传入MessageInfo,并把这个widget添加进ScrollBox的子项,最后是将Count加1。
扩展EditableTextBox的OnTextCommitted事件,判断玩家在按下回车的时候调用此事件然后发送消息。