加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Unity 3D追踪效果的实现 目标箭头指引

(2017-01-06 14:25:00)
标签:

unity

目标

目标箭头

任务指引

3d追踪

分类: Unity起航

版本:unity 5.4.1  语言:C#

 

有段时间没写博客了,就搞搞自己的小游戏自娱自乐。

 

今天给大家带来3D空战或者宇宙飞行目标箭头的显示,参考了网友ζ随风去旅行的2D指引效果,自己研究了3D效果的实现。

 

下面是代码:

public class CArrowLockAt : MonoBehaviour

{

    public Transform target;    //目标

    public Transform self;  //自己

 

    public float direction; //箭头旋转的方向,或者说角度,只有正的值

    public Vector3 u;   //叉乘结果,用于判断上述角度是正是负

 

    float devValue = 10f;   //离屏边缘距离

    float showWidth;    //由devValue计算出从中心到边缘的距离(宽和高)

    float showHeight;

 

    Quaternion originRot;   //箭头原角度

 

    // 初始化

    void Start()

    {

        originRot = transform.rotation;

        //showWidth = Screen.width / 2 - devValue;

        //showHeight = Screen.height / 2 - devValue;

    }

 

    void Update()

    {

        // 每帧都重新计算一次,主要是调试使用方便

        showWidth = Screen.width / 2 - devValue;

        showHeight = Screen.height / 2 - devValue;

 

        // 计算向量和角度

        Vector3 forVec = self.forward;  //计算本物体的前向量

        Vector3 angVec = (target.position - self.position).normalized;  //本物体和目标物体之间的单位向量

 

        Vector3 targetVec = Vector3.ProjectOnPlane(angVec - forVec, forVec).normalized; //这步很重要,将上述两个向量计算出一个代表方向的向量后投射到本身的xy平面

        Vector3 originVec = self.up;

 

        direction = Vector3.Dot(originVec, targetVec);  //再跟y轴正方向做点积和叉积,就求出了箭头需要旋转的角度和角度的正负

        u = Vector3.Cross(originVec, targetVec);

 

        direction = Mathf.Acos(direction) * Mathf.Rad2Deg;  //转换为角度

 

        u = self.InverseTransformDirection(u);  //叉积结果转换为本物体坐标

 

        // 给与旋转值

        transform.rotation = originRot * Quaternion.Euler(new Vector3(0f, 0f, direction * (u.z > 0 ? 1 : -1)));

 

        // 计算当前物体在屏幕上的位置

        Vector2 screenPos = Camera.main.WorldToScreenPoint(target.position);

        

        //if(Vector3.Dot(forVec, angVec) < 0)

        // 不在屏幕内的情况

        if(screenPos.x < devValue || screenPos.x > Screen.width - devValue || screenPos.y < devValue || screenPos.y > Screen.height - devValue || Vector3.Dot(forVec, angVec) < 0)

        {

            Vector3 result = Vector3.zero;

            if (direction == 0) //特殊角度0和180直接赋值,大家知道tan90会出现什么结果

            {

                result.y = showHeight;

            }

            else if (direction == 180)

            {

                result.y = -showHeight;

            }

            else    //非特殊角

            {

                // 转换角度

                float direction_new = 90 - direction;

                float k = Mathf.Tan(Mathf.Deg2Rad * direction_new);

 

                // 矩形

                result.x = showHeight / k;

                if ((result.x > (-showWidth)) && (result.x < showWidth))    // 角度在上下底边的情况

                {

                    result.y = showHeight;

                    if (direction > 90)

                    {

                        result.y = -showHeight;

                        result.x = result.x * -1;

                    }

                }

                else    // 角度在左右底边的情况

                {

                    result.y = showWidth * k;

                    if ((result.y > -showHeight) && result.y < showHeight)

                    {

                        result.x = result.y / k;

                    }

                }

                if (u.z > 0)

                    result.x = -result.x;

            }

            transform.localPosition = result;

        }

        else    // 在屏幕内的情况

        {

            transform.position = screenPos;

        }

    }

}

 

过完年之后好好确定一下今年计划,说不定给大家带来3D游戏开发大师的读书心得,期待一下咯。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有