Unity实现3D模型子物体伸出折线并显示各自名称的功能

一、灵感

        在unity项目中我们经常会遇到很多介绍产品的场景需求,所以咱干脆写一个脚本来简单介绍把!话不多说,直接开干!

二、场景搭建

1、搭建一个简单的场景,创建一个cube作为最大的父物体,接着再创建一个球和一个圆柱作为cube的子物体。具体场景结构如下图:

三、实现过程

先说一些废话和思路:

1、首先我们设想的是设计一个脚本1.0版本,这个脚本会在场景启动时,从每个子物体发射一条折线,并在折线末端显示子物体的名称。后面发现有很多需要解决的问题,比如:

1、在实际场景中我们发射射线是很容易使射线重合或者错乱的,后面我就想直接生成一个三点式折线,哪三个点呢?分别是:子物体质心、外部转折点、折线尾端3个转折点。

2、Textmesh组件这东西显示文本是会丢失文本精度的!!!真可恶啊!

3、文本总是不能正常显示在折线尾部中间位置,后面想了一想,是由于没有水平居中和垂直居中的原因,小问题。

4、功能实现了折线不可控?全部数据变量写死了?这不可能,不是我的风格,好,直接把变量集成到脚本公开变量上去,把子物体信息也给我私有数组遍历展示出来,确保每一个子物体折线都可控。嘿嘿嘿。

5、再来几个小小的动态效果!

动态的射线发射是必要的吧!

动态的模型旋转是必要的吧!

动态的文本凝视摄像机是必要的吧!

好滴!终于哔哔完了!

四、功能讲解及演示

1、将脚本挂载在cube父物体上

2、启动场景,脚本会遍历cube的所有子物体形成私有数组,在数组中,可以单独设置每一个物体发射的折线的径向长度和高度这2个数值,折线的发射速度也是可调节的图中为0.5,还有一个是否进行自旋转的勾选框,最后还有一个旋转速度调节。

上视频,诶嘿嘿,视频来喽!

介绍功能实现展示视频

五、代码

using UnityEngine;
using TMPro;
using System;

public class LineDrawer : MonoBehaviour
{
    [System.Serializable]
    public struct LineData
    {
        public string name;
        public float radialLength;
        public float lineHeight;
    }

    public LineData[] lineDataArray;
    public float lineSpeed = 1.0f; // 线条发射速度
    public bool enableRotation = false; // 控制旋转
    public float rotationSpeed = 10.0f; // 旋转速度
    private Transform[] children;
    private LineRenderer[] lineRenderers;
    private GameObject[] textObjects;

    void Start()
    {
        // 获取所有子物体
        children = new Transform[transform.childCount];
        lineRenderers = new LineRenderer[transform.childCount];
        textObjects = new GameObject[transform.childCount];

        for (int i = 0; i < transform.childCount; i++)
        {
            children[i] = transform.GetChild(i);

            // 初始化LineData
            if (i >= lineDataArray.Length)
            {
                Array.Resize(ref lineDataArray, i + 1);
            }
            lineDataArray[i].name = children[i].name;

            // 创建LineRenderer
            GameObject lineObj = new GameObject("Line");
            lineObj.transform.SetParent(transform);
            LineRenderer lr = lineObj.AddComponent<LineRenderer>();
            lr.startWidth = 0.05f;
            lr.endWidth = 0.05f;
            lr.positionCount = 3; // 三个点形成折线
            lineRenderers[i] = lr;

            // 创建TextMeshPro
            GameObject textObj = new GameObject("Text");
            textObj.transform.SetParent(transform);
            TextMeshPro textMesh = textObj.AddComponent<TextMeshPro>();
            textMesh.text = children[i].name;
            textMesh.fontSize = 6;
            textMesh.color = Color.black;
            textMesh.alignment = TextAlignmentOptions.Center; // 水平和垂直居中
            textObjects[i] = textObj;
        }
    }

    void Update()
    {
        for (int i = 0; i < children.Length; i++)
        {
            // 获取当前子物体的折线数据
            float radialLength = lineDataArray[i].radialLength;
            float lineHeight = lineDataArray[i].lineHeight;

            // 更新线条位置
            Vector3 startPosition = children[i].position;
            Vector3 bendPosition = startPosition + Vector3.right * radialLength; // 折线中间点
            Vector3 endPosition = bendPosition + Vector3.up * lineHeight; // 线条末端
            lineRenderers[i].SetPosition(0, startPosition);
            lineRenderers[i].SetPosition(1, Vector3.Lerp(lineRenderers[i].GetPosition(1), bendPosition, Time.deltaTime * lineSpeed));
            lineRenderers[i].SetPosition(2, Vector3.Lerp(lineRenderers[i].GetPosition(2), endPosition, Time.deltaTime * lineSpeed));

            // 更新文本位置
            Vector3 textPosition = lineRenderers[i].GetPosition(2);
            textObjects[i].transform.position = textPosition + new Vector3(0, 0.1f, 0); // 调整文本位置

            // 使文本面向摄像机
            textObjects[i].transform.rotation = Quaternion.LookRotation(textObjects[i].transform.position - Camera.main.transform.position);
        }

        // 旋转功能
        if (enableRotation)
        {
            transform.Rotate(Vector3.up, rotationSpeed * Time.deltaTime, Space.World);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值