UE5- c++ websocket客户端写法

# 实现目标

  • ue5 c++ 实现socket客户端,读取服务端数据,并进行解析

#实现步骤

  1. {projectName}.Build.cs里增加 "WebSockets","JsonUtilities", "Json"配置信息,最终输出如下:
    using UnrealBuildTool;
    
    public class myue521 : ModuleRules
    {
    	public myue521(ReadOnlyTargetRules Target) : base(Target)
    	{
    		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
    
    		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore"
            , "HeadMountedDisplay", "EnhancedInput"
            , "WebSockets","JsonUtilities", "Json"});
    	}
    }

    说明,其中myue521是我的模块名,文件名为myue521.Build.cs。 新增的模块:"WebSockets","JsonUtilities", "Json"。

  2. 准备实现自己的webscoket_client。具体操作步骤如下:

    1. 在ue5中自定义类,父类设置为UGameInstance,我这命名为UUWebSocketGameInstance

    2. 在UUWebSocketGameInstance.h里新增如下方法。

      1. 其中init和 Shutdown方法是在父类UGameInstance中定义的,我们这里覆盖它;

      2. WebSocket用来标识我们代码生成的socket,计划在init里初始化,在Shutdown里销毁

      3. OnConnected、OnConnectionError、OnClosed、OnMessage、OnMessageSent用来处理socket消息,具体看后买你的代码实现。

    3. 在UUWebSocketGameInstance.cpp里实现已经生命的方法。

      // Fill out your copyright notice in the Description page of Project Settings.
      
      
      #include "UWebSocketGameInstance.h"
      #include "WebSockets/Public/WebSocketsModule.h"
      #include "WebSockets/Public/IWebSocket.h"
      #include "Templates/SharedPointer.h"
      
      
      void UUWebSocketGameInstance::Init() {
      	Super::Init();
      
      	if (!FModuleManager::Get().IsModuleLoaded("WebSockets")) {
      		FModuleManager::Get().LoadModule("WebSockets");
      	}
      
      	WebSocket = FWebSocketsModule::Get().CreateWebSocket("ws://127.0.0.1:8081/webSocketServer/ue");
      	 
      	WebSocket->OnConnected().AddUObject(this, &UUWebSocketGameInstance::OnConnected);
      	WebSocket->OnConnectionError().AddUObject(this, &UUWebSocketGameInstance::OnConnectionError);
      	WebSocket->OnClosed().AddUObject(this, &UUWebSocketGameInstance::OnClosed);
      	WebSocket->OnMessage().AddUObject(this, &UUWebSocketGameInstance::OnMessage);
      	WebSocket->OnMessageSent().AddUObject(this, &UUWebSocketGameInstance::OnMessageSent);
      
      	WebSocket->Connect();
      
      }
       
      
      void UUWebSocketGameInstance::Shutdown() {
      
      	if (WebSocket->IsConnected()) {
      		WebSocket->Close();
      	} 
      	Super::Shutdown();
      }
      
      
      
      void UUWebSocketGameInstance::OnConnected()
      {
      	UE_LOG(LogTemp, Warning, TEXT("%s"), *FString(__FUNCTION__));
      
      	GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Green, "Successfully Connected");
      }
      
      void UUWebSocketGameInstance::OnConnectionError(const FString& Error)
      {
      	UE_LOG(LogTemp, Warning, TEXT("%s Error:%s"), *FString(__FUNCTION__), *Error);
      }
      
      void UUWebSocketGameInstance::OnClosed(int32 StatusCode, const FString& Reason, bool bWasClean)
      {
      	UE_LOG(LogTemp, Warning, TEXT("%s StatusCode:%d Reason:%s bWasClean:%d"),
      		*FString(__FUNCTION__), StatusCode, *Reason, bWasClean);
      }
      
      void UUWebSocketGameInstance::OnMessage(const FString& Message)
      {
      	GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Cyan, FString::Printf(TEXT("%s Message:%s"), *FString(__FUNCTION__), *Message) );
      
      	UE_LOG(LogTemp, Warning, TEXT("%s Message:%s"), *FString(__FUNCTION__), *Message);
      
      	TSharedRef< TJsonReader<> > Reader = TJsonReaderFactory<>::Create(Message);
      	TSharedPtr<FJsonObject> Root;
      
      	if (FJsonSerializer::Deserialize(Reader, Root))
      	{
      		if (Root->HasField(TEXT("Topic"))) {
      			FString Topic = Root->GetStringField(TEXT("Topic"));
      			TSharedPtr<FJsonObject, ESPMode::ThreadSafe> Data = Root->GetObjectField(TEXT("Data"));
      
      			// TSharedPtr<FJsonObject, ESPMode::ThreadSafe> ObjectField = Object->GetObjectField(TEXT("realtime"));
      			FString KeyField = Data->GetStringField("Key");
      			FString ValueField = Data->GetStringField("Value");
      
      
      			GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Cyan, "Key: " + KeyField + ",Value:" + ValueField);
      		}
      		else {
      			GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Cyan, "解析json异常");
      		}
      	}
      }
      
      void UUWebSocketGameInstance::OnMessageSent(const FString& MessageString)
      {
      	UE_LOG(LogTemp, Warning, TEXT("%s MessageString:%s"), *FString(__FUNCTION__), *MessageString);
      }
      
      
      1. 其中UUWebSocketGameInstance::Init()里初始化了websocket,并配置监听方法

      2. UUWebSocketGameInstance::Shutdown()用来销毁生成的websocket

      3. UUWebSocketGameInstance::OnConnected(),UUWebSocketGameInstance::OnConnectionError,UUWebSocketGameInstance::OnClosed,UUWebSocketGameInstance::OnMessage,UUWebSocketGameInstance::OnMessageSent是用来处理绑定消息的。其中UUWebSocketGameInstance::OnMessage里的消息是json格式,具体格式见下面的备注1.

  3. 开始配置使用并调用方法。

    1. 自主调用可以在某个Character里通过如下代码进行调用。可以在自己的类里面调用。比如放到构造方法或者某个动作触发调用。

      void Amyue521Character::NotifyServer() {
      	UUWebSocketGameInstance* GameInstance = Cast<UUWebSocketGameInstance>(GetGameInstance());
      	if (GameInstance) {
      		if (GameInstance->WebSocket->IsConnected()) {
      			GameInstance->WebSocket->Send("FROM UnrealEngine 5");
      		}
      	}
      }
    2. 通过UE5的项目设置进行修改游戏实例。

  4. 备注

    1. 约定接收的json数据格式为

      {
          "Topic": "Unreal",
          "Data": {
              "Key": "mood",
              "Value": 1.0
          }
       }
  5. 总结

    1.  通过该例子我们学到了websocket,json的应用

    2. 还学到的两种打印log的方法

      GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Cyan, FString::Printf(TEXT("%s Message:%s"), *FString(__FUNCTION__), *Message) );
      
      UE_LOG(LogTemp, Warning, TEXT("%s Message:%s"), *FString(__FUNCTION__), *Message);
  6. 待解决的问题

    1. 为什么使用UGameInstance, UGameInstance在UE5中充当什么角色

    2. ULog 的使用,参考文档:http://www.bimant.com/blog/ue_log-crash-course/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/102270.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深入探讨梯度下降:优化机器学习的关键步骤(二)

文章目录 &#x1f340;引言&#x1f340;eta参数的调节&#x1f340;sklearn中的梯度下降 &#x1f340;引言 承接上篇&#xff0c;这篇主要有两个重点&#xff0c;一个是eta参数的调解&#xff1b;一个是在sklearn中实现梯度下降 在梯度下降算法中&#xff0c;学习率&#xf…

Maven 基础之安装和命令行使用

Maven 的安装和命令行使用 1. 下载安装 下载解压 maven 压缩包&#xff08;http://maven.apache.org/&#xff09; 配置环境变量 前提&#xff1a;需要安装 java 。 在命令行执行如下命令&#xff1a; mvn --version如出现类似如下结果&#xff0c;则证明 maven 安装正确…

无涯教程-Android - ImageButton函数

ImageButton是一个AbsoluteLayout,可让您指定其子级的确切位置。这显示了带有图像(而不是文本)的按钮,用户可以按下或单击该按钮。 Android button style set ImageButton属性 以下是与ImageButton控件相关的重要属性。您可以查看Android官方文档以获取属性的完整列表以及可以…

webrtc 的Bundle group 和RTCP-MUX

1&#xff0c;最近调试程序的时候发现抱一个错误 max-bundle configured but session description has no BUNDLE group 最后发现是一个参数设置错误 config.bundle_policy webrtc::PeerConnectionInterface::BundlePolicy::kBundlePolicyMaxBundle; 2&#xff0c;rtcp-mu…

迈向无限可能, ATEN宏正领跑设备切换行业革命!

随着互联网在各个领域的广泛应用,线上办公这一不受时间和地点制约、不受发展空间限制的办公模式开始广受追捧,预示着经济的发展正朝着新潮与活跃的方向不断跃进。当然,在互联网时代的背景下,多线程、多设备的线上办公模式也催生了许多问题:多设备间无法进行高速传输、切换;为保…

SpringCloud(十)——ElasticSearch简单了解(一)初识ElasticSearch和RestClient

文章目录 1. 初始ElasticSearch1.1 ElasticSearch介绍1.2 安装并运行ElasticSearch1.3 运行kibana1.4 安装IK分词器 2. 操作索引库和文档2.1 mapping属性2.2 创建索引库2.3 对索引库的查、删、改2.4 操作文档 3. RestClient3.1 初始化RestClient3.2 操作索引库3.3 操作文档 1. …

A Mathematical Framework for Transformer Circuits—Part (1)

A Mathematical Framework for Transformer Circuits 前言Summary of ResultsREVERSE ENGINEERING RESULTSCONCEPTUAL TAKE-AWAYS Transformer OverviewModel SimplificationsHigh-Level ArchitectureVirtual Weights and the Residual Stream as a Communication ChannelVIRTU…

Tomcat安装与配置

文章目录 一,说明二,安装三:运行四,配置(若本地一个tomcat服务,可配置,若多个,可忽略)五:修改端口六:启动多tomcat(举例两个)七:Idea关联tomcat(由于老项目不是SpringBoot,这里贴下设置)八:启动服务CMD窗口和Idea关联启动中文乱码九:Linux环境下的部署流程 一,说明 本文主要介…

本地启动若依微服务版本

前置工作&#xff1a; 1.导入sql文件 2.安装完nacos 3.安装完redis 启动步骤&#xff1a; 1.开启nacos&#xff0c;在bin目录下 startup.cmd -m standalone 注意&#xff1a;在这之前要配置nacos持久化&#xff0c;修改conf/application.properties文件&#xff0c;增加支持…

BTC价格预测:灰度突如其来的胜利是否会打破“九月魔咒”?

加密市场即将进入第三季度交易的最后阶段&#xff0c;由于9月份被视为是比特币的下跌时期&#xff0c;大多数投资者都预测加密货币之王将会进一步下跌。然而&#xff0c;事情却发生了逆转&#xff0c;灰度突如其来的胜利是否会打破“九月魔咒”&#xff1f; 受该事件影响&#…

【从0学习Solidity】合约入门 Hello Web3

【学习Solidity的基础】入门智能合约开发 Hello Web3 &#x1f4f1;不写代码没饭吃上架主页 在强者的眼中&#xff0c;没有最好&#xff0c;只有更好。我们是全栈开发领域的优质创作者&#xff0c;同时也是阿里云专家博主。 ✨ 关注我们的主页&#xff0c;探索全栈开发的无限…

Linux下的系统编程——文件与目录操作(六)

前言&#xff1a; 在Linux系统中&#xff0c;文件和目录的操作非常灵活。用户可以通过命令行或者图形界面来进行操作。下面是Linux文件和目录操作的一些常见操作&#xff1a; 目录 一、文件系统 1.inode 2.dentry 二、文件操作 1.stat/lstat&#xff1a; 2.link/unlink…

运行命令出现错误 /bin/bash^M: bad interpreter: No such file or directory

在系统上运行一个 Linux 的命令的时候出现下面的错误信息&#xff1a; -bash: ./build.sh: /bin/bash^M: bad interpreter: No such file or directory 这个是在 Windows 作为 WSL 的时候出的错误。 原因和解决 出现问题的原因在于脚本在 Windows 中使用的回车换行和 Linux …

LLM学习笔记(1)

学习链接 ChatGPT Prompt Engineering for Developers - DeepLearning.AI 一、prompt engineering for developer 1、原则 prompting principles and iterative pattern 2、用于summarize 环境与helper functions import openai import osfrom dotenv import load_dotenv…

基于Kohonen网络的聚类算法

1.案例背景 1.1 Kohonen网络 Kohonen网络是自组织竞争型神经网络的一种,该网络为无监督学习网络,能够识别环境特征并自动聚类。Kohonen神经网络是芬兰赫尔辛基大学教授Teuvo Kohonen 提出的,该网络通过自组织特征映射调整网络权值,使神经网络收敛于一种表示形态。在这一形态中…

【LeetCode】1654:到家的最少跳跃次数的解题思路 关于力扣无法return的BUG的讨论

文章目录 一、题目二、题解与代码三、神奇的BUG3.1 无法执行的 return 和 break 语句3.2 通过另一个 break 解决 一、题目 有一只跳蚤的家在数轴上的位置 x 处。请你帮助它从位置 0 出发&#xff0c;到达它的家。 跳蚤跳跃的规则如下&#xff1a; 它可以 往前 跳恰好 a 个位…

Maven入门教程(三):Maven语法

视频教程&#xff1a;Maven保姆级教程 Maven入门教程(一)&#xff1a;安装Maven环境 Maven入门教程(二)&#xff1a;idea/Eclipse使用Maven Maven入门教程(三)&#xff1a;Maven语法 Maven入门教程(四)&#xff1a;Nexus私服 Maven入门教程(五)&#xff1a;自定义脚手架 6.Mav…

spring高级源码50讲-37-42(springBoot)

Boot 37) Boot 骨架项目 如果是 linux 环境&#xff0c;用以下命令即可获取 spring boot 的骨架 pom.xml curl -G https://start.spring.io/pom.xml -d dependenciesweb,mysql,mybatis -o pom.xml也可以使用 Postman 等工具实现 若想获取更多用法&#xff0c;请参考 curl …

Android逆向学习(二)vscode进行双开与图标修改

Android逆向学习&#xff08;二&#xff09;vscode进行双开与图标修改 写在前面 这其实应该还是吾爱的第一个作业&#xff0c;但是写完上一个博客的时候已经比较晚了&#xff0c;如果继续敲机械键盘吵到室友&#xff0c;我怕我看不到明天的太阳&#xff0c;所以我决定分成两篇…

七、Linux中一些符号的含义和宿主目录的介绍

1、Linux中一些符号的含义 在Linux命令行中&#xff0c;会看到如下一些符号&#xff0c;含义如下。 符号含义. 代表当前目录..代表上一层目录&#xff0c;当前目录的父目录-代表前一个目录&#xff0c;刚才从哪个目录cd过来~代表当前用户的宿主目录/代表根目录$普通用户的命…