Unity - 2D 瞄准鼠标,同时限制最小/最大旋转并考虑父级旋转

Posted

技术标签:

【中文标题】Unity - 2D 瞄准鼠标,同时限制最小/最大旋转并考虑父级旋转【英文标题】:Unity - 2D Aim at Mouse, while restricting min/max rotation and factoring in parent rotation 【发布时间】:2021-04-13 05:12:18 【问题描述】:

所以,我有一艘船,上面附有一个“Hardpoint”,可以放置武器。放置后,它们会瞄准鼠标位置并具有有限的旋转范围: See here

旋转范围基于 minAngle 和 maxAngle,并由父硬件点槽的 eulerAngles.z 加上/减去角度修改器(在本例中为 20)计算。我不得不做一些奇怪的旋转巫术(参见代码 sn-p 中的 OneEightyToThreeSixty()),以使鼠标视角与 minAngle/maxAngle 匹配相同的格式。

角度是 -180 -> 180 度而不是 0 -> 360 度,就像挂点的旋转一样。写了一个方法在运行时将其转换为 360。

我重写这个脚本的次数已经数不胜数,但最终还是I'm hit with this issue.

如您所见,对于 360 度旋转的 270 度,瞄准和限制完全正常。但是在轮换的右上四分之一处,一切都变得混乱了。

我尝试了很多不同的实现,但它们似乎都有这个一致的问题。我无法弄清楚我错过了什么。代码如下:

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;
        


    

快速回顾一下:

Hardpoint 需要查看鼠标,但前提是鼠标在其瞄准范围范围内,该范围由 baseAim 偏移 (20) 和父 Hardpoint 插槽的旋转计算得出。 适用于 270 度旋转,但不适用于最后 90 度。

有什么想法吗?我是否遗漏了一些非常明显的东西?

【问题讨论】:

【参考方案1】:

我会采取另一种方法,利用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);
    


【讨论】:

嗨@Ruzihm,刚刚有机会应用这个解决方案,我现在遇到了这个问题。 link 鼠标越靠近变换的中心,它似乎从鼠标位置向左或向右偏移。即使鼠标位于其半径的中心,它也永远不会直接指向鼠标位置。我仍在调查,但如果我找到解决方案,我会发表评论。 @Binkling 我在方法开始时将其更改为在世界空间而不是屏幕空间中操作。看看有没有帮助 成功了!非常感谢!

以上是关于Unity - 2D 瞄准鼠标,同时限制最小/最大旋转并考虑父级旋转的主要内容,如果未能解决你的问题,请参考以下文章

基于鼠标的瞄准 Unity3d

Unity3d台球/台球瞄准问题

Unity中,允许用户通过滑动条或输入值的方式设置参数值

unity 2d角色根据鼠标转向

新人求教unity 2d 物体跟随鼠标移动的问题

Unity实用技巧