当前位置:   article > 正文

UE中蓝图,C++结合UDP通信_虚幻udp

虚幻udp

一:ue中udp通信方法(本篇使用的是第二种方法)

1.通过插件,然后在ue中蓝图中直接使用,比较方便。(下面这个两个是虚幻引擎中的udp插件,比较好用)

2. 通过自己编写c++代码,实现udp通信逻辑,在ue中的蓝图使用。

二:使用c++代码编写蓝图udp通信逻辑

在蓝图中c++类新创建一个BlueprintFunctionLibrary类,类名可以自己取,我这个去的类名为

UDPSocketServer.h,UDPSocketServer.cpp(源码放在下面了),网上代码基本上都是差不多的

源码(在我的源码中我通过udp测试软件实现了发送zoom:***%百分比数据控制角色大小缩放)

1.UDPSocketServer.h(头文件)
  1. // Fill out your copyright notice in the Description page of Project Settings.
  2. #pragma once
  3. #include "CoreMinimal.h"
  4. #include "Kismet/BlueprintFunctionLibrary.h"
  5. #include "Runtime/Networking/Public/Networking.h"
  6. #include "Engine.h"
  7. #include "UDPSocketServer.generated.h"
  8. /**
  9. *
  10. */
  11. UCLASS(Blueprintable)
  12. // 这里需要注意一下DEMO_3D_API ,这个API是项目名字的API
  13. class DEMO_3D_API UUDPSocketServer : public UBlueprintFunctionLibrary
  14. {
  15. GENERATED_BODY()
  16. public:
  17. static void ScreenMsg(const FString& Msg);
  18. static void ScreenMsg(const FString& Msg, const float Value);
  19. static void ScreenMsg(const FString& Msg, const FString& Msg2);
  20. UFUNCTION(BlueprintCallable, Category = "UDP")
  21. //新建初始化Receiver函数
  22. static void StartUDPReceiver(const FString& YourChosenSocketName, const FString& TheIP, const int32 ThePort, bool& success);
  23. UFUNCTION(BlueprintCallable, Category = "UDP")
  24. static bool StartUDPSender(const FString& YourChosenSocketName, const FString& TheIP, const int32 ThePort);
  25. UFUNCTION(BlueprintCallable, Category = "UDP")
  26. static void CloseUDPReceiver();
  27. UFUNCTION(BlueprintCallable, Category = "UDP")
  28. static void CloseUDPSender();
  29. UFUNCTION(BlueprintCallable, Category = "UDP")
  30. static bool RamaUDPSender_SendString(FString ToSend);
  31. UFUNCTION(BlueprintCallable, Category = "UDP")
  32. static FVector SetScale(FString Data);
  33. UFUNCTION(BlueprintPure, Category = "UDP")
  34. //DataRecv返回函数
  35. static FString DataRecv(FString& str, bool& success);
  36. };
2.UDPSocketServer.cpp(源文件)
  1. // Fill out your copyright notice in the Description page of Project Settings.
  2. #include "UDPSocketServer.h"
  3. TSharedPtr<FInternetAddr> RemoteAddr;
  4. FSocket* SenderSocket;
  5. FSocket* ListenSocket;
  6. FUdpSocketReceiver* UDPReceiver = nullptr;
  7. //ScreenMsg 把数据打印到屏幕
  8. void UUDPSocketServer::ScreenMsg(const FString& Msg)
  9. {
  10. GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, *Msg);
  11. }
  12. void UUDPSocketServer::ScreenMsg(const FString& Msg, const float Value)
  13. {
  14. GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("%s %f"), *Msg, Value));
  15. }
  16. void UUDPSocketServer::ScreenMsg(const FString& Msg, const FString& Msg2)
  17. {
  18. GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, *Msg);
  19. GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, *Msg2);
  20. }
  21. void UUDPSocketServer::CloseUDPSender()
  22. {
  23. if (SenderSocket) //Clear all sockets!
  24. {
  25. SenderSocket->Close();
  26. ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(SenderSocket);
  27. }
  28. }
  29. // 发送并打印到屏幕中
  30. bool UUDPSocketServer::RamaUDPSender_SendString(FString ToSend) //发送消息处理
  31. {
  32. if (!SenderSocket)
  33. {
  34. ScreenMsg("No sender socket");
  35. return false;
  36. }
  37. //~~~~~~~~~~~~~~~~
  38. //发送消息
  39. int32 BytesSent = 0;
  40. FString serialized = ToSend;
  41. TCHAR* serializedChar = serialized.GetCharArray().GetData();
  42. int32 size = FCString::Strlen(serializedChar);
  43. int32 sent = 0;
  44. //SenderSocket->SendTo(Writer.GetData(), Writer.Num(), BytesSent, *RemoteAddr);
  45. SenderSocket->SendTo((uint8*)TCHAR_TO_UTF8(serializedChar), size, BytesSent, *RemoteAddr);//发送给远端地址
  46. if (BytesSent <= 0)
  47. {
  48. const FString Str = "Socket is valid but the receiver received 0 bytes, make sure it is listening properly!";
  49. UE_LOG(LogTemp, Error, TEXT("%s"), *Str);
  50. ScreenMsg(Str);
  51. return false;
  52. }
  53. ScreenMsg("UDP Send Succcess! INFO Sent = ", ToSend);
  54. return true;
  55. }
  56. // 设置人物角色缩放
  57. FVector UUDPSocketServer::SetScale(FString Data)
  58. {
  59. FVector ScaleValue;
  60. if (Data.StartsWith(TEXT("zoom:")))
  61. {
  62. FString PercentageData = Data.Mid(5); // 获取第五为后的数据
  63. float Zoom = FCString::Atof(*PercentageData) / 100.0f;
  64. float value = (1 + Zoom) * 0.8; // 缩放值:0.8 --- 1.6
  65. ScaleValue = FVector(value, value, value);
  66. }
  67. return ScaleValue;
  68. }
  69. // 接收到的数据
  70. FString UUDPSocketServer::DataRecv(FString& str, bool& success)
  71. {
  72. if (!ListenSocket)
  73. {
  74. ScreenMsg("No sender socket");
  75. success = false;
  76. //return success;
  77. }
  78. TSharedRef<FInternetAddr> targetAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
  79. TArray<uint8> ReceivedData;//定义一个接收器
  80. uint32 Size;
  81. if (ListenSocket->HasPendingData(Size))
  82. {
  83. success = true;
  84. str = "";
  85. uint8* Recv = new uint8[Size];
  86. int32 BytesRead = 0;
  87. ReceivedData.SetNumUninitialized(FMath::Min(Size, 65507u));
  88. ListenSocket->RecvFrom(ReceivedData.GetData(), ReceivedData.Num(), BytesRead, *targetAddr);//创建远程接收地址
  89. char ansiiData[1024];
  90. memcpy(ansiiData, ReceivedData.GetData(), BytesRead);//拷贝数据到接收器
  91. ansiiData[BytesRead] = 0; //判断数据结束
  92. FString debugData = ANSI_TO_TCHAR(ansiiData); //字符串转换
  93. str = debugData;
  94. // memset(ansiiData,0,1024);//清空
  95. }
  96. else
  97. {
  98. success = false;
  99. }
  100. return str;
  101. }
  102. // 创建udp发送端
  103. bool UUDPSocketServer::StartUDPSender(const FString& YourChosenSocketName, const FString& TheIP, const int32 ThePort)///初始化远端IP 发送信息前
  104. {
  105. //FIPv4Endpoint Endpoint(FIPv4Address::Any, 6789);
  106. //Create Remote Address.
  107. RemoteAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
  108. bool bIsValid;
  109. RemoteAddr->SetIp(*TheIP, bIsValid);
  110. RemoteAddr->SetPort(ThePort);
  111. if (!bIsValid)
  112. {
  113. ScreenMsg("Rama UDP Sender>> IP address was not valid!", TheIP);
  114. return false;
  115. }
  116. SenderSocket = FUdpSocketBuilder(*YourChosenSocketName)
  117. .AsReusable()
  118. .WithBroadcast() // 广播
  119. .WithSendBufferSize(2 * 1024 * 1024)
  120. //.BoundToEndpoint(Endpoint)
  121. ;
  122. //check(SenderSocket->GetSocketType() == SOCKTYPE_Datagram);
  123. //Set Send Buffer Size
  124. int32 SendSize = 2 * 1024 * 1024;
  125. SenderSocket->SetSendBufferSize(SendSize, SendSize);
  126. SenderSocket->SetReceiveBufferSize(SendSize, SendSize);
  127. if (bIsValid)
  128. {
  129. bIsValid = true;
  130. }
  131. return bIsValid;
  132. }
  133. // 关闭udp接收
  134. void UUDPSocketServer::CloseUDPReceiver()
  135. {
  136. delete UDPReceiver;
  137. UDPReceiver = nullptr;
  138. //Clear all sockets!
  139. // makes sure repeat plays in Editor dont hold on to old sockets!
  140. if (ListenSocket)
  141. {
  142. ListenSocket->Close();
  143. ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ListenSocket);
  144. }
  145. }
  146. // 创建udp接收端
  147. void UUDPSocketServer::StartUDPReceiver(const FString& YourChosenSocketName, const FString& TheIP, const int32 ThePort, bool& success)
  148. {
  149. TSharedRef<FInternetAddr> targetAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
  150. FIPv4Address Addr;
  151. FIPv4Address::Parse(TheIP, Addr);
  152. //Create Socket
  153. FIPv4Endpoint Endpoint(FIPv4Address::Any, ThePort); //所有ip地址本地
  154. //FIPv4Endpoint Endpoint(Addr, ThePort); //指定ip地址
  155. ListenSocket = FUdpSocketBuilder(*YourChosenSocketName)
  156. .AsNonBlocking()
  157. .AsReusable()
  158. .BoundToEndpoint(Endpoint)
  159. .WithReceiveBufferSize(2 * 1024 * 1024);
  160. //BUFFER SIZE
  161. int32 BufferSize = 2 * 1024 * 1024;
  162. ListenSocket->SetSendBufferSize(BufferSize, BufferSize);
  163. ListenSocket->SetReceiveBufferSize(BufferSize, BufferSize);
  164. if (!ListenSocket)
  165. {
  166. ScreenMsg("No socket");
  167. success = false;
  168. }
  169. if (ListenSocket)
  170. {
  171. ScreenMsg("The receiver is initialized");
  172. success = true;
  173. }
  174. //return true;
  175. }

三:蓝图的使用(角色蓝图类的类型为character)

1.创建udp接收发送端口(reciver是接收端,IP为本机电脑IP,不知到IP的可以使用Windows+R打开运行,输入cmd,然后使用ipconfig命令查看IP,port为本机端口,必须与要给它发送数据的发送端目标的端一致)

2.关闭发送接收端口

3.接收数据然后设置角色缩放(set actor transform为设置角色变换)

location为设置当前角色位置

rotation为设置当前角色旋转

如果不设置上述那么角色在设置缩放后位置为0,0,0

这里最重要的逻辑是使用data recv接收到数据,返回值(return value)传递给set scale判断是否为zoom:百分比数据,如果是那么返回值(return value),将FVector类型传递给(set actor transform)从而设置角色缩放

本篇文章为自己总结,如果网友发现不够细微之处,麻烦在评论区指出,我尽力做到最好

如需转载请说明出处UE中蓝图,C++结合UDP通信-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/894977
推荐阅读
相关标签
  

闽ICP备14008679号