C# 有没有一种方法可以使用四元数。FromToRotation支持使用一个轴?
我已经为这个问题挣扎了太多个小时,现在是我向你寻求帮助的时候了 形势 我有一个移动的角色,我四处走动,并与它行走的表面对齐。我通过光线投射到下一个它将要打开的曲面,并获得与曲面对齐所需的旋转来实现这一点C# 有没有一种方法可以使用四元数。FromToRotation支持使用一个轴?,c#,unity3d,quaternions,C#,Unity3d,Quaternions,我已经为这个问题挣扎了太多个小时,现在是我向你寻求帮助的时候了 形势 我有一个移动的角色,我四处走动,并与它行走的表面对齐。我通过光线投射到下一个它将要打开的曲面,并获得与曲面对齐所需的旋转来实现这一点 Quaternion newRotation = Quaternion.FromToRotation(transform.up, foundSurface.normal) * transform.rotation; 角色是一个称为Modelholder的变换,它可以平滑地旋转到新的旋转,并使用
Quaternion newRotation = Quaternion.FromToRotation(transform.up, foundSurface.normal) * transform.rotation;
角色是一个称为Modelholder的变换,它可以平滑地旋转到新的旋转,并使用
modelHolder.rotation = Quaternion.Slerp(modelHolder.rotation, newRotation, Time.deltaTime * modelRotationSmoothing);
modelHolder的内部是模型。我根据鼠标的下颌运动更改model.localRotation.y
摄影机只是一个跟随modelholder的变换,并且有一个称为Rotator的子变换,该变换也基于鼠标移动进行旋转(这次是下巴和俯仰)。摄影机是此旋转器变换的子对象
有了这个,我可以走上人行道和天花板,同时与所有东西对齐,非常整洁
问题
我制作了一个抓钩,可以将角色移动到抓钩表面。飞行结束时的重新对齐方式与步行对齐方式相同。这一切都很好,除非你从地面抓斗到天花板(反之亦然)。当我向东或向西看时,模型似乎会做一个“桶形滚动”来重新对齐到新曲面,但当我向北或向南看时,模型会做一个向后或向前翻转
模特儿运动:
模型运动:
桶形滚转很好,但我想找到一种旋转的方式,这样玩家在着陆后就不会朝相反的方向看(或者从天花板上跳下来,同时朝北或向南看,因为这样重新对准重力也会导致翻转),因为翻转是可怕的迷失方向
我尝试过的事情:
- 我试着不把模特和模特分开。这并不能解决问题,只会给我带来更多的问题,因为我有一个平滑但反应灵敏的摄像头
- 我尝试在重新对齐之前保存lookdirection,并在重新对齐时将其旋转到旧的lookdirection。 这只是做了一个超级奇怪的翻转,这是更迷惑
- 我试着检测新旧旋转之间的比较差异,看看我是否能“检测”出它什么时候想要翻转,什么时候想要滚桶,这样我就可以对抗它了。我只感到困惑和沮丧
新旋转
,该旋转在使局部向上成为曲面法线的同时,尽可能保持前进方向
FromToRotation
仅保证使用时的一个对齐轴。相反,您可以使用叉积和四元数.LookRotation
进行所需的计算
Vector3 newPlayerRight = Vector3.Cross(foundSurface.normal, modelHolder.forward);
Vector3 newPlayerForward = Vector3.Cross(newPlayerRight, foundSurface.normal);
Quaternion newRotation = Quaternion.LookRotation(newPlayerForward, foundSurface.normal);
然后,您可以像以前一样继续:
modelHolder.rotation = Quaternion.Slerp(modelHolder.rotation, newRotation,
Time.deltaTime * modelRotationSmoothing);
虽然我不赞成将Slerp/Lerp方法与t
一起使用,但它不能保证达到或超过1。我建议改为使用四元数。旋转方向:
float modelRotationSpeed = 180f;
modelHolder.rotation = Quaternion.RotateTowards(modelHolder.rotation, newRotation,
Time.deltaTime * modelRotationSpeed);
为了保持相对于刚穿过的边的前向角度,可以尝试其他方法:
Quaternion newRotation;
// ..
Vector3 previousSurfaceNormal = modelHolder.up;
Vector3 previousForward = modelHolder.forward;
bool flyingOrFallingToNewSurface;
if (flyingOrFallingToNewSurface)
{
Vector3 newPlayerRight = Vector3.Cross(foundSurface.normal, modelHolder.forward);
Vector3 newPlayerForward = Vector3.Cross(newPlayerRight, foundSurface.normal);
newRotation = Quaternion.LookRotation(newPlayerForward, foundSurface.normal);
} else
{
// This direction lies in both surfaces.
Vector3 edgeTraversed = Vector3.Cross(previousSurfaceNormal, foundSurface.normal);
// Find the angle from edgeTraversed to previousForward
float ang = Vector3.SignedAngle(edgeTraversed, previousForward, previousSurfaceNormal);
// Find newForward in new plane that's the same angle
Vector3 newPlayerForward = Quaternion.AngleAxis(ang,foundSurface.normal) * edgeTraversed;
newRotation = Quaternion.LookRotation(newPlayerForward, foundSurface.normal);
}
// ...
float modelRotationSpeed = 180f;
modelHolder.rotation = Quaternion.RotateTowards(modelHolder.rotation, newRotation,
Time.deltaTime * modelRotationSpeed);
我爱你,爱你,爱你拍摄了一段你的问题的视频,让你的模型看起来像统一轴。我真的希望更多的人在问起旋转的时候会这么做。这个脚本是附加在什么对象上的?为什么要使用transform.up
而不是modelHolder.up
?@RobinHerben感谢您的回复。今天晚些时候,我将对此进行另一次尝试。@RobinHerben我要求对这个问题进行澄清,但与此同时,如果您执行Vector3 newPlayerRight=Vector3.Cross(foundSurface.normal,modelHolder.forward),会发生什么情况代码>相反?那也不行。但是我没有一个单独的模型和模型持有者,而是通过使用交叉积和lookrotation方法来实现的!将您的答案标记为已接受,谢谢@RobinHerben我想问一个新问题,包括关于你现在正在使用的东西的信息(对于初学者来说,我不知道你的相机是如何设置的),但类似的东西可能会有所帮助:Vector3先前的CameraForward代码>四元数cameraPivotGoal=四元数.LookRotation(以前的CameraForward,foundSurface.normal)代码>cameraHolder.rotation=Quaternion.rotatetowwards(camerrapivot.rotation,camerrapivotgoal,Time.deltaTime*cameraRotationSpeed)
/*更新相机控制器内部值*/
(假设您的相机有一个像这里这样的枢轴父级)@RobinHerbern我明白了,这就把事情弄清楚了。好吧,只有当你沿着地面移动时,这才有意义,而这不是问题的初衷。在像这样的“行走”的情况下,旋转轴是固定的,你需要保持向前相对于旋转轴的方向不变。在飞行/坠落的情况下,你关心的是绝对向前,旋转轴是保持尽可能接近它所需要的。我在我的答案中添加了一部分,希望能解决这个问题。如果没有帮助,请考虑问一个单独的问题。