質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
ソケット

TCP/IPにおいて、IPアドレスとサブアドレスであるポート番号を組み合わせたネットワークアドレスのことを呼びます。また、ソフトウェアアプリケーションにおいて、TCP/IP通信を行う為の仮想的なインターフェースという意味もある。

UDP

UDP(User Datagram Protocol)とは、トランスポート層のプロトコルであり、コネクション型のデータサービスです。IPネットワーク上の別のホストにコンピュータのアプリケーションがメッセージを送ることができ、転送チャンネルやデータ経路を設定する必要はありません。TCPに比べて高速であるが、信頼性が薄いという特徴があります。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

UE4

UE4はUnreal Engine(アンリアルエンジン)の第4世代です。 UEは、Epic Gamesより開発されたゲームエンジンです。

Q&A

解決済

1回答

3370閲覧

UE4 UDP通信時,フレームレートが低下・フリーズする問題

退会済みユーザー

退会済みユーザー

総合スコア0

ソケット

TCP/IPにおいて、IPアドレスとサブアドレスであるポート番号を組み合わせたネットワークアドレスのことを呼びます。また、ソフトウェアアプリケーションにおいて、TCP/IP通信を行う為の仮想的なインターフェースという意味もある。

UDP

UDP(User Datagram Protocol)とは、トランスポート層のプロトコルであり、コネクション型のデータサービスです。IPネットワーク上の別のホストにコンピュータのアプリケーションがメッセージを送ることができ、転送チャンネルやデータ経路を設定する必要はありません。TCPに比べて高速であるが、信頼性が薄いという特徴があります。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

UE4

UE4はUnreal Engine(アンリアルエンジン)の第4世代です。 UEは、Epic Gamesより開発されたゲームエンジンです。

0グッド

0クリップ

投稿2022/01/09 13:29

編集2022/01/09 13:53

実現したいこと

Unreal Engine4で,同PC上の別のプログラムからデータを受信させる為のUDP通信機能を実装しました.概要は以下の様なものです.

  • EventBeginPlayに続いて,指定のip/PortでUDPソケットを作成して受信可能な状態になります.

データが受信される度に,UEのデリゲートによるコールバックがされ,ログとして「data received!」を出力します.

  • EventEndPlayに続いて,ソケットを破棄します.

発生している問題

まず前提ですが,当方のスペック下では,新規にプロジェクトを作成して特に何も処理やオブジェクトを追加する事無く実行すると,120fps前後出ます.
ソケット通信の動作確認は,ほぼ空のプロジェクトに前述の通信処理のみを追加したマップを実行する事により行いました.

UDPでデータを120回/sの速度で送信し続けるpythonプログラムを作り,UEエディタ上での実行にて動作確認を行っています.
概ね正常に動作している様ですが,不可解な問題が発生し,原因がわからず困っております.

  1. UEエディタのPlayボタンを押して先にゲームを開始してから,その後データ送信プログラムを起動すると,

フレームレートは15fps程度とかなり低くなり,そのまま徐々に低下し続け,やがてフリーズする.

  1. 先にデータ送信プログラムを起動しておいた状態で,その後ゲームを開始させると,

問題は起こらず,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を参考しました.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

手元で同様のコードを試してみましたがこちらの環境だと1と2で挙動に差はありませんでした
(1/120程度のスパンで送信する場合は1でも2でも処理でき、sleepを挟まないレベルになると1でも2でも処理しきれない)

原因

こちらで見られた原因はUE_LOGにありました。
UE_LOGはそこそこ重たい処理になり、UDPの送信スパンよりUE_LOGの処理時間の方が長くなった時にリクエストを捌ききれなくなりどんどんリクエストが溜まっていってFPSが低下するという流れになっていました。

根本的な原因の予想

軽くエンジンコードを追ってみたところコールバック自体はゲームスレッドから独立して動いているのですが、
UE_LOGの内部処理がスレッドセーフで動作するようになっていた為大量にリクエストがきても順番待ちになり処理がどんどん重くなっていっているのかもしれません
(それかUE_LOGがGameThreadにスレッドを切り替えて書き込み→スレッドを戻すみたいなことをやっている可能性もあります)

解決案

取り急ぎログの出力をなくすことで sleepを無くしてリクエストを投げれるだけ投げても大きなFPSの低下がみられないことを確認しました。
一度試してみてください

投稿2022/01/13 09:49

編集2022/01/13 09:50
MMashiro

総合スコア2380

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問