问题描述
所以,我有一艘附有“硬点”的船,可以在上面放置武器。放置后,它们会瞄准鼠标位置并限制旋转范围: See here
旋转范围基于 minAngle 和 maxAngle,并通过父硬点槽的 eulerAngles.z 加上/减去角度修改器(在本例中为 20)计算得出。我不得不做一些奇怪的旋转巫术(参见代码片段中的 OneEightyToThreeSixty())来让鼠标视角匹配与 minAngle/maxAngle 相同的格式。
角度是 -180 -> 180 度而不是 0 -> 360,就像硬点的旋转一样。编写了一个在运行时将其转换为 360 的方法。
我重写这个脚本的次数多得数不过来,但最终I'm hit with this issue.
如您所见,对于 270 度的 360 度旋转,瞄准和限制完全正常。但是在旋转的右上角四分之一处,一切都变得混乱了。
我尝试了很多不同的实现,但它们似乎都有这个一致的问题。我无法弄清楚我错过了什么。代码如下:
public class HardpointSlot : MonoBehavIoUr
{
public HardpointController ship;
public GameObject hardpoint;
public float minAngle;
public float maxAngle;
public float angle;
public float offsetAngle;
public bool switched;
void Update()
{
aimAtMouse();
}
public void aimAtMouse()
{
Vector3 dir = Input.mousePosition - Camera.main.WorldToScreenPoint(transform.position);
angle = Mathf.atan2(dir.y,dir.x) * Mathf.Rad2Deg;
minAngle = (transform.eulerAngles.z - 20) + 90f;
maxAngle = (transform.eulerAngles.z + 20) + 90f;
angle = OneEightyToThreeSixty(angle);
if (angle < minAngle)
{
angle = minAngle;
}
else if (angle > maxAngle)
{
angle = maxAngle;
}
hardpoint.transform.rotation = Quaternion.AngleAxis(angle,Vector3.forward);
}
public float OneEightyToThreeSixty(float angle)
{
float newAngle = 0f;
if (angle >= 0 && angle <= 180)
{
return angle;
} else
{
return newAngle = 360 + angle;
}
}
}
快速回顾:
- 硬点需要查看鼠标,但前提是鼠标在其瞄准范围范围内,这是由 baseaim 偏移量 (20) 和父硬点插槽的旋转计算得出的。
- 适用于 270 度旋转,但不适用于最后 90 度。
有什么想法吗?我是否遗漏了一些非常明显的东西?
解决方法
我会采取另一种方法,利用 Vector3.SignedAngle
获得从中性方向到鼠标方向的角度。然后,使用 Mathf.Clamp
将其夹在边界之间,然后使用 Quaternion.AngleAxis
创建结果方向。最后,使用 Quaternion.LookRotation
将旋转分配给硬点的变换:
public class HardpointSlot : MonoBehaviour
{
[SerializeField] HardpointController ship;
[SerializeField] GameObject hardpoint;
[SerializeField] float minAngle;
[SerializeField] float maxAngle;
[SerializeField] float angle;
void Update()
{
AimAtMouse();
}
public void AimAtMouse()
{
Vector3 dir = Camera.main.ScreenToWorldPoint(Input.mousePosition)
- transform.position;
// flatten z axis
dir.z = 0;
Vector3 neutralDir = transform.up;
float angle = Vector3.SignedAngle(neutralDir,dir,Vector3.forward);
minAngle = -20f;
maxAngle = 20f;
angle = Mathf.Clamp(angle,minAngle,maxAngle);
// rotate neutral dir by the clamped angle
dir = Quaternion.AngleAxis(angle,Vector3.forward) * neutralDir;
// set the rotation so that local up points in dir direction
// and local forward in global forward
hardpoint.transform.rotation = Quaternion.LookRotation(Vector3.forward,dir);
}
}