向量的应用

点乘求角度,叉乘求方向

比如敌人再附近,点乘可以求出玩家面朝方向和敌人方向的夹角,叉乘可以得出左转还是右转更好的转向敌人

Part 1 点乘:

数学上的 点乘为 a * b = |a| * |b| * cos(Θ)

Unity中的点乘也是如此 点乘结果为 float 是投影长度

点乘的主要作用就是,点乘求角度。 Θ = Arcos( a * b / |a| * |b|)

代码实现:

        float tmpNormalized = Vector3.Dot(attacked.right.normalized, tmpDistance.normalized);      //计算出在攻击方向的单位向量上的投影

        float tmpRadian = Mathf.Acos(tmpNormalized);    //计算出弧度

        float tmpAngle = Mathf.Rad2Deg * tmpRadian; //弧度转换为角度


点乘的方法是

Vector3.Dot(向量A,向量B);   得到的结果是数  即 B在A上的投影长度

例如:

tmpDistanceX = Vector3.Dot(attacker.right, tmpDis); //即tmpDis 在 attacker.right向量上的投影长度

点乘的简单应用A:设置矩形体区域

    ///

/// 以攻击点为中心,长为 2 * distance 宽为 2 * half 高为2 * height的矩形体范围

    ///

    /// 生成范围的中心点的位置

    /// 目标物体的位置

    /// 中心点到两侧的宽度,实际宽度为2倍长度

    /// 中心点到最远攻击点的距离

    /// 中心点到最高的距离

    ///

    private bool RectAttack(Transform attacker, Transform attacked, float half, float distance, float height)    //生成一个矩形体范围的碰撞区域

    {

        Vector3 tmpDis = attacked.position - attacker.position;    //算出攻击者和被攻击者之间的向量差

        float tmpDistanceX, tmpDistanceY, tmpDistanceZ;

        tmpDistanceX = Vector3.Dot(attacker.right, tmpDis);        //算出向量差在 攻击方向上的投影,设攻击方向为  right

        Debug.Log("tmpDistance.X = " + tmpDistanceX);

        //float tmpDistance = Vector3.Distance(attacker.position, attacked.position);      //实际距离

        //Debug.Log("tmpDistance = " + tmpDistance);         

        if (tmpDistanceX >= 0 && tmpDistanceX <= distance)    //判断投影是在 攻击方向正面,且在攻击范围内

            //排除了目标在攻击点背后的情况

        {

            tmpDistanceZ = Mathf.Abs(Vector3.Dot(attacker.forward, tmpDis));              //计算向量差在 攻击范围横轴上的距离

            tmpDistanceY = Mathf.Abs(Vector3.Dot(attacker.up, tmpDis));            //计算向量差在 攻击范围横轴上的距离

            if (tmpDistanceZ <= half && tmpDistanceY <= height)            //在范围内则进行攻击

            {

                Debug.Log("Attacked!!!");

                      return true;

            }

        }

        return true;

    }

点乘的简单应用B:设置扇形体区域

    ///

    /// 以攻击点为中心,到任一点夹角为45°,且长度为radius的扇形体区域

    /// 扇形所指的为 以攻击点为固定点,长度为radius,角度为 2 * angle的覆盖区域

    ///

    /// 攻击者的位置

    /// 被攻击者的位置

    /// 攻击点到其中一侧的夹角,即整个扇形角度为 2 * angle

    ///

    ///

    private bool UmbrallaAttack(Transform attacker, Transform attacked, float angle, float radius)      //生成一个扇形体范围的碰撞区域

    {

        Vector3 tmpDistance = attacked.position - attacker.position;        //算出攻击者和被攻击者之间的向量差

        //取值范围 [-1, 1]

        float tmpNormalized = Vector3.Dot(attacked.right.normalized, tmpDistance.normalized);      //计算出在攻击方向的单位向量上的投影

        float tmpRadian = Mathf.Acos(tmpNormalized);    //计算出弧度

        float tmpAngle = Mathf.Rad2Deg * tmpRadian;

        float tmpDis = tmpDistance.magnitude;          //已知向量,求tmpDistance的距离长度

        //float tmpDis2 = Vector3.Distance(attacker.position, attacked.position);    //求两点间的距离长度

        //Debug.Log("tmpAngle == " + tmpAngle + "tmpDis == " + tmpDis + "tmpDis2 == " + tmpDis2);

        if(tmpAngle <= angle && tmpDis <= radius)

        {

            Debug.Log("Attack!!!");

            return true;

        }

        return false;

    }


Part 2 叉乘:

数学上的叉乘 使用右手定则 确认 结果向量方向

Unity中的叉乘 使用左手定则 确认结果向量方向

叉乘方法

Vector3.Cross(tmpA, tmpB) 叉乘结果是一个向量

**叉乘的主要应用是:**求方向

在同一平面内, 结果 > 0 表示 B在A的逆时针方向, 结果 <0 表示B在A的顺式针方向, 结果 = 0表示B与A同向

左手定则:

Vector3.Cross(tmpA, tmpB) tmpA为大拇指,食指为tmpB, 其余三指自然弯曲90°即为叉乘结果

叉乘简单应用:判断方向

    private void CrossTest(Vector3 tmpA, Vector3 tmpB)

    {

        Vector3 result = Vector3.Cross(tmpA, tmpB);

        if(result.y> 0){

            Debug.Log("tmpB在tmpA的顺时针方向");

        }

        if (result.y == 0){

            Debug.Log("tmpB在tmpA同向");

        }

        if (result.y < 0)   {

            Debug.Log("tmpB在tmpA的逆时针方向");

        }

    }

    void Update()    {

        Vector3 tmpA = attacked.position - transform.position;

        Vector3 tmpB = newAttacked.position - transform.position;

        CrossTest(tmpB, tmpA);

    }


测试结果:

Part 3 点乘和叉乘的综合应用:

点乘求出相差角度,叉乘求出转向

让AI朝玩家方向自动移动,转向

    void Update()

    {

        Vector3 tmpVector = Player.transform.position - transform.position;

        float tmpDistance = tmpVector.magnitude;        //计算AI到Player之间的距离

        //Debug.Log("Distance == " + tmpDistance);

        if (tmpDistance <= 7)

        {

            TimeCount += 0.1f;

            if (TimeCount >= 0)

            {

                Debug.Log("Attack!!!");

                BulletParent.GetComponent().GenBullet();    //调用子弹实例化脚本方法

                TimeCount = 0;

            }

            //transform.LookAt(Player);

        }

        else

        {

            Vector3 tmpCross = Vector3.Cross(transform.forward, tmpVector);    //叉乘计算书 玩家在AI的哪一侧

            if(tmpCross.y >= 0)

            {

                transform.Rotate(Vector3.up, 0.5f);

            }

            if (tmpCross.y < 0)

            {

                transform.Rotate(Vector3.up, -0.5f);

            }

            transform.Translate(Vector3.forward* 0.02f, Space.Self);

        }

    }

}

你可能感兴趣的:(向量的应用)