Unity—四元数、欧拉角API+坐标系统

每日一句:做喜欢的事是没有截止日期的

补上这两天的~

目录

练习:计算物体右前方30度,10m远的坐标

练习:计算爆炸点到玩家两个切点坐标

//投影测试ProjectOnPlane

将当前物体移动(要过程)(欧拉角)

四元数API

练习:根据用户输入的方向旋转角色,并向前移动

坐标系统

Unity坐标系

扫描二维码关注公众号,回复: 15023278 查看本文章

World Space

Local Space

Screen Space

Viewport Space

坐标系转换

Local Space—>World Space

World Space—>Local Space

World Space<—>Local Space

World Space<—>Viewport Space

练习:如果移出屏幕外,停止运动,(可返回);移出屏幕上边界,下边界返回,移出左边界,右边界返回


练习:计算物体右前方30度,10m远的坐标

public Vector3 vect;

    void Update()

    {

        Debug.DrawLine(this.transform.position, vect);

        vect = this.transform.position + Quaternion.Euler(0, 30, 0) *this.transform.rotation * new Vector3(0, 0, 10);

}

this.transform.position + 把向量移到当前物体位置

*this.transform.rotation * new Vector3(0, 0, 10)向量随当前物体的旋转而旋转

练习:计算爆炸点到玩家两个切点坐标

已知:玩家半径Radius,玩家、炸弹位置

思路:1.计算玩家到爆炸点方向,半径长向量

           2.根据夹角旋转该向量

脚本给炸弹,本身就知道炸弹位置了

(两个物体没关系怎么找,用标签找)

 

 

public string playerTag = "Player";

    private Transform playerTF;

    private float radius;

    void Start()

    {

        GameObject playerGO = GameObject.FindWithTag(playerTag);//获取玩家的游戏对象

        playerTF = playerGO.transform;

        radius = playerGO.GetComponent<CapsuleCollider>().radius;

    }

    private Vector3 leftTangent,rightTangent;

    void Update()

    {

        Vector3 playerToExplosion = this.transform.position - playerTF.position;

        Vector3 playerToExplosionDirection = playerToExplosion.normalized * radius;

        float angle = Mathf.Acos(radius / playerToExplosion.magnitude) * Mathf.Rad2Deg;

        leftTangent = Quaternion.Euler(0, -angle, 0) * playerToExplosionDirection + playerTF.position;

        rightTangent = Quaternion.Euler(0, angle, 0) * playerToExplosionDirection + playerTF.position;

        Debug.DrawLine(this.transform.position, leftTangent, Color.red);

        Debug.DrawLine(this.transform.position, rightTangent, Color.red);

}

效果展示:

 

 sqrMagnitude 模长的平方 若只比较两向量长度,用sqrMagnitude,比magnitude少开方了,节省性能

Vector3.OrthoNormalize(ref Vector3 normal,ref Vector3 tangent,ref Vector3 binormal)

将向量标准化,返回tangent、binormal与normal是垂直关系

//投影测试ProjectOnPlane

 

public Transform t1;

 public Vector3 planeNorm;

 private void Update()

    {

        Vector3 result = Vector3.ProjectOnPlane(t1.position, planeNorm);

        Debug.DrawLine(Vector3.zero, result, Color.red);

        Debug.DrawLine(Vector3.zero, t1.position);

}

将当前物体移动(要过程)(欧拉角)

//匀速移动,能达到目标点

this.transform.position=Vector3.MoveTowards(this.transform.position,new Vector3(0,0,10),0.1f);(起点,终点,速度)

//先快后慢,不能到达目标点(无限接近)//终点、比例固定

this.transform.position=Vector3.Lerp(this.transform.position,new Vector3(0,0,10),0.1f);

//自然移动

public AnimationCurve curve;//动画曲线

private float x;

public float duration=3;//持续时间(3秒钟到达终点)

private void Update()

{ x+=Time.deltaTime/duration;//累加每帧消耗的时间

  this.transform.position=Vector3.Lerp(Vector3zero,

new Vector3(0,0,10),curve.Evaluate(x));

四元数API

四元数—>欧拉角

Quaternion qt=this.transform.rotation;

Vector3 euler=qt.eulerAngles;

轴/角旋转

Quaternion Quaternion.AngleAxis(float angle,Vector3 axis);(角,轴向)

this.transform.rotation=Quaternion.AngleAxis(50,Vector3.up);

(等同Quaternion.Euler(0,50,0);)

//注视旋转(z轴)

public Transform tf;//当前物体注视tf旋转

Vector3 dir=tf.position-this.transform.position;//当前物体注视tf旋转

this.transform.rotation=Quaternion.LookRotation(dir);//可以分成多帧

(this.transform.LookAt(tf);)//一帧就变了

//差值旋转Lerp,匀速旋转Quaternion.RotateTowards

Quaternion dir=Quaternion.LookRotation(tf.position-this.transform.position);

this.transform.rotation=Quaternion.Lerp(this.transform.rotation,dir,0.1f);

Quaternion dir = Quaternion.Euler(0, 90, 0);

    void Update()

    {

        this.transform.rotation = Quaternion.Lerp(this.transform.rotation, dir, 0.1f);

        //如果当前旋转角度,接近目标旋转角度

        if(Quaternion.Angle(this.transform.rotation,dir)<1)

        {

            this.transform.rotation = dir;

        }

    }

//x轴注视旋转

this.transform.right=tf.position-this.transform.position;

想慢慢转—>凑Lerp—>四元数

Quaternion dir=Quaternion.FormToRotation

(Vector3.right,tf.position-this.transform.position);

练习:根据用户输入的方向旋转角色,并向前移动

public float moveSpeed = 3;

    public float rotateSpeed = 2;

    private void Update()

    {

        float hor = Input.GetAxis("Horizontal");

        float ver = Input.GetAxis("Vertical");

        Quaternion dir = Quaternion.LookRotation(new Vector3(hor, 0, ver));

        this.transform.rotation = dir;

        this.transform.rotation = Quaternion.Lerp(this.transform.rotation, dir, Time.deltaTime * rotateSpeed);

        if(hor!=0||ver!=0)

            this.transform.Translate(0, 0, Time.deltaTime * moveSpeed);

    }

坐标系统

Unity坐标系

World Space

世界(全局)坐标系:整个场景的固定坐标

作用:在游戏场景中表示每个游戏对象的位置和方向

Local Space

物体(局部)坐标系:每个物体独立的坐标系,原点为模型轴心点,随物体移动或旋转而改变

作用:表示物体间相对位置与方向

Screen Space

屏幕坐标系:以像素为单位,屏幕左下角为原点(0,0),右上角屏幕宽,高度,z为到相机的距离

作用:表示物体在屏幕中的位置

Viewport Space

视口(摄像机)坐标系:屏幕左上方原点为(0,0),右上角为(1,1),z为到相机的距离

作用:表示物体在摄像机中的位置

坐标系转换

Local Space—>World Space

transform.forward在世界坐标系中表示物体在正前方

transform.right在世界坐标系中表示物体在正右方

transform.up在世界坐标系中表示物体在正上方

transform.TransformPoint 转换点,受变换组件位置、旋转和缩放影响

transform.TransformDirection 方向,受变换组件旋转影响

transform.TransformPoint 向量,受变换组件旋转和缩放影响

World Space—>Local Space

transform.InverseTransformPoint;转换点,受变换组件位置,旋转和缩放影响

transform.InverseTransformDirection;方向,受变换组件旋转影响

transform.InverseTransformVector;转换点,受变换组件旋转和缩放影响

World Space<—>Local Space

Camera.main.WorldToScreenPoint将点从世界坐标系转换到屏幕坐标系中

Camera.main.ScreenToWorldPoint将点从屏幕坐标系转换到世界坐标系中

World Space<—>Viewport Space

Camera.main.WorldToViewportPoint将点从世界坐标系转换到视口坐标系中

Camera.main.ViewportToWorldPiont将点从屏幕坐标系转换到世界坐标系中

练习:如果移出屏幕外,停止运动,(可返回);移出屏幕上边界,下边界返回,移出左边界,右边界返回

public float moveSpeed = 3;

    private Camera mainCamera;

       private void Start()

    {

        mainCamera = Camera.main;

    }

    private void Update()

    {



        float hor = Input.GetAxis("Horizontal");

        float ver = Input.GetAxis("Vertical");

        hor *= moveSpeed * Time.deltaTime;

        ver*= moveSpeed * Time.deltaTime;

        Vector3 screenPoint = mainCamera.WorldToScreenPoint(this.transform.position);

        //如果超过屏幕,停止运动

        //如果到了最左边 并且还想向左运动 或者到了最右边并且还想向右运动

        if (screenPoint.x <= 0 && hor < 0 || screenPoint.x >= Screen.width && hor > 0)

            hor = 0;

        //上出,下进

        if (screenPoint.y > Screen.height)

            screenPoint.y = 0;

        //下出,上进

        if (screenPoint.y < 0)

            screenPoint.y = Screen.height;

        this.transform.position = Camera.main.ScreenToWorldPoint(screenPoint);

        this.transform.Translate(hor, 0, ver);

    }

猜你喜欢

转载自blog.csdn.net/m0_63330263/article/details/126099261