Fort achieve automatic steering (weapon) of

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/wangjiangrong/article/details/98075122

Foreword

In some shooting games, there are often similar fort weapons, you can rotate up and down, the target to aim. Or is a person who guns, in the heart of the quasi-rotation time, maintaining the direction toward the in-arms of the heart. Benpian simply carried out to achieve the effect, as shown below:

Meaning of pitch, yaw, roll under first need to know

pitch is rotation about the X-axis, also called the pitch angle (vertically rotatable arms), as shown:

yaw is rotation about the Y axis, also called the yaw angle (rotation around arms), as shown:

roll is rotation around the Z-axis, also called roll angle, as shown:

According to demand, we generally only need to implement the pitch and yaw rotation can be weapons, aiming to achieve the specified location effect.

Thinking

First fort similar, generally barrel and barrel will turn separately, such as a gun barrel rotatable about only (Yaw), barrel rotate up and down (pitch). We need two Transform to control the rotation, where the gun barrel to be used as body control. But the kind of firearms generally would not be split into two controls, so we put two Transform also point to the same controls. At the same time and then point to aim at a Transform object, and we can set some maximum rotation angle limit.

Requirement 1, was aiming weapons has been aimed at, but when the aim was not to aim the weapon behind process: weapons may be calculated to a positive angle directly in front thereof and weapons targeting, if the angle of <90 degrees, i.e., do aiming operations, otherwise, not processed.

需求2,yaw旋转:即根据Y轴旋转,eulerAngles.y进行变动,物体呈左右转动之势。因为是左右旋转,所以我们可以忽略武器和瞄准物的Y轴高度差距,使两者在同一高度的情况下(可以使用Vector3.ProjectOnPlane,将武器到瞄准物的向量映射到武器的xz平面上),计算武器forward的向量和武器到瞄准物的向量之间的夹角,若夹角为0则已瞄准,否则则改动eulerAngles.y的值,使Transform.forward变动,从而让夹角为0。(我们可以利用向量的叉乘Vector3.Cross,来判断两个向量之间的左右关系

需求3,picth旋转:基本和yaw旋转同理,只是改变的是eulerAngles.x的值。

实现

直接上代码,绑定在武器的父节点GameObject上,绑定好对应关联即可

using UnityEngine;

public class AutoRotationGun : MonoBehaviour
{
    //最大旋转角度限制
    public int MaxPitchAngle = 60;
    public int MaxYawAngle = 60;

    //旋转速度
    public int Speed = 20;
    
    //pitch转动的物体
    public Transform PitchTransform;
    //yaw转动的物体
    public Transform YawTransform;
    //瞄准物
    public Transform TargetTransform;

    Vector3 mPitchTarget, mYawTarget;
    float mCurrentPitchAngle, mCurrentYawAngle;

    //精度
    float mPrecision = 0.5f;

    Transform mTransform;

    float mPitchAngleOffset, mYawAngleOffset, mAimAngleOffset;
    Vector3 mPitchCross, mYawCross;

    void Start()
    {
        mTransform = transform;
    }

    void Update()
    {
        if (TargetTransform != null && IsCanAim())
        {
            //旋转不使用PitchTransform.Rotate(x,y,z),防止z轴的变化
            if (PitchTransform == YawTransform)
            {
                PitchTransform.localEulerAngles = new Vector3(PitchRotation(), YawRotation(), 0);
            }
            else
            {
                PitchTransform.localEulerAngles = new Vector3(PitchRotation(), 0, 0);
                YawTransform.localEulerAngles = new Vector3(0, YawRotation(), 0);
            }
        }
#if UNITY_EDITOR
        Debug.DrawRay(PitchTransform.position, PitchTransform.forward * 100, Color.red);
#endif
    }

    bool IsCanAim()
    {
        //武器到瞄准物的向量与武器的正前面的夹角在90度以内才可瞄准
        if (PitchTransform != null && YawTransform != null)
        {
            //mAimAngleOffset = Mathf.Acos(Vector3.Dot(transform.forward, (TargetTransform.position - PitchTransform.position).normalized)) * Mathf.Rad2Deg;
            mAimAngleOffset = Vector3.Angle(mTransform.forward, TargetTransform.position - PitchTransform.position);
            if (mAimAngleOffset < 90)
            {
                return true;
            }
        }
        return false;
    }

    float PitchRotation()
    {
        //当前旋转角度
        mCurrentPitchAngle = PitchTransform.localEulerAngles.x;
        if (mCurrentPitchAngle > 180)
        {
            mCurrentPitchAngle = -(360 - mCurrentPitchAngle);
        }
        
        //武器到瞄准物的向量,映射到武器的yz屏幕上的法向量
        mPitchTarget = Vector3.ProjectOnPlane(TargetTransform.position - PitchTransform.position, PitchTransform.right).normalized;
        
        //计算当前瞄准方向与预期方向的夹角。大于精度则需要pitch转动来调整
        mPitchAngleOffset = Vector3.Angle(PitchTransform.forward, mPitchTarget);

        if (mPitchAngleOffset > mPrecision)
        {
            //计算两个向量的叉乘,用于判断向量的左右关系
            mPitchCross = Vector3.Cross(mPitchTarget, PitchTransform.forward).normalized;
            if (mCurrentPitchAngle > -MaxPitchAngle && mPitchCross == PitchTransform.right)
            {
                return mCurrentPitchAngle - Speed * Time.deltaTime;
            }
            else if (mCurrentPitchAngle < MaxPitchAngle && mPitchCross != PitchTransform.right)
            {
                return mCurrentPitchAngle + Speed * Time.deltaTime;
            }
        }
        return mCurrentPitchAngle;
    }

    float YawRotation()
    {
        mCurrentYawAngle = YawTransform.localEulerAngles.y;
        if (mCurrentYawAngle > 180)
        {
            mCurrentYawAngle = -(360 - mCurrentYawAngle);
        }

        mYawTarget = Vector3.ProjectOnPlane(TargetTransform.position - YawTransform.position, YawTransform.up).normalized;
        mYawAngleOffset = Vector3.Angle(YawTransform.forward, mYawTarget);

        if (mYawAngleOffset > mPrecision)
        {
            mYawCross = Vector3.Cross(mYawTarget, YawTransform.forward).normalized;
            if (mCurrentYawAngle > -MaxYawAngle && mYawCross == YawTransform.up)
            {
                return mCurrentYawAngle - Speed * Time.deltaTime;
            }
            else if (mCurrentYawAngle < MaxYawAngle && mYawCross != YawTransform.up)
            {
                return mCurrentYawAngle + Speed * Time.deltaTime;
            }
        }
        return mCurrentYawAngle;
    }
}

 

Guess you like

Origin blog.csdn.net/wangjiangrong/article/details/98075122