通过移动旋转使2个方块的面对齐

题目在这里插入图片描述

思路

  1. 一个方块多种颜色:可以通过建模贴不同颜色的材质,或者shader实现
  2. 随机位置和角度:使用随机数,生成随机向量,赋给position和eulerAngles
  3. 位置误差:两个面的中点的position的差值
  4. 旋转误差:用自身各个轴和要对齐的平面的夹角表示。旋转顺序应该为将X轴转到要对齐的平面,再将Y轴转到要对其的平面,使得两个面在同一平面内;然后旋转Z轴,使两个面完全重合。

我的解答

在这里插入图片描述

  1. 把方块作为Quad的子类,移动Quad吸附要对齐的面,得到面的位姿
    在这里插入图片描述

  2. 设定平移和旋转两种交互模式,勾选切换后,通过键盘操作平移和旋转,并且复用按钮减少操作复杂度

  3. 强制设定了交互顺序,先平移再旋转

  4. 绿方块按照自身轴旋转和平移,只需要将误差调到指定的数,即可对齐。

代码

  1. 随机位置和角度
    public GameObject Cube;
    public float RandomRadius; //限制随机出现的范围,使红色方块一定出现在摄像机视野内

    void Start()
    {
        Cube.transform.position = RandomPosi(RandomRadius);
        Cube.transform.eulerAngles = RandomRot();
    }

    private Vector3 RandomPosi(float radius)//随机位置
    {
        Vector3 pos;
        float x= Random.Range(-radius, radius);
        float y= Random.Range(-radius, radius);
        float z= Random.Range(-radius, radius);
        return pos;
    }

    private Vector3 RandomRot()//随机角度
    {
        Vector3 rot;
        float x = Random.Range(0.0f, 360.0f);
        float y= Random.Range(0.0f, 360.0f);
        float z= Random.Range(0.0f, 360.0f);
        return rot;
    }

在这里插入图片描述

  1. 平移、旋转、显示误差
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class MoveCube : MonoBehaviour
{
    public bool IsMove = false ;//移动模式
    public bool IsRot = false ;//旋转模式
    //移动、旋转的速度
    private  float MoveXspeed;
    private float MoveYspeed;
    private float MoveZspeed;
    private float RotXspeed;
    private float RotYspeed;
    private float RotZspeed;
    //设置最快速度和最慢速度,接近对齐时使用慢速微调
    public float FastMoveSpeed;
    public float SlowMoveSpeed;
    public float FastRotSpeed;
    public float SlowRotSpeed;
    //显示误差
    public GameObject RedQuad;
    public GameObject GreenQuad;
    public Text TextBoard;


    void Update()
    {
        TextBoard.text = showError();
        if (IsMove) Move();
        if (IsRot) Rot();       
    }

    //平移方法
    private void Move()
    {
        //Y轴,上下移动
        if (Input.GetKey(KeyCode.W)
            this.transform.Translate(Vector3.up * Time.fixedTime * MoveYspeed);
        
        if (Input.GetKey(KeyCode.S) )  
            this.transform.Translate(-Vector3.up * Time.fixedTime * MoveYspeed);
        

        //X轴,左右移动
        if (Input.GetKey(KeyCode.A) )        
            this.transform.Translate(Vector3.left * Time.fixedTime * MoveXspeed);
        
        if (Input.GetKey(KeyCode.D) )        
            this.transform.Translate(-Vector3.left * Time.fixedTime * MoveXspeed);
       

        //Z轴,前后移动
        if (Input.GetKey(KeyCode.Q) )      
            this.transform.Translate(Vector3.back * Time.fixedTime *MoveZspeed);
 
        if (Input.GetKey(KeyCode.E) )
            this.transform.Translate(-Vector3.back * Time.fixedTime * MoveZspeed);
        
    }

    //旋转方法
    private void Rot()
    {
        //绕Y轴
        if (Input.GetKey(KeyCode.W))       
            this.transform.Rotate(Vector3.down * Time.fixedTime * RotYspeed);     
        if (Input.GetKey(KeyCode.S))
            this.transform.Rotate(-Vector3.down * Time.fixedTime * RotYspeed);
            
        //绕X轴
        if (Input.GetKey(KeyCode.A))        
            this.transform.Rotate(Vector3.left * Time.fixedTime * RotXspeed);        
        if (Input.GetKey(KeyCode.D))        
            this.transform.Rotate(-Vector3.left * Time.fixedTime * RotXspeed);
            
        //绕Z轴
        if (Input.GetKey(KeyCode.Q))
            this.transform.Rotate(Vector3.back * Time.fixedTime * RotZspeed);      
        if (Input.GetKey(KeyCode.E))        
            this.transform.Rotate(-Vector3.back * Time.fixedTime * RotZspeed);
    }


    //是否平移
    public void MoveGo()
    {
        IsMove = true;
        IsRot = false;
    }

    //是否旋转
    public void RotGo()
    {
        IsRot = true;
        IsMove = false;
    }

    
    //显示误差
    private string showError()
    {
        string posError = PosError();
        string rotError = RotError();
        return "先平移:"+"\r\n" + posError 
            + "\r\n" + "后旋转:" + "\r\n" + rotError;
    }


    //位置误差
    private string PosError()
    {        
        float GreenX = GreenQuad.transform.position.x;
        float GreenY = GreenQuad.transform.position.y;
        float GreenZ = GreenQuad.transform.position.z;

        float x = RedQuad.transform.position.x - GreenX;
        float y = RedQuad.transform.position.y - GreenY;
        float z = RedQuad.transform.position.z - GreenZ;


        //根据误差大小控制速度
        if (Mathf.Abs(y) > 1.0f)
            MoveYspeed = FastMoveSpeed;
        else MoveYspeed = SlowMoveSpeed;
        if (Mathf.Abs(x) > 1.0f)
            MoveXspeed = FastMoveSpeed;
        else MoveXspeed = SlowMoveSpeed;
        if (Mathf.Abs(z) > 1.0f) 
            MoveZspeed = FastMoveSpeed;
        else MoveZspeed = SlowMoveSpeed;

        return "X轴方向误差(操作AD使误差归0):"+x+"\r\n"
            + "Y轴方向误差(操作WS使误差归0):" + y+"\r\n"
            + "Z轴方向误差(操作QE使误差归0):" + z+"\r\n";
    }

    //角度误差
    private string RotError()
    {       
        float XZ = Angle(GreenQuad.transform.right,RedQuad.transform.forward);
        float YZ = Angle(GreenQuad.transform.up, RedQuad.transform.forward);
        float ZZ = Angle(GreenQuad.transform.forward, RedQuad.transform.forward);
        float XX = Angle(GreenQuad.transform.right, RedQuad.transform.right);        

        根据误差大小控制速度
        if (YZ > 95.0f || YZ < 85.0f)
            RotXspeed = FastRotSpeed;
        else RotXspeed = SlowRotSpeed;
        if (XZ > 95.0f || XZ < 85.0f)
            RotYspeed = FastRotSpeed;
        else RotYspeed = SlowRotSpeed;
        if (0.0f <= XX && XX < 5.0f)
            RotZspeed = SlowRotSpeed;
        else if (175.0f <= XX && XX < 185.0f)
            RotZspeed = SlowRotSpeed;
        else RotZspeed = FastRotSpeed;


        return "操作WS按钮,使误差接近90\r\n"
            + "绿方块x轴与红方块xy平面的夹角(操作WS):" +XZ+ "\r\n" + "\r\n"
            + "操作AD按钮,使误差接近90\r\n"
            + "绿方块y轴与红方块xy平面的夹角(操作AD):" + YZ + "\r\n" + "\r\n"
            + "180代表相对,0代表重合\r\n"
            + "绿方块z轴与红方块z轴的夹角:" + ZZ + "\r\n" + "\r\n"
            + "操作QE按钮,使误差接近0或180\r\n"
            + "绿方块x轴与红方块x轴的夹角(操作QE):" + XX + "\r\n";
    }

    //求两向量夹角
    private float Angle(Vector3 red, Vector3 green)
    {       
        float dot = Vector3.Dot(red.normalized, green.normalized);
        float angle = Mathf.Acos(dot) * Mathf.Rad2Deg; 
        return angle;
    }
}

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值