内蒙古自治区网站建设_网站建设公司_在线客服_seo优化
2026/1/19 20:09:49 网站建设 项目流程

好的,明白了!根据你的确认,我来提供完整的实现代码。

完整修改方案

一、UdpSocketServer.h 修改

在文件中添加以下内容:

1. 添加委托声明(在现有委托声明区域,建议放在 FOnMissileGroupDataReceived 之后)

DECLARE_DYNAMIC_MULTICAST_DELEGATE_FiveParams(FOnLoiteringMunitionGroupDataReceived, const TArray<uint8>&, MunitionIds, const TArray<uint8>&, MunitionTypes, const TArray<uint8>&, MunitionStates, const TArray<FVector>&, MunitionPositions,const TArray<FRotator>&, MunitionRotations
);

2. 添加委托实例(在public区域,建议放在 OnMissileGroupDataReceived 之后)

UPROPERTY(BlueprintAssignable, Category = "UDP Loitering Munition Delegate")
FOnLoiteringMunitionGroupDataReceived OnLoiteringMunitionGroupDataReceived;

3. 添加解析函数声明(在 ParseMissileGroupData 之后)

void ParseLoiteringMunitionGroupData(const TArray<uint8>& Data, FString& OutStr);

二、UdpSocketServer.cpp 修改

1. 在 DataRecv 函数的 switch 语句中添加 case 5

找到 DataRecv 函数中的 switch 语句,在 case 4 之后添加:

case 5:
{FString DebugStr;ParseLoiteringMunitionGroupData(ReceivedData, DebugStr);str = DebugStr;success = true;break;
}

2. 实现 ParseLoiteringMunitionGroupData 函数

在文件末尾(建议放在 ParseMissileGroupData 函数之后)添加:

void UUdpSocketServer::ParseLoiteringMunitionGroupData(const TArray<uint8>& Data, FString& OutStr)
{int32 Offset = 1;uint8 MunitionCount = Data[Offset];Offset += 1;const int32 SingleMunitionDataSize = 51;  // 1(ID) + 1(Type) + 1(State) + 24(Position) + 24(Rotation)if ((Data.Num() - Offset) < (MunitionCount * SingleMunitionDataSize)){UE_LOG(LogTemp, Warning, TEXT("Insufficient data for loitering munition group. munition count: %d, hope length: %d, fact length: %d"),MunitionCount, Offset + MunitionCount * SingleMunitionDataSize, Data.Num());OutStr = TEXT("Error: Insufficient data for loitering munition group");return;}TArray<uint8> MunitionIds;TArray<uint8> MunitionTypes;TArray<uint8> MunitionStates;TArray<FVector> MunitionPositions;TArray<FRotator> MunitionRotations;FString GroupStr = TEXT("Loitering Munition Group: ");for (int32 i = 0; i < MunitionCount; ++i){uint8 MunitionId = Data[Offset];uint8 MunitionType = Data[Offset + 1];uint8 MunitionState = Data[Offset + 2];// 解析位置double X = 0, Y = 0, Z = 0;FMemory::Memcpy(&X, &Data[Offset + 3], sizeof(double));FMemory::Memcpy(&Y, &Data[Offset + 11], sizeof(double));FMemory::Memcpy(&Z, &Data[Offset + 19], sizeof(double));// 解析姿态double Yaw = 0, Pitch = 0, Roll = 0;FMemory::Memcpy(&Yaw, &Data[Offset + 27], sizeof(double));FMemory::Memcpy(&Pitch, &Data[Offset + 35], sizeof(double));FMemory::Memcpy(&Roll, &Data[Offset + 43], sizeof(double));FVector Position(static_cast<float>(X), static_cast<float>(Y), static_cast<float>(Z));FRotator Rotation(static_cast<float>(Pitch), static_cast<float>(Yaw), static_cast<float>(Roll));GroupStr += FString::Printf(TEXT("[ID: %d, Type: %d, State: %d, Pos: %s, Rot: %s] "),MunitionId, MunitionType, MunitionState, *Position.ToString(), *Rotation.ToString());Position = ConvertUEOffset(Position);if (MunitionId > 0)  // 0 为无效巡飞弹{MunitionIds.Add(MunitionId);MunitionTypes.Add(MunitionType);MunitionStates.Add(MunitionState);MunitionPositions.Add(Position);MunitionRotations.Add(Rotation);}Offset += SingleMunitionDataSize;}OutStr = GroupStr;if (bIsLogReceivedPackage)UE_LOG(LogTemp, Warning, TEXT("the data parse loitering munition group is: %s"), *OutStr);// 广播委托OnLoiteringMunitionGroupDataReceived.Broadcast(MunitionIds, MunitionTypes, MunitionStates, MunitionPositions, MunitionRotations);
}

三、Python 测试脚本

创建一个测试脚本来验证功能:

import socket
import struct
import timedef send_loitering_munition_group(sock, target_ip, target_port, munitions_data):"""发送巡飞弹组数据munitions_data: list of dict, 每个dict包含 id, type, state, position(x,y,z), rotation(yaw,pitch,roll)"""message_type = 5munition_count = len(munitions_data)# 构建数据包packet = struct.pack('BB', message_type, munition_count)for munition in munitions_data:# 基本信息: ID, Type, Statepacket += struct.pack('BBB', munition['id'], munition['type'], munition['state'])# 位置: X, Y, Z (double)packet += struct.pack('ddd', munition['position'][0],munition['position'][1],munition['position'][2])# 姿态: Yaw, Pitch, Roll (double)packet += struct.pack('ddd',munition['rotation'][0],  # Yawmunition['rotation'][1],  # Pitchmunition['rotation'][2])  # Rollsock.sendto(packet, (target_ip, target_port))print(f"发送巡飞弹组数据: {munition_count} 个巡飞弹")print(f"数据包大小: {len(packet)} 字节")# 测试代码
if __name__ == "__main__":# 配置TARGET_IP = "127.0.0.1"  # 修改为你的目标IPTARGET_PORT = 8888        # 修改为你的目标端口# 创建UDP socketsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 测试数据:3个巡飞弹test_munitions = [{'id': 1,'type': 1,'state': 0,'position': [100.0, 200.0, 50.0],'rotation': [45.0, 10.0, 5.0]  # Yaw, Pitch, Roll},{'id': 2,'type': 2,'state': 1,'position': [150.0, 250.0, 60.0],'rotation': [90.0, 15.0, -5.0]},{'id': 3,'type': 1,'state': 0,'position': [200.0, 300.0, 70.0],'rotation': [135.0, 20.0, 0.0]}]try:while True:send_loitering_munition_group(sock, TARGET_IP, TARGET_PORT, test_munitions)# 更新位置和姿态(模拟移动)for munition in test_munitions:munition['position'][0] += 1.0munition['position'][1] += 0.5munition['rotation'][0] = (munition['rotation'][0] + 1) % 360time.sleep(0.1)  # 100ms发送一次except KeyboardInterrupt:print("\n停止发送")finally:sock.close()

四、修改总结

修改的文件:

  1. UdpSocketServer.h - 添加委托和函数声明
  2. UdpSocketServer.cpp - 添加解析逻辑

关键点:

  • ✅ 复用 NumMissilesPerPacket 配置
  • ✅ 使用消息类型 5
  • ✅ 数据包格式:1(消息类型) + 1(数量) + N×51(每个巡飞弹数据)
  • ✅ 仅实现 Group 版本
  • ✅ 包含位置和姿态数据
  • ✅ 支持坐标转换 ConvertUEOffset

数据包结构:

[消息类型:1字节] [数量:1字节] [巡飞弹1数据:51字节] [巡飞弹2数据:51字节] ...每个巡飞弹数据(51字节):
- ID: 1字节
- Type: 1字节  
- State: 1字节
- Position X: 8字节(double)
- Position Y: 8字节(double)
- Position Z: 8字节(double)
- Yaw: 8字节(double)
- Pitch: 8字节(double)
- Roll: 8字节(double)

这样修改后,你就可以在蓝图中订阅 OnLoiteringMunitionGroupDataReceived 委托来接收和处理巡飞弹数据了!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询