Unity 3D模型展示之生成标注

1.效果图

在这里插入图片描述

2.生成标注
标注生成要求:
1.指定元件生成标注。
2.生成标注出现位置可以设置。

根据标注生成的要求,可以在元件添加脚本时将这些信息读取并进行实现。控制标注生成在元件的位置,生成标注的距离。

  • 创建标注预制体,分别在标注预制体中设置8个连接点
    在这里插入图片描述
    在这里插入图片描述

  • 在MSwitchParts增加属性来保存标注出现位置信息,并提供方法进行信息的设置。

    MSwitchParts中的代码片段

    public MSwitchParts(int id, string partName, string objName, string details, string inFopostion = "Bottom0", float infoDis = 1, float infoAngle = 45, int pId = 0, List<int> pIds = null)
    {
        this.Id = id;
        this.PartName = partName;
        this.ObjName = objName;
        this.Details = details;
        this.PId = pId;
        this.InFopostion = inFopostion;
        this.InfoDis = infoDis;
        this.InfoAngle = infoAngle;
        this.pIds = pIds;
    }

在SwitchOperation初始化数据,参数为连接点、距离、角度。
在这里插入图片描述

  • 这里根据设置距离、角度,需要进行生成点位置的计算
    public Vector3 GetEndPointByTrigonometric(float angle, Vector3 StartPoint, float distance)
    {
        Vector3 EndPoint = Vector3.zero;

        //角度转弧度
        var radian = (angle * Math.PI) / 180;
        Debug.Log(Math.Cos(radian));
        //计算新坐标 r 就是两者的距离
        EndPoint.x = StartPoint.x + float.Parse((distance * Math.Cos(radian)).ToString());
        EndPoint.y = StartPoint.y + float.Parse((distance * Math.Sin(radian)).ToString());
        EndPoint.z = StartPoint.z;
        return EndPoint;
    }
  • 已知起始坐标(元件的坐标)与计算出的终点坐标,需要画上一根线连接起来。新建MyLine脚本。
using UnityEngine;

[RequireComponent(typeof(LineRenderer))]
public class MyLine : MonoBehaviour
{
    [SerializeField]
    private Transform TransformA;
    [SerializeField]
    public Transform TransformB;

    public LineRenderer LineRender;

    [System.Obsolete]
    void Start()
    {
        TransformA = this.transform;
        LineRender = this.GetComponent<LineRenderer>();
        if (LineRender != null)
        {

            LineRender.sharedMaterial = SwitchOperation.Instance.lineColormaterial;
            LineRender.generateLightingData = true;
            LineRender.SetWidth(0.008f, 0.008f);
            //LineRender.enabled = false;
        }
    }

    void Update()
    {
        if (LineRender && TransformB)
        {
            LineRender.SetPosition(0, TransformA.position);
            LineRender.SetPosition(1, TransformB.position);
        }

    }
}

  • 修改SwitchOperation脚本实现功能。主要代码。
 //获取终点坐标
                var objPointPostion = GetEndPointByTrigonometric(tempModel.InfoAngle, t.position, tempModel.InfoDis);
                var infoRotation = t.rotation;
                //生成标注
                GameObject infoTemp = Instantiate(infoPrefabs, objPointPostion, infoRotation);
                //生成标注 命名
                infoTemp.name = "info" + t.name;
                //infoTemp.tag = "Info";

                var tempText = infoTemp.transform.Find("info").transform.Find("btnInfo").transform.Find("Text").GetComponent<Text>();
                tempText.text = tempModel.PartName;
                MyLine line = t.gameObject.AddComponent<MyLine>();

                if (tempModel.InFopostion != "")
                {
                    line.TransformB = infoTemp.transform.Find(tempModel.InFopostion).transform;
                }
                else
                {
                    line.TransformB = infoTemp.transform;
                }
  • SwitchOperation完整代码

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;

public class SwitchOperation : MonoBehaviour
{
    public static SwitchOperation Instance;
    private List<MSwitchParts> list = new List<MSwitchParts>();
    [FormerlySerializedAs("infoPrefabs")]
    [Tooltip("Prefab of the  object. Prefab must have a infoPrefabs component. May be an empty game object or a full avatar.")]
    public GameObject infoPrefabs;
    public int currentIndex = 0;
    public Material lineColormaterial;


    private void Awake()
    {
        Instance = this;
    }
    // Start is called before the first frame update
    void Start()
    {
        InitData();
      
    }

    public List<MSwitchParts> GetSwitchParts()
    {
        return list;
    }

    /// <summary>
    /// 初始化数据
    /// </summary>
    private void InitData()
    {
        var dd = new MSwitchParts(1, "真空交流接触器", "zuoduanzhenkongjiaoliuqi2_N", "详细信息比萨饼爸爸", "Bottom1", 1.414f, 90);
        dd.setTask(1, "选择卸载" + dd.PartName, 7, "1");
        dd.setTask(2, "卸载" + dd.PartName + "的接线柱", 7, "2");
        dd.setTask(3, "卸载" + dd.PartName + "的固定螺丝", 7, "3");
        dd.setTask(4, "取出" + dd.PartName, 7, "4");
        list.Add(dd);
        dd = new MSwitchParts(2, "电流互感器", "zuoduandianliuhuganqi1_N", "详细信息222323232", "Right", 0.8f, 180);
        dd.setTask(1, "选择卸载" + dd.PartName, 7, "1");
        dd.setTask(2, "卸载" + dd.PartName + "的接线柱", 7, "2");
        dd.setTask(3, "卸载" + dd.PartName + "的固定螺丝", 7, "3");
        dd.setTask(4, "取出" + dd.PartName, 7, "4");
        list.Add(dd);
        dd = new MSwitchParts(3, "变压器TC", "zuoduanjiaoliuqi1_N", "详细信息222323232", "Top1", 1f, 235);
        dd.setTask(1, "选择卸载" + dd.PartName, 7, "1");
        dd.setTask(2, "卸载" + dd.PartName + "的接线柱", 7, "2");
        dd.setTask(3, "卸载" + dd.PartName + "的固定螺丝", 7, "3");
        dd.setTask(4, "取出" + dd.PartName, 7, "4");
        list.Add(dd);
        dd = new MSwitchParts(4, "千伏级熔断器FU1", "qianfurongduanqi_N", "详细信息222323232", "Top1", 1f, -50);
        dd.setTask(1, "选择卸载" + dd.PartName, 7, "1");
        dd.setTask(2, "卸载" + dd.PartName + "的接线柱", 7, "2");
        dd.setTask(3, "卸载" + dd.PartName + "的固定螺丝", 7, "3");
        dd.setTask(4, "取出" + dd.PartName, 7, "4");
        list.Add(dd);

        dd = new MSwitchParts(5, "中间继电器", "jidianqi2_N", "详细信息222323232", "Left", 1f, 0);
        dd.setTask(1, "选择卸载" + dd.PartName, 7, "1");
        dd.setTask(2, "卸载" + dd.PartName + "的接线柱", 7, "2");
        dd.setTask(3, "卸载" + dd.PartName + "的固定螺丝", 7, "3");
        dd.setTask(4, "取出" + dd.PartName, 7, "4");
        list.Add(dd);
        dd = new MSwitchParts(6, "保护器", "baohuqi1_N", "详细信息222323232", "Right", 1.5f, 180);
        dd.setTask(1, "选择卸载" + dd.PartName, 7, "1");
        dd.setTask(2, "卸载" + dd.PartName + "的接线柱", 7, "2");
        dd.setTask(3, "卸载" + dd.PartName + "的固定螺丝", 7, "3");
        dd.setTask(4, "取出" + dd.PartName, 7, "4");
        list.Add(dd);
        dd = new MSwitchParts(7, "隔离开关QS", "gelizhuanxiangkaiguan003_N", "详细信息222323232", "Bottom1", 1f, 90);
        dd.setTask(1, "选择卸载" + dd.PartName, 7, "1");
        dd.setTask(2, "卸载" + dd.PartName + "的接线柱", 7, "2");
        dd.setTask(3, "卸载" + dd.PartName + "的固定螺丝", 7, "3");
        dd.setTask(4, "取出" + dd.PartName, 7, "4");
        list.Add(dd);

        dd = new MSwitchParts(8, "急停按钮", "jitinganniudizuo2_N", "详细信息222323232", "Right", 1.5f, 135);
        dd.setTask(1, "选择卸载" + dd.PartName, 7, "1");
        dd.setTask(2, "卸载" + dd.PartName + "的接线柱", 7, "2");
        dd.setTask(3, "卸载" + dd.PartName + "的固定螺丝", 7, "3");
        dd.setTask(4, "取出" + dd.PartName, 7, "4");
        list.Add(dd);

        dd = new MSwitchParts(9, "阻容吸收装置", "zhurongxishouqi3_N", "详细信息222323232", "Left", 1f, 35);
        dd.setTask(1, "选择卸载" + dd.PartName, 7, "1");
        dd.setTask(2, "卸载" + dd.PartName + "的接线柱", 7, "2");
        dd.setTask(3, "卸载" + dd.PartName + "的固定螺丝", 7, "3");
        dd.setTask(4, "取出" + dd.PartName, 7, "4");
        list.Add(dd);

        Transform[] allTr = transform.GetComponentsInChildren<Transform>();
        int m = 0;
        foreach (Transform t in allTr)
        {
         
            var tempModel = list.Find(p => p.ObjName == t.name);

       
            if (tempModel != null)
            {
                Debug.Log(t.name);
                SwitchPart part = t.gameObject.AddComponent<SwitchPart>();
                part.ownerIndex = m;
                m++;
                part.mSwitchParts = tempModel;
                //获取终点坐标
                var objPointPostion = GetEndPointByTrigonometric(tempModel.InfoAngle, t.position, tempModel.InfoDis);
                var infoRotation = t.rotation;
                //生成标注
                GameObject infoTemp = Instantiate(infoPrefabs, objPointPostion, infoRotation);
                //生成标注 命名
                infoTemp.name = "info" + t.name;
                

                var tempText = infoTemp.transform.Find("info").transform.Find("btnInfo").transform.Find("Text").GetComponent<Text>();
                tempText.text = tempModel.PartName;
                MyLine line = t.gameObject.AddComponent<MyLine>();

                if (tempModel.InFopostion != "")
                {
                    line.TransformB = infoTemp.transform.Find(tempModel.InFopostion).transform;
                }
                else
                {
                    line.TransformB = infoTemp.transform;
                }
            }
        }
    }

    public Vector3 GetEndPointByTrigonometric(float angle, Vector3 StartPoint, float distance)
    {
        Vector3 EndPoint = Vector3.zero;

        //角度转弧度
        var radian = (angle * Math.PI) / 180;
        Debug.Log(Math.Cos(radian));
        //计算新坐标 r 就是两者的距离
        EndPoint.x = StartPoint.x + float.Parse((distance * Math.Cos(radian)).ToString());
        EndPoint.y = StartPoint.y + float.Parse((distance * Math.Sin(radian)).ToString());
        EndPoint.z = StartPoint.z;
        return EndPoint;
    }

    public void SetCurrentIndex(int opeIndex)
    {
        if (opeIndex > list.Count)
        {
            currentIndex = list.Count;
        }
        else
        {
            currentIndex = opeIndex;
        }
    }

    public void SetCurrentInfo()
    {
        list[currentIndex].OperaStatus = "N";
    }

    public void SetCurrentFinishInfo()
    {
        list[currentIndex].OperaStatus = "T";
    }

    public GameObject GetCurrentSwitchObj()
    {
        print("GetCurrentSwitchObj:" + currentIndex);
        var name = list[currentIndex].ObjName;
        print("GetCurrentSwitchObj:" + name);
        var obj = UHelper.FindTheChild(this.gameObject, name).gameObject;
        return obj;
    }

    public MSwitchParts GetCurrentSwitchInfo()
    {
        return list[currentIndex];
    }
}

3.效果展示
标注显示效果不理想。这时我们在添加一个脚本使得标注总是看向主摄像机。

在这里插入图片描述
添加脚本LookCamera。


using UnityEngine;

public class LookCamera : MonoBehaviour
{
    Transform m_Camera;

    public Camera myCamera;

    void Start()
    {
        if (myCamera != null)
        {
            m_Camera = myCamera.transform;
        }
        else
        {
            m_Camera = Camera.main.transform;
        }

    }

    // Update is called once per frame
    void LateUpdate()
    {
        // 这里我的角色朝向和UI朝向是相反的,如果直接用LookAt()还需要把每个UI元素旋转过来。
        // 为了简单,用了下面这个方法。它实际上是一个反向旋转,可以简单理解为“负负得正”吧
        transform.rotation = Quaternion.LookRotation(transform.position - m_Camera.position);
    }

}

最终效果
在这里插入图片描述

  • 10
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yxlalm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值