c# - 如何限制矢量的角度?

标签 c# unity3d

我尝试编写一个脚本来显示手指跟随的 Sprite 。但是我需要这个 Sprite 只能在距 anchor 指定的距离上移动,并且只能在指定的角度之间移动。现在,我有下一个代码:

public class GunPowerController : MonoBehaviour {

    public GameObject _fingerprint;
    public Transform _anchor;
    public Gun _gun;
    public float _maxPower = 1f;
    public float _maxAngle = 15f;
    public float _minAngle = 0f;

    private Camera _camera;
    private GameObject _fingerprintInstance;

    void Awake()
    {
        _maxPower = Mathf.Abs(_maxPower);
        _camera = Camera.main;
    }

    // Update is called once per frame
    void Update ()
    {
        if (Input.GetMouseButtonDown(0))
        {
            var touchWorldPosition = _camera.ScreenToWorldPoint(Input.mousePosition);
            var hitInfo = Physics2D.Raycast(touchWorldPosition, Vector2.zero);

            if (hitInfo && hitInfo.transform.gameObject.Equals(gameObject))
            {
                touchWorldPosition.z = transform.position.z;
                _fingerprintInstance = (GameObject)Instantiate(_fingerprint, touchWorldPosition, Quaternion.identity);
            }
        }
        else if (_fingerprintInstance != null)
        {

            if (Input.GetMouseButtonUp(0))
            {
                Destroy(_fingerprintInstance);
            }
            else
            {
                var touchWorldPosition = _camera.ScreenToWorldPoint(Input.mousePosition);
                Move(touchWorldPosition);
            }
        }
    }

    private void Move(Vector3 target)
    {
        target.z = transform.position.z;
        Vector3 distance = target - _anchor.position;
        Vector3 axis = _anchor.position;
        axis.x = -1f;
        float angle = Vector3.Angle(axis, distance) * Mathf.Sign(distance.y - axis.y);

        if (distance.sqrMagnitude > _maxPower * _maxPower)
        {
            distance.Normalize();
            distance *= _maxPower;
            target = _anchor.position + distance;
        }

        if(_minAngle > angle)
        {
            //Here I need to hold vector rotation while the user doesn't
            //return to the available space between angles.
        }
        else if (_maxAngle < angle)
        {
            //Here I need to hold vector rotation while the user doesn't
            //return to the available space between angles.
        }

        _fingerprintInstance.transform.position = Vector3.Lerp(_fingerprintInstance.transform.position, target,
            10f * Time.deltaTime);
    }
}

我尝试根据差异 _min|maxAngle - angle 旋转矢量 target 但它工作不正常。怎么做到的?
目前的问题: Scheme
附言我重试了很多变体,但没有成功。如果需要一些细节,请写信给我,我会发布。

最佳答案

基本上,我不是试图计算旋转数学,而是在法线(但具有与目标向量相同的幅度)之间 lerp,将其视为零旋转,以及上限向量,并使用矢量超过了目标角度的上限,以确定 lerp 的距离。

public static Vector3 ClampAngle(Vector3 vector, Vector3 normal, float maxAngle, float magnitude = float.NaN)
{
    //Get the angle between the normal and the current vector
    float angle = Vector3.Angle(normal, vector);

    //If the angle isn't greater than max angle, then we don't need to do anything
    if(angle > maxAngle)
    {
        //Avoid sqr root calculation in magnitude if we already know it, otherwise get magnitude from the original vector
        if(float.IsNaN(magnitude))
        {
            magnitude = vector.magnitude;
        }

        //Value becomes the percentage from zero to our overcapped angle, so by lerping to that percentage place we can shift the vector to the max angle
        float value = maxAngle / angle;

        //We use the given normal, times the magnitude of the original line to get our un-rotated positon, we then multiply that by value to apropriatlly
        //shorten the vector based on how long it would have to have been to be a the same position at a different angle.
        //Then we lerp betwen that vector and the original vector to find a vector that has an angle that is not greater than given angle based on the percentage value we got above.
        vector = Vector3.Lerp(normal.normalized * magnitude * value, vector, value);
    }
    
    //Return the vector
    return vector;
}

关于c# - 如何限制矢量的角度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38555988/

相关文章:

c# - 如何在Twitter更新中处理ISO-2022-JP(和其他字符集)?

c# - 如何将此循环写成一行?

c# - 设置与高度/宽度相关的图像 DPI C#

c# - 代码剥离错误 Unity

unity3d - Vuforia - 使用 Cardboard 时看不到地形

c# - 如何从unity 3d中的另一个对象访问相机

ios - 如何在iOS上修复Ironsource Unity SDK中的错误

c# - MVC4 中的 Styles.Render

c# - MVC App_GlobalResources,使用本地并发布

c# - 在Unity3D中无法接收来自PLC的C#UDP消息,但在Wireshark中可见