为UE5的Actor添加能够读写姿态的功能
提问
// Copyright 2019-2022 The MathWorks, Inc.
#include "SetGetActorLocation.h"// Sets default values
ASetGetActorLocation::ASetGetActorLocation():SignalReader(nullptr), SignalWriter(nullptr)
{
}void ASetGetActorLocation::Sim3dSetup()
{
Super::Sim3dSetup();if (Tags.Num() != 0) {unsigned int numElements = 3;FString tagName = Tags.Top().ToString();FString SignalReaderTag = tagName;SignalReaderTag.Append(TEXT("Set"));SignalReader = StartSimulation3DMessageReader(TCHAR_TO_ANSI(*SignalReaderTag), sizeof(float)*numElements);FString SignalWriterTag = tagName;SignalWriterTag.Append(TEXT("Get"));SignalWriter = StartSimulation3DMessageWriter(TCHAR_TO_ANSI(*SignalWriterTag), sizeof(float)*numElements);}
}void ASetGetActorLocation::Sim3dStep(float DeltaSeconds)
{unsigned int numElements = 3;float array[3];int statusR = ReadSimulation3DMessage(SignalReader, sizeof(float)*numElements, array);FVector NewLocation;NewLocation.X = array[0];NewLocation.Y = array[1];NewLocation.Z = array[2];SetActorLocation(NewLocation);float fvector[3] = { NewLocation.X, NewLocation.Y, NewLocation.Z };int statusW = WriteSimulation3DMessage(SignalWriter, sizeof(float)*numElements ,fvector);
}void ASetGetActorLocation::Sim3dRelease()
{Super::Sim3dRelease();if (SignalReader) {StopSimulation3DMessageReader(SignalReader);}SignalReader = nullptr; if (SignalWriter) {StopSimulation3DMessageWriter(SignalWriter);}SignalWriter = nullptr;
}
这个代码块的核心功能应该是可以接收三维坐标的位置,同时也支持输出三维坐标的位置,是么?
回答
是的,你的理解完全正确。
这个 ASetGetActorLocation
类的核心功能就是:
✅ 接收 (Set) 和 输出 (Get) 三维坐标位置(FVector
)的功能。
📌 详细说明如下:
1. 输入位置:从外部系统接收位置坐标并设置Actor的位置
int statusR = ReadSimulation3DMessage(SignalReader, sizeof(float)*3, array);
FVector NewLocation;
NewLocation.X = array[0];
NewLocation.Y = array[1];
NewLocation.Z = array[2];
SetActorLocation(NewLocation);
- 从
SignalReader
中读取一个float[3]
数组。 - 把这个数组解析为
X, Y, Z
三个坐标。 - 使用
SetActorLocation
设置这个Actor
的新位置。
2. 输出位置:获取当前Actor的位置并输出
float fvector[3] = { NewLocation.X, NewLocation.Y, NewLocation.Z };
int statusW = WriteSimulation3DMessage(SignalWriter, sizeof(float)*3 ,fvector);
- 把当前的坐标写入到
fvector
数组中。 - 用
SignalWriter
写出这组坐标,让外部系统获取当前的位置。
🧠 额外注意事项:
Tags.Top().ToString()
作为唯一标识名拼接"Set"
与"Get"
,作为信号通道名。- 这段代码是用于 Unreal Engine 与 Simulink 3D 信号交换的接口层(Simulink + Unreal plugin 常用的方式)。
结论:这段代码确实是双向处理Actor位置的:接收 → 设置位置,输出 → 获取位置。
a. 需要我帮你加上错误处理逻辑,比如检查 statusR
/ statusW
是否成功吗?
b. 想加入一个调试输出 GEngine->AddOnScreenDebugMessage
显示当前坐标吗?
继续提问:SetActorLocation 来自SetGetActorLocation.h是么?
回答
不是的,SetActorLocation
不是 来自你自定义的 SetGetActorLocation.h
,而是:
✅ 来自 Unreal Engine 的基类 AActor
详细解释:
你的类定义是这样的:
class ASetGetActorLocation : public AActor
这说明 ASetGetActorLocation
是从 AActor
继承的。而 SetActorLocation
是 AActor
提供的公共成员函数:
🔧 SetActorLocation
定义:
bool AActor::SetActorLocation(FVector NewLocation, bool bSweep = false, FHitResult* OutSweepHitResult = nullptr, ETeleportType Teleport = ETeleportType::None);
所以结论:
SetActorLocation
是 Unreal Engine 4/5 自带的。- 它在你头文件
SetGetActorLocation.h
中没有定义,而是通过继承AActor
获得的。
a. 想看下完整的 SetGetActorLocation.h
文件结构,确认有哪些成员和继承关系?
b. 是否需要我帮你补全一个带注释的 .h
文件来配合这个 .cpp
文件使用?
继续提问
现在我想仿照上面的代码,做一个实时获取三个方向旋转的代码。可以分别叫做SetGetActorRotation.h和SetGetActorLocation.cpp。 现在要求你为我提供这两个代码。我相信也很方便,可能需要用到类似于SetActorLocation (只不过是旋转版本)的函数(应该也是继承自AActor)
回答
好的,下面是你要的两个完整文件:
✅ SetGetActorRotation.h
// Copyright 2019-2025 The MathWorks, Inc.#pragma once#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "SetGetActorRotation.generated.h"UCLASS()
class ASetGetActorRotation : public AActor
{GENERATED_BODY()public:ASetGetActorRotation();virtual void Sim3dSetup();virtual void Sim3dStep(float DeltaSeconds);virtual void Sim3dRelease();private:void* SignalReader;void* SignalWriter;
};
✅ SetGetActorRotation.cpp
// Copyright 2019-2025 The MathWorks, Inc.#include "SetGetActorRotation.h"// Sets default values
ASetGetActorRotation::ASetGetActorRotation() : SignalReader(nullptr), SignalWriter(nullptr)
{
}void ASetGetActorRotation::Sim3dSetup()
{Super::Sim3dSetup();if (Tags.Num() != 0) {unsigned int numElements = 3;FString tagName = Tags.Top().ToString();FString SignalReaderTag = tagName + TEXT("SetRot");SignalReader = StartSimulation3DMessageReader(TCHAR_TO_ANSI(*SignalReaderTag), sizeof(float) * numElements);FString SignalWriterTag = tagName + TEXT("GetRot");SignalWriter = StartSimulation3DMessageWriter(TCHAR_TO_ANSI(*SignalWriterTag), sizeof(float) * numElements);}
}void ASetGetActorRotation::Sim3dStep(float DeltaSeconds)
{unsigned int numElements = 3;float array[3];int statusR = ReadSimulation3DMessage(SignalReader, sizeof(float) * numElements, array);FRotator NewRotation;NewRotation.Roll = array[0];NewRotation.Pitch = array[1];NewRotation.Yaw = array[2];SetActorRotation(NewRotation);float frotator[3] = { NewRotation.Roll, NewRotation.Pitch, NewRotation.Yaw };int statusW = WriteSimulation3DMessage(SignalWriter, sizeof(float) * numElements, frotator);
}void ASetGetActorRotation::Sim3dRelease()
{Super::Sim3dRelease();if (SignalReader) {StopSimulation3DMessageReader(SignalReader);}SignalReader = nullptr;if (SignalWriter) {StopSimulation3DMessageWriter(SignalWriter);}SignalWriter = nullptr;
}
📌 说明
- 使用了
FRotator
来处理三维旋转角度(Roll, Pitch, Yaw),与 Unreal Engine 的坐标系统一致。 SetActorRotation
是AActor
提供的函数,类似于SetActorLocation
,用于设置 Actor 的旋转。- 信号名后缀改为
SetRot
/GetRot
,以便和位置的信号区分。
a. 需要我同时给你添加 OnScreenDebugMessage
输出当前角度调试信息吗?
b. 想加入角度范围的验证或归一化(如限制在 [-180°, 180°])吗?
继续提问
我能不能直接在现有的cpp:SetActorLocation.cpp上进行添加呀?然后重新命名为SetActorLocation_Rotation.cpp,使其同时具有读写三维坐标信息和三维朝向信息,因为我需要一个C++类的实例化实体本身具有同时具有读写三维坐标信息和三维朝向信息,并为这个实例赋予静态网格体,而不是说拆成两个实例。
回答
是的 ✅,你完全可以把 位置 + 旋转
的功能合并在一个类中,并将 .cpp
文件重命名为 SetActorLocation_Rotation.cpp
。这符合 Unreal Engine 的编程范式,也更适合你说的目标:
需要一个 C++ 类的实体同时具有:
- 读写三维位置(Location)
- 读写三维朝向(Rotation)
- 并挂载一个静态网格体组件(Static Mesh Component)
✅ 合并设计方案
类名建议:
ASetGetActorLocationRotation
✅ 功能包含:
1. Setup(创建两个通道:位置 Set/Get + 旋转 Set/Get)
2. Step(读取并设置位置和旋转;写出当前的位置和旋转)
3. Release(释放所有通道资源)
4. 添加静态网格体组件(通过 UStaticMeshComponent
)
✅ 下一步我将为你生成一个完整的版本:
.h
文件:SetGetActorLocationRotation.h
.cpp
文件:SetGetActorLocation_Rotation.cpp
是否需要我现在就为你生成完整的合并版本代码?是否你已经有绑定好的 mesh 名字,还是我用默认 placeholder?
你也可以告诉我使用哪个 .uasset
路径,我可以写到 ConstructorHelpers::FObjectFinder
里。
a. 是否希望我加入 UStaticMeshComponent
并自动绑定一个默认立方体?
b. 是否你想我把信号命名规范统一为 "SetPos"
/"GetPos"
和 "SetRot"
/"GetRot"
?