解决UE4万向节锁(Gimbal Lock)的问题
一、问题描述 在开发类似飞行类游戏的时候往往需要将相机的旋转范围设置到[-180~180],但引擎默认会将pitch和roll两个轴向限定到[-90~90],这并不是一个bug,是引擎为了适配FPS游戏所做的限制,你可以垂直向上或者向下看,超过这个角度就没有意义了且会导致万向节锁的现象,为了避免这种现象我们可以采用四元数的方法。 二、解决步骤 使用的是飞行模板,创建自己的GameMode和Controller和pawn并在worldSettings中设置为我们的GameMode。如图示1.1(注意Pawn类中要加入Camera组件) 1 2 图示1.1 项目设置中添加输入,如图示1.2 1 2 图示1.2 接下来是主要的一步,使用四元数的方法解决万向节锁的现象。为了方便使用,我这里写成了一个插件。如图1.3所示,选择模板“BlueprintLibrary”,创建一个插件。 1 2 图示1.3 打开VS,将如下代码加入到.h和.cpp中。注意:在cpp中将函数名称“UMyFunctionName”替换为自己的类名称。如图1.4所示 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 public: // 旋转公式:将欧拉角的度数转换为四元数 UFUNCTION(BlueprintCallable, meta = (DisplayName = "Euler To Quaternion", Keywords = "rotation, quaterion"), Category = "Quaternion Rotation") static FQuat Euler_To_Quaternion(FRotator Current_Rotation); // 根据输入的四元数设置组件的世界坐标的旋转 UFUNCTION(BlueprintCallable, meta = (DisplayName = "Set World Rotation (Quaterion)", Keywords = "rotation, quaternion"), Category = "Quaternion Rotation") static void SetWorldRotationQuat(USceneComponent* SceneComponent, const FQuat& Desired_Rotation); // 根据输入的四元数设置组件的相对旋转 UFUNCTION(BlueprintCallable, meta = (DisplayName = "Set Relative Rotation (Quaterion)", Keywords = "rotation, quaternion"), Category = "Quaternion Rotation") static void SetRelativeRotationQuat(USceneComponent* SceneComponent, const FQuat& Desired_Rotation); // 添加本地旋转量 UFUNCTION(BlueprintCallable, meta = (DisplayName = "Add Local Rotation (Quaterion)", Keywords = "rotation, quaternion"), Category = "Quaternion Rotation") static void AddLocalRotationQuat(USceneComponent* SceneComponent, const FQuat& Delta_Rotation); // 根据输入的四元数设置Actor的世界坐标的旋转 UFUNCTION(BlueprintCallable, meta = (DisplayName = "Set Actor World Rotation (Quaternion)", Keywords = "rotation, quaternion"), Category = "Quaternion Rotation") static void SetActorWorldRotationQuat(AActor* Actor, const FQuat& Desired_Rotation); //根据输入的四元数设置Actor的相对旋转 UFUNCTION(BlueprintCallable, meta = (DisplayName = "Set Actor Relative Rotation (Quaternion)", Keywords = "rotation, quaternion"), Category = "Quaternion Rotation") static void SetActorRelativeRotationQuat(AActor* Actor, const FQuat& Desired_Rotation); // 添加本地旋转量 UFUNCTION(BlueprintCallable, meta = (DisplayName = "Add Actor Local Rotation (Quaternion)", Keywords = "rotation, quaternion"), Category = "Quaternion Rotation") static void AddActorLocalRotationQuat(AActor* Actor, const FQuat& Delta_Rotation); FQuat UQuaternoinsBPLibrary::Euler_To_Quaternion(FRotator Current_Rotation) { //声明输出四元数 FQuat q; //将度数转换为弧度 float yaw = Current_Rotation....