実現したいこと
Unreal Engine4で,同PC上の別のプログラムからデータを受信させる為のUDP通信機能を実装しました.概要は以下の様なものです.
- EventBeginPlayに続いて,指定のip/PortでUDPソケットを作成して受信可能な状態になります.
データが受信される度に,UEのデリゲートによるコールバックがされ,ログとして「data received!」を出力します.
- EventEndPlayに続いて,ソケットを破棄します.
発生している問題
まず前提ですが,当方のスペック下では,新規にプロジェクトを作成して特に何も処理やオブジェクトを追加する事無く実行すると,120fps前後出ます.
ソケット通信の動作確認は,ほぼ空のプロジェクトに前述の通信処理のみを追加したマップを実行する事により行いました.
UDPでデータを120回/sの速度で送信し続けるpythonプログラムを作り,UEエディタ上での実行にて動作確認を行っています.
概ね正常に動作している様ですが,不可解な問題が発生し,原因がわからず困っております.
- UEエディタのPlayボタンを押して先にゲームを開始してから,その後データ送信プログラムを起動すると,
フレームレートは15fps程度とかなり低くなり,そのまま徐々に低下し続け,やがてフリーズする.
- 先にデータ送信プログラムを起動しておいた状態で,その後ゲームを開始させると,
問題は起こらず,120fps前後で安定し,低下はしない.
試したこと
送信側のプログラムの送信速度を変えてみたりしました.
問題のある1.の場合だと,送信速度をさらに低くしてみると,UE側のフレームレートの低下の度合いはほんの少し緩和しましたが,やはり継続的に低下し続けてやがてフリーズに陥ります.
逆に,問題が無い2.の場合では,500回/sといったUEの側の描写速度を上回る送信速度に引き上げてみても,変わらず問題は起こりませんでした.但し,送信速度の制限を完全に無くしてしまうと,1.と同様にフレームレートの低下&フリーズが起こりました.
所感ですが「捌き切れない何かが溜まり続けていっぱいいっぱいになってしまう」という様な印象があります.
通信を扱う経験は少なく まだ詳しくないですが,UDP通信でそういう事が起こるものなのでしょうか….
(送信側との受信確認連絡や再送信を行わないというだけで,ちゃんと受信されたデータは地道に捌いていくという感じなのでしょうか.)
1.と2.の様に,起動順によって問題が起こったり起こらなかったりするという点では,そういう問題でもない気もしますが….
少なくとも,送信側と受信側の,どちらを先に起動する場合でも問題が無いようにしたいです.
何か分かる方がいれば,お教え頂きたいです.宜しくお願い致します.
ソースコード
受信プログラム.
UUDPTestUObject.h
cpp
1#pragma once 2 3#include "CoreMinimal.h" 4#include "UObject/NoExportTypes.h" 5#include "Networking.h" 6#include "Sockets.h" 7#include "UUDPTestUObject.generated.h" 8 9UCLASS( BlueprintType ) 10class UUDPTestUObject : public UObject 11{ 12 GENERATED_BODY() 13private: 14 FSocket* socket_; 15 FUdpSocketReceiver* receiver_; 16 FIPv4Address ip_address_; 17 int32 port_number_; 18 19 // Connect関数が呼ぶ 20 bool CreateSocket(); 21 bool CreateReceiver(); 22 // Shutdown関数が呼ぶ 23 void DeleteSocket(); 24 void DeleteReceiver(); 25 26 // データ受信時にコールバックされる.今回は単なるログ出力. 27 void OnSocketDataReceivedFunc( const FArrayReaderPtr& reader, const FIPv4Endpoint& sender ); 28 29public: 30 // localhostの指定ポートにソケットを作ってUDPで受信出来る状態にする 31 UFUNCTION( BlueprintCallable ) 32 bool Connect( int32 port_number ); 33 // ソケットを破棄する 34 UFUNCTION( BlueprintCallable ) 35 void Shutdown(); 36};
UUDPTestUObject.cpp
CPP
1#include "UUDPTestUObject.h" 2 3void UUDPTestUObject::OnSocketDataReceivedFunc( const FArrayReaderPtr& reader, const FIPv4Endpoint& sender ) 4{ 5 UE_LOG( LogTemp, Log, TEXT( "Received Data!" ) ); 6} 7bool UUDPTestUObject::Connect( int32 port_number ) 8{ 9 ip_address_ = FIPv4Address( 127, 0, 0, 1 ); 10 port_number_ = port_number; 11 12 if ( !CreateSocket() ) 13 { 14 Shutdown(); 15 return false; 16 } 17 if ( !CreateReceiver() ) 18 { 19 Shutdown(); 20 return false; 21 } 22 return true; 23} 24void UUDPTestUObject::Shutdown() 25{ 26 DeleteReceiver(); 27 DeleteSocket(); 28} 29 30bool UUDPTestUObject::CreateSocket() 31{ 32 socket_ = FUdpSocketBuilder( TEXT( "Unicast" ) ) 33 .BoundToAddress( ip_address_ ) 34 .BoundToPort( port_number_ ) 35 .Build(); 36 if ( !socket_ ) 37 { 38 return false; 39 } 40 return true; 41} 42bool UUDPTestUObject::CreateReceiver() 43{ 44 receiver_ = new FUdpSocketReceiver( socket_, FTimespan::FromMilliseconds( 1 ), TEXT( "Receiver" ) ); 45 if ( !receiver_ ) 46 { 47 return false; 48 } 49 receiver_->OnDataReceived() 50 .BindUObject( this, &UUDPTestUObject::OnSocketDataReceivedFunc ); 51 receiver_->Start(); 52 return true; 53} 54void UUDPTestUObject::DeleteSocket() 55{ 56 if ( socket_ ) 57 { 58 socket_->Close(); 59 delete socket_; 60 socket_ = nullptr; 61 } 62 return; 63} 64void UUDPTestUObject::DeleteReceiver() 65{ 66 if ( receiver_ ) 67 { 68 receiver_->Stop(); 69 delete receiver_; 70 receiver_ = nullptr; 71 } 72 return; 73}
データ送信プログラム
python
1import socket 2import time 3 4sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 5print('Sender: socket created.') 6 7while True: 8 try: 9 message = "hello" 10 send_len = sock.sendto(message.encode('utf-8'), ('127.0.0.1', 8888) ) 11 # ★送信スピードの制限 :さらに下げて1/60にしてみたり,1/500にしてみたり,コメントアウトしたり…を試しました 12 # time.sleep(1/120) 13 14 except KeyboardInterrupt: 15 print('closing socket') 16 sock.close() 17 print('closed') 18 break
補足情報(FW/ツールのバージョンなど)
環境
- Unreal Engine 4.27.2
- Python 3.10.1
- Windows10 Home 64bit
C++コードはhistoria-Inc/Tech_UDPDemoを参考しました.
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。