【Unity3D小功能】Unity3D中实现点击‘文字’出现‘UI面板’

推荐阅读

  • CSDN主页
  • GitHub开源地址
  • Unity3D插件分享
  • 简书地址
  • QQ群:398291828

大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。

一、前言

宠粉博主又来了,今天有粉丝问我如何实现点击一段文字然后出现的面板在那段文字附近显示:
在这里插入图片描述
深入了解后发现原来就是想要点击文字出现UI面板,并且UI面板在文字附近:
在这里插入图片描述
这种效果在很多游戏都会出现,比如梦幻西游、DNF,查看武器装备啥的。

接下来,这篇文章就来实现一下这种效果。

二、正文

2-1、制作UI

我们先做一个这个武器介绍的UI面板:
在这里插入图片描述
OK,再做一个聊天框:

在这里插入图片描述

2-2、UI文字点击事件

这里,要实现UI文字的点击事件,需要重写Text组件,具体实现可以参考这篇文章:
【Unity3D小功能】Unity3D中Text使用超链接并绑定点击事件

新建HyperlinkText.cs,编辑代码:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace UIClick
{
    /// <summary>
    /// 超链接信息类
    /// </summary>
    /// 
    [Serializable]
    public class HyperlinkInfo
    {
        public int startIndex;
        public int endIndex;
        public string name;
        public readonly List<Rect> boxes = new List<Rect>();
    }
    /// <summary>
    /// 文本控件,支持超链接
    /// </summary>
    public class HyperlinkText : Text, IPointerClickHandler
    {
        /// <summary>
        /// 解析完最终的文本
        /// </summary>
        private string m_OutputText;
        /// <summary>
        /// 超链接信息列表
        /// </summary>
        private readonly List<HyperlinkInfo> _mLinkInfos = new List<HyperlinkInfo>();
        /// <summary>
        /// 文本构造器
        /// </summary>
        protected static readonly StringBuilder s_TextBuilder = new StringBuilder();
        /// <summary>
        /// 超链接正则表达式
        /// </summary>
        private static readonly Regex s_HrefRegex = new Regex(@"<a link=([^>\n\s]+)>(.*?)(</a>)", RegexOptions.Singleline);
        /// <summary>
        /// 文本超链接控件
        /// </summary>
        private HyperlinkText mHyperlinkText;


        protected override void Awake()
        {
            base.Awake();
            mHyperlinkText = GetComponent<HyperlinkText>();
        }

        #region 回调事件
        public Action<string> onLinkClick;
        /// <summary>
        /// 点击事件检测是否点击到超链接文本
        /// </summary>
        /// <param name="eventData"></param>
        public void OnPointerClick(PointerEventData eventData)
        {
            RectTransformUtility.ScreenPointToLocalPointInRectangle(
                rectTransform, eventData.position, eventData.pressEventCamera, out var lp);

            foreach (var info in _mLinkInfos)
            {
                var boxes = info.boxes;
                for (var i = 0; i < boxes.Count; ++i)
                {
                    if (!boxes[i].Contains(lp)) continue;
                    onLinkClick?.Invoke(info.name);
                    return;
                }
            }
        }
        #endregion

        #region 生成超链接
        /// <summary>
        /// 重新渲染网格
        /// </summary>
        public override void SetVerticesDirty()
        {
            base.SetVerticesDirty();
            m_OutputText = GetOutputText(text);
        }

        /// <summary>
        /// 处理Text顶点数据
        /// </summary>
        /// <param name="toFill"></param>
        protected override void OnPopulateMesh(VertexHelper toFill)
        {
            var orignText = m_Text;
            m_Text = m_OutputText;
            base.OnPopulateMesh(toFill);
            m_Text = orignText;
            UIVertex vert = new UIVertex();

            // 处理超链接包围框
            foreach (var hrefInfo in _mLinkInfos)
            {
                hrefInfo.boxes.Clear();
                if (hrefInfo.startIndex >= toFill.currentVertCount)
                {
                    continue;
                }
                // 将超链接里面的文本顶点索引坐标加入到包围框
                toFill.PopulateUIVertex(ref vert, hrefInfo.startIndex);
                var pos = vert.position;
                var bounds = new Bounds(pos, Vector3.zero);
                for (int i = hrefInfo.startIndex, m = hrefInfo.endIndex; i < m; i++)
                {
                    if (i >= toFill.currentVertCount)
                    {
                        break;
                    }
                    toFill.PopulateUIVertex(ref vert, i);
                    pos = vert.position;
                    if (pos.x < bounds.min.x) // 换行重新添加包围框
                    {
                        hrefInfo.boxes.Add(new Rect(bounds.min, bounds.size));
                        bounds = new Bounds(pos, Vector3.zero);
                    }
                    else
                    {
                        bounds.Encapsulate(pos); // 扩展包围框

                    }
                }
                hrefInfo.boxes.Add(new Rect(bounds.min, bounds.size));
            }
        }

        /// <summary>
        /// 获取超链接解析后的最后输出文本
        /// </summary>
        /// <returns></returns>
        protected virtual string GetOutputText(string outputText)
        {
            s_TextBuilder.Length = 0;
            _mLinkInfos.Clear();
            var indexText = 0;
            foreach (Match match in s_HrefRegex.Matches(outputText))
            {
                s_TextBuilder.Append(outputText.Substring(indexText, match.Index - indexText));

                string str = s_TextBuilder.ToString();
                char[] array = str.ToCharArray();                //把字符串转化成字符数组
                IEnumerator enumerator = array.GetEnumerator();         //得到枚举器
                StringBuilder stringBuilder = new StringBuilder();
                while (enumerator.MoveNext())                         //开始枚举
                {
                    if ((char)enumerator.Current != ' ')         //向StringBuilder类对象添加非空格字符
                        stringBuilder.Append(enumerator.Current.ToString());
                }

                var group = match.Groups[1];
                var hrefInfo = new HyperlinkInfo
                {
                    startIndex = stringBuilder.Length * 4, // 超链接里的文本起始顶点索引
                    endIndex = (stringBuilder.Length + match.Groups[2].Length - 1) * 4 + 3,
                    name = group.Value
                };

                _mLinkInfos.Add(hrefInfo);
                s_TextBuilder.Append("<color=blue>");  // 超链接颜色
                s_TextBuilder.Append(match.Groups[2].Value);
                s_TextBuilder.Append("</color>");
                indexText = match.Index + match.Length;
            }
            s_TextBuilder.Append(outputText.Substring(indexText, outputText.Length - indexText));
            return s_TextBuilder.ToString();
        }
        #endregion
    }
}

新建HyperlinkLogic.cs脚本,编辑代码:

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

namespace UIClick
{
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class HyperlinkLogic : MonoBehaviour
    {
        public HyperlinkText[] hyperlinkText;
        void Start()
        {
            // 绑定事件
            for (int i = 0; i < hyperlinkText.Length; i++)
            {
                hyperlinkText[i].onLinkClick = (info) => onclick(info);
            }
        }

        void onclick(string info)
        {
            Debug.Log(info);

            switch (info)
            {
                case "匕首":
                    break;
                case "宝刀":
                    break;
                case "斧头":
                    break;
            }
        }
    }
}

将聊天文本的Text组件改成HyperlinkText.cs
在这里插入图片描述

2-3、将武器介绍的UI面板和Text点击事件绑定一下

新建WeaponItem.cs脚本,编辑代码:

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

public class WeaponItem : MonoBehaviour
{
    public static WeaponItem Instance;
    public GameObject Current;

    public Image Item;
    public Sprite[] SpirteItem;

    public Button BtnClose;
    public Text TextName;
    public Text TextRank;
    public Text TextContent;

    private void Awake()
    {
        Instance = this;
    }

    void Start()
    {
        Current.SetActive(false);
        BtnClose.onClick.AddListener(Close);
    }

    public void ShowInfo(int ItemType,string itemName,string itemRank,string itemContent)
    {
        Current.SetActive(true);
        Item.sprite = SpirteItem[ItemType];
        TextName.text = itemName;
        TextRank.text = itemRank;
        TextContent.text = itemContent;
    }

    public void Close()
    {
        Current.SetActive(false);
    }
}

继续修改HyperlinkLogic.cs脚本:

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

namespace UIClick
{
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class HyperlinkLogic : MonoBehaviour
    {
        public HyperlinkText[] hyperlinkText;

        public GameObject WeaponPanel;

        void Start()
        {
            // 绑定事件
            for (int i = 0; i < hyperlinkText.Length; i++)
            {
                hyperlinkText[i].onLinkClick = (info) => onclick(info);
            }
        }

        void onclick(string info)
        {
            Debug.Log(info);

            Vector3 pos = Input.mousePosition;
            pos.x += 100;
            pos.y -= 100;
            WeaponPanel.transform.position = pos;

            switch (info)
            {
                case "匕首":
                    WeaponItem.Instance.ShowInfo(0,info,"普通","这是一把绝世匕首。");
                    break;
                case "宝刀":
                    WeaponItem.Instance.ShowInfo(1, info, "史诗", "这是一把绝世宝刀。");
                    break;
                case "斧头":
                    WeaponItem.Instance.ShowInfo(2, info, "优秀", "这是一把绝世斧头。");
                    break;
            }
        }
    }
}

2-4、运行效果图

在这里插入图片描述

2-5、源代码

https://download.csdn.net/download/q764424567/89030869

三、后记

如果觉得本篇文章有用别忘了点个关注,关注不迷路,持续分享更多Unity干货文章。


你的点赞就是对博主的支持,有问题记得留言:

博主主页有联系方式。

博主还有跟多宝藏文章等待你的发掘哦:

专栏方向简介
Unity3D开发小游戏小游戏开发教程分享一些使用Unity3D引擎开发的小游戏,分享一些制作小游戏的教程。
Unity3D从入门到进阶入门从自学Unity中获取灵感,总结从零开始学习Unity的路线,有C#和Unity的知识。
Unity3D之UGUIUGUIUnity的UI系统UGUI全解析,从UGUI的基础控件开始讲起,然后将UGUI的原理,UGUI的使用全面教学。
Unity3D之读取数据文件读取使用Unity3D读取txt文档、json文档、xml文档、csv文档、Excel文档。
Unity3D之数据集合数据集合数组集合:数组、List、字典、堆栈、链表等数据集合知识分享。
Unity3D之VR/AR(虚拟仿真)开发虚拟仿真总结博主工作常见的虚拟仿真需求进行案例讲解。
Unity3D之插件插件主要分享在Unity开发中用到的一些插件使用方法,插件介绍等
Unity3D之日常开发日常记录主要是博主日常开发中用到的,用到的方法技巧,开发思路,代码分享等
Unity3D之日常BUG日常记录记录在使用Unity3D编辑器开发项目过程中,遇到的BUG和坑,让后来人可以有些参考。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/488652.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何在VS Code上搭建 C/C++开发环境

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、什么是VScode VScode&#xff08;Visual Studio Code&#xff09;是一款由微软开发的免费开源的轻量级代码编辑器。它…

AI垃圾装满溢出识别摄像机

AI垃圾装满溢出识别摄像机是一种基于人工智能技术的创新设备&#xff0c;旨在实时监测公共场所垃圾箱的装填情况&#xff0c;及时警示相关部门进行清理或更换&#xff0c;提高城市管理效率&#xff0c;改善城市环境质量。这种AI垃圾装满溢出识别摄像机通过搭载先进的图像识别和…

大唐杯国赛解读及赛前准备分析

从参赛类别的区分到大唐杯名称由原来的“第九届‘大唐杯’全国大学生移动通信5G技术大赛”变更为“第九届‘大唐杯’全国大学生新一代信息通信技术大赛”一系列的变化。 接下来重点讲解本科A组的情况分析: 需要注意的是,和去年的比赛不同,今年并不是两人互相讨论,而是和省…

如何使用 JavaScript 导入和导出 Excel

前言 在现代的Web应用开发中&#xff0c;与Excel文件的导入和导出成为了一项常见而重要的任务。无论是数据交换、报告生成还是数据分析&#xff0c;与Excel文件的交互都扮演着至关重要的角色。本文小编将为大家介绍如何在熟悉的电子表格 UI 中轻松导入 Excel 文件&#xff0c;…

zabbix进阶

知识点补充 zabbix server在主机上运行服务&#xff0c;端口号为10050&#xff0c;zabbix agent 在被监控机器上运行&#xff08;源码下载&#xff09;主要完成对cpu&#xff0c;磁盘的信息采集&#xff0c;端口号为10051 zabbix 软件结构组成&#xff1a; 1.Zabbix Web GUI …

【Java程序设计】【C00369】基于(JavaWeb)Springboot的笔记记录分享平台(有论文)

[TOC]() 博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过上千套毕业设计程序&#xff0c;博客中有上百套程序可供参考&#xff0c;欢迎共同交流学习。 项目简介 项目获取 &#x1f345;文末点击…

常用类四(Math类)

目录 Math 类的常用方法&#xff1a; Random 类的常用方法&#xff1a; java.lang.Math 提供了一系列静态方法用于科学计算&#xff1b;其方法的参数和返回值类型一般 为 double 型。如果需要更加强大的数学运算能力&#xff0c;计算高等数学中的相关内容&#xff0c;可以使用…

【Java程序设计】【C00343】基于Springboot的船运物流管理系统(有论文)

基于Springboot的船运物流管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 项目获取 &#x1f345;文末点击卡片获取源码&#x1f345; 开发环境 运行环境&#xff1a;推荐jdk1.8&#xff1b; 开发工具&#xff1a;eclipse以及i…

libVLC 视频缩放

libvlc是一个常用的开源多媒体框架&#xff0c;它可以用来播放和处理各种类型的音频和视频文件。如果想要缩放视频&#xff0c;可以通过libvlc提供的API来实现。 //设置视频的缩放比例。 libvlc_video_set_scale() 以下是如何使用 libVLC 设置视频缩放的基本步骤&#xff1a;…

根据IP地址获取归属地

IP获取归属地&#xff0c;通过地址库获取 如果使用API接口获取&#xff0c;可能会出现服务挂了&#xff0c;或者服务地址不提供服务了等问题。而采用本地地址库就没有这些问题。 本文采用离线IP地址定位库 Ip2region&#xff0c;Ip2region是一个离线IP地址定位库&#xff0c;微…

ElasticSearch之数据建模

写在前面 本文看下es数据建模相关的内容。 1&#xff1a;什么是数据建模 数据建模是对真实数据的一种抽象&#xff0c;最终映射为计算机形式的表现。其包括如下三个阶段&#xff1a; 1&#xff1a;概念模型 2&#xff1a;逻辑模型 3&#xff1a;数据模型2&#xff1a;es数据…

案例分享:F5助力车企打造智能高效自动化应用

纵观当下的汽车市场&#xff0c;智能汽车百花齐放。自动驾驶、车载娱乐、实时3D地图等实现人机互动的出行场景&#xff0c;解锁着全新的出行方式。然而得到独特而先进的智能用车体验&#xff0c;离不开持续而深入的汽车应用变革。那么怎样打造智能高效的自动化应用呢&#xff1…

JavaWeb后端——HTTP协议/Tomcat

HTTP HTTP协议&#xff1a;无状态&#xff0c;对事务处理没有记忆能力。每次请求-响应都是独立的。后一次请求不会记录前一次请求数据。缺点&#xff1a;多次请求之间不能共享数据&#xff0c;优点&#xff1a;速度快。 HTTP协议请求报文&#xff1a; HTTP协议响应报文&#x…

(MATLAB)第二十一章 Simulink仿真设计初步

Simulink是MATLAB的重要组成部分&#xff0c;可以非常容易地实现可视化建模&#xff0c;并把理论研究和工程实践有机地结合在一起&#xff0c;不需要书写大量程序&#xff0c;只需要使用鼠标和键盘对已有模块进行简单的操作和设置。 21.1 Simulink简介 Simulink是MATLAB软件的…

一、Java开发环境搭建-----系统类的简单使用

JavadocAPI文档练习&#xff1a; 1、Date类的使用——代码实战 Date类为日期类&#xff0c;是Java中和日期相关的一个类&#xff0c;如下将日期做一个简单的介绍。 package com.kangning.web.controller.common;import java.util.Date;public class DateDemo1 {public static…

SAP/ERP系统PP模块常用增强之二:报表COOIS增加字段

SAP/PP模块中的COOIS报表(订单信息系统)是最常用的标准报表之一,它可以查询有关生产订单的完整信息,但实际项目实施中也会经常遇到这个报表增强需求,一般要求增加一些产品相关的一些额外信息。 SAP系统为此类需求预留第三代BADI增强出口,可以非常方便的实现在COOIS报表中…

水泊梁山108小酒坛之小李广花荣

小李广花荣&#xff0c;是中国著名小说《水浒传》中的108将之一&#xff0c;有“百步穿杨”的功夫。在梁山泊英雄中排行第九&#xff0c;为马军八虎骑兼先锋使之首。原是清风寨副知寨&#xff0c;使一杆银枪&#xff0c;一张弓射遍天下无敌手&#xff0c;生得一双俊目&#xff…

谈谈消息队列

这篇文章我们来聊聊消息队列。我一直在想&#xff0c;能不能用一篇文章就把消息队列的所有内容给串联起来。然后&#xff0c;之后每次看到这篇文章的时候&#xff0c;我就能够立马回忆起来这个大知识的所有知识点。所以我想尝试一下用这种长文的方式&#xff0c;将我自己对于消…

财富池指标公式--通达信资金进场买入提示指标公式

1、“准备现金”信号出现&#xff0c;可开始关注该个股&#xff0c;等待合适价位介入&#xff0c;较为激进的投资者也可在此时介入&#xff0c;更稳健的做法是&#xff0c;等到“买入股票”信号出现后再介入。 2、“见顶清仓”信号出现&#xff0c;预示着即将见顶&#xff0c;是…

Matlab从入门到精通课程

教程介绍 MATLAB是美国MathWorks公司出品的商业数学软件&#xff0c;用于数据分析、无线通信、深度学习、图像处理与计算机视觉、信号处理、量化金融与风险管理、机器人&#xff0c;控制系统等领域。 学习地址 链接&#xff1a;https://pan.baidu.com/s/1PxGarBwQusMzwPVqcE…