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

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

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

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

UDP

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

C++

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

UE4

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

解決済

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

WFB
WFB

総合スコア12

ソケット

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

UDP

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

C++

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

UE4

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

1回答

0評価

0クリップ

389閲覧

投稿2022/01/09 13:29

編集2022/01/13 18:50

実現したいこと

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

#pragma once #include "CoreMinimal.h" #include "UObject/NoExportTypes.h" #include "Networking.h" #include "Sockets.h" #include "UUDPTestUObject.generated.h" UCLASS( BlueprintType ) class UUDPTestUObject : public UObject { GENERATED_BODY() private: FSocket* socket_; FUdpSocketReceiver* receiver_; FIPv4Address ip_address_; int32 port_number_; // Connect関数が呼ぶ bool CreateSocket(); bool CreateReceiver(); // Shutdown関数が呼ぶ void DeleteSocket(); void DeleteReceiver(); // データ受信時にコールバックされる.今回は単なるログ出力. void OnSocketDataReceivedFunc( const FArrayReaderPtr& reader, const FIPv4Endpoint& sender ); public: // localhostの指定ポートにソケットを作ってUDPで受信出来る状態にする UFUNCTION( BlueprintCallable ) bool Connect( int32 port_number ); // ソケットを破棄する UFUNCTION( BlueprintCallable ) void Shutdown(); };

UUDPTestUObject.cpp

CPP

#include "UUDPTestUObject.h" void UUDPTestUObject::OnSocketDataReceivedFunc( const FArrayReaderPtr& reader, const FIPv4Endpoint& sender ) { UE_LOG( LogTemp, Log, TEXT( "Received Data!" ) ); } bool UUDPTestUObject::Connect( int32 port_number ) { ip_address_ = FIPv4Address( 127, 0, 0, 1 ); port_number_ = port_number; if ( !CreateSocket() ) { Shutdown(); return false; } if ( !CreateReceiver() ) { Shutdown(); return false; } return true; } void UUDPTestUObject::Shutdown() { DeleteReceiver(); DeleteSocket(); } bool UUDPTestUObject::CreateSocket() { socket_ = FUdpSocketBuilder( TEXT( "Unicast" ) ) .BoundToAddress( ip_address_ ) .BoundToPort( port_number_ ) .Build(); if ( !socket_ ) { return false; } return true; } bool UUDPTestUObject::CreateReceiver() { receiver_ = new FUdpSocketReceiver( socket_, FTimespan::FromMilliseconds( 1 ), TEXT( "Receiver" ) ); if ( !receiver_ ) { return false; } receiver_->OnDataReceived() .BindUObject( this, &UUDPTestUObject::OnSocketDataReceivedFunc ); receiver_->Start(); return true; } void UUDPTestUObject::DeleteSocket() { if ( socket_ ) { socket_->Close(); delete socket_; socket_ = nullptr; } return; } void UUDPTestUObject::DeleteReceiver() { if ( receiver_ ) { receiver_->Stop(); delete receiver_; receiver_ = nullptr; } return; }

データ送信プログラム

python

import socket import time sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) print('Sender: socket created.') while True: try: message = "hello" send_len = sock.sendto(message.encode('utf-8'), ('127.0.0.1', 8888) ) # ★送信スピードの制限 :さらに下げて1/60にしてみたり,1/500にしてみたり,コメントアウトしたり…を試しました # time.sleep(1/120) except KeyboardInterrupt: print('closing socket') sock.close() print('closed') break

補足情報(FW/ツールのバージョンなど)

環境

  • Unreal Engine 4.27.2
  • Python 3.10.1
  • Windows10 Home 64bit

C++コードはhistoria-Inc/Tech_UDPDemoを参考しました.

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

ソケット

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

UDP

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

C++

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

UE4

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