Unity 标签功能

 1、效果展示

2、主要代码

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

public class LabelUiItem : MonoBehaviour
{
    private Vector3 center;

    private Image linkLine;

    private Image Line;

    private Text contentText;

    private GameObject contentBG;

    private Transform targetTrans;

    public struct LabelUiData
    {
        public float zValue;

        public GameObject labelUiItemGame;

        public string targetName;
    }

    private LabelUiData labelUiData;

    //初始化
    public void Init(Transform targetTrans, Transform canvasTrans)
    {
        this.targetTrans = targetTrans;

        Line = transform.Find("line").GetComponent<Image>();

        linkLine = transform.Find("linkLine").GetComponent<Image>();

        contentBG = transform.Find("contentBG").gameObject;

        contentText = contentBG.transform.Find("content").GetComponent<Text>();

        contentText.text = targetTrans.name;

        transform.SetParent(canvasTrans, false);

        center = GetModelCenterPoint();

        gameObject.SetActive(true);

        labelUiData = new LabelUiData();

        labelUiData.labelUiItemGame = gameObject;

        labelUiData.targetName = targetTrans.name;

        gameObject.name = targetTrans.name;
    }

    /// <summary>
    /// 判断当前位置是否被遮挡
    /// </summary>
    private bool IsBaffle()
    {
        Camera curSceneCamera = Camera.main;

        Vector3 directionToTarget = targetTrans.position - curSceneCamera.transform.position;

        Ray ray = new Ray(curSceneCamera.transform.position, directionToTarget);
        RaycastHit hit;

        if (Physics.Raycast(ray, out hit, directionToTarget.magnitude))
        {
            // 如果射线击中的物体不是目标物体,则表示目标物体被遮挡
            if (hit.collider.gameObject.name.Equals(targetTrans.gameObject.name))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        return true;
    }

    private Vector3 GetModelCenterPoint()
    {
        Transform partentTrans = targetTrans.parent;

        Renderer[] renderers = partentTrans.GetComponentsInChildren<Renderer>();

        Bounds box = new Bounds(new Vector3(0, 0, 0), new Vector3(0, 0, 0));

        for (int i = 0; i < renderers.Length; i++)
        {
            Renderer renderer = renderers[i];

            box.Encapsulate(renderer.bounds.min);

            box.Encapsulate(renderer.bounds.max);
        }

        return box.center;
    }

    public void SetDir(Vector3 lineDir)
    {
        if (lineDir == Vector3.zero)
            lineDir = Vector3.right;

        bool isLeft = lineDir.x < 0;

        Vector3 xDirection = isLeft ? Vector3.left : Vector3.right;

        Vector3 normalDir = lineDir.normalized;

        linkLine.transform.localPosition = Vector3.zero;

        Quaternion rotation = Quaternion.FromToRotation(Vector3.right, normalDir);

        linkLine.transform.localRotation = rotation;

        Vector2 pivot = isLeft ? new Vector2(1f, 0.5f) : new Vector2(0f, 0.5f);

        Line.rectTransform.pivot = pivot;

        contentText.rectTransform.pivot = pivot;

        contentBG.GetComponent<RectTransform>().pivot = pivot;

        Line.transform.localPosition = normalDir * linkLine.rectTransform.rect.width - xDirection;

        Vector3 contentPos = Line.transform.localPosition + new Vector3(0, 10, 0) + xDirection * (Line.rectTransform.rect.width + 5) * 1;

        contentBG.transform.localPosition = new Vector3(contentPos.x, Line.transform.localPosition.y, contentPos.z);
    }

    private bool IsModelVisible()
    {
        Renderer modelRenderer = targetTrans.GetComponent<Renderer>();
        Vector3 screenPos = Camera.main.WorldToScreenPoint(modelRenderer.bounds.center);
        return screenPos.z > 0 &&
               screenPos.x >= 0 &&
               screenPos.x <= Screen.width &&
               screenPos.y >= 0 &&
               screenPos.y <= Screen.height;
    }

    public void LabelLateUpdate()
    {
        // 获取目标物体的世界坐标
        Vector3 worldPosition = targetTrans.position;

        // 将世界坐标转换为屏幕坐标
        Vector3 screenPosition = Camera.main.WorldToScreenPoint(worldPosition);

        if (IsBaffle() && IsModelVisible())
        {
            gameObject.SetActive(true);

            Vector3 screenCenter = Camera.main.WorldToScreenPoint(center);

            var angleValue = (screenPosition - screenCenter);

            Debug.Log($"{targetTrans.name}   {angleValue.z}");

            labelUiData.zValue = angleValue.z;

            SetDir(angleValue);

            gameObject.transform.position = screenPosition;

            LabelUiManager.Instance.AddOrUpdataLabelUiData(labelUiData);
        }
        else
        {
            gameObject.SetActive(false);
        }
    }
}

需要一个管理 LabelUiManager

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class LabelUiManager : MonoBehaviour
{
    public static LabelUiManager Instance;

    private Dictionary<string, LabelUiItem.LabelUiData> labelUiDatas;

    public GameObject labelUIItem;

    public Transform canvasTrans;

    public void Awake()
    {
        Instance = this;

        labelUiDatas = new Dictionary<string, LabelUiItem.LabelUiData>();
    }

    //添加 或者 刷新标注ui的数据
    public void AddOrUpdataLabelUiData(LabelUiItem.LabelUiData labelUiData)
    {
        if (labelUiDatas.ContainsKey(labelUiData.targetName))
        {
            labelUiDatas[labelUiData.targetName] = labelUiData;
        }
        else
        {
            labelUiDatas.Add(labelUiData.targetName, labelUiData);
        }
    }

    //设置刷新标注ui的层级
    public void SetLabelUiHierarchy()
    {
        List<LabelUiItem.LabelUiData> labelUiOrderByDatas = labelUiDatas.Values.OrderBy(n => n.zValue).ToList();

        for (int i = 0; i < labelUiOrderByDatas.Count; i++)
        {
            LabelUiItem.LabelUiData labelUiData = labelUiOrderByDatas[i];

            labelUiData.labelUiItemGame.transform.SetAsFirstSibling();
        }
    }

    //创建标注item
    public LabelUiItem CreateLabelUiItem(Transform targetTrans)
    {
        GameObject labelUIItemGame = Instantiate(labelUIItem);

        LabelUiItem labelUiItem = labelUIItemGame.GetComponent<LabelUiItem>();

        labelUiItem.Init(targetTrans, canvasTrans);

        return labelUiItem;
    }

    // Start is called before the first frame update
    private void Start()
    {
    }

    // Update is called once per frame
    private void Update()
    {
        SetLabelUiHierarchy();
    }
}

3、项目Demo

链接:https://pan.baidu.com/s/1ri_xKNrvBDI1aW-1xXBG6g?pwd=xm61
提取码:xm61
--来自百度网盘超级会员V7的分享

Unity中实现登录注册功能可以通过以下步骤进行: 1. 创建用户界面(UI):使用Unity的UI系统创建登录和注册界面。你可以使用Unity提供的UI元素,例如按钮、文本框和标签来设计用户界面。 2. 创建用户管理系统:你需要实现一个用户管理系统来处理用户的注册和登录。可以创建一个用户类来保存用户的信息,例如用户名和密码。你可以使用C#编写逻辑代码来处理用户输入和验证。 3. 注册功能:在注册界面上,用户可以输入用户名和密码,并点击注册按钮。当用户点击注册按钮时,你可以检查用户名是否已经存在,并将新用户的信息保存到用户管理系统中。 4. 登录功能:在登录界面上,用户可以输入已注册的用户名和密码,并点击登录按钮。当用户点击登录按钮时,你可以检查用户名和密码是否匹配用户管理系统中的信息,如果匹配成功,则用户登录成功。 5. 用户认证和授权:一旦用户成功登录,你可以实现用户认证和授权机制来限制用户的访问权限。你可以为每个用户分配不同的角色或权限,并根据用户的角色或权限来控制用户能够访问的功能和内容。 通过以上步骤,你可以在Unity中实现一个简单的登录注册功能。当用户注册和登录成功后,你可以根据需要进行后续的逻辑开发,例如保存用户数据、实现记住密码功能等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值