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

news2024/11/15 5:01:04

推荐阅读

  • 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和坑,让后来人可以有些参考。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习 - 神经网络分类

什么叫做分类问题&#xff1f; A classification problem involves predicting whether something is one thing or another. Problem typeWhat is it?ExampleBinary classificationTarget can be one of two options, e.g. yes or noPredict whether or not someone has hea…

AXI_Lite协议详解

文章目录 摘要一、AXI_Lite接口全局信号&#xff1a;1、写地址通道&#xff1a;2、写数据通道&#xff1a;3、写响应通道&#xff1a;4、读地址通道&#xff1a;5、读数据通道&#xff1a; 二、仿真波形 摘要 AXI4-lite是AXI4-full的简化版。用于简单、低吞吐量的内存映射通信…

基于CNN-RNN的动态手势识别系统构建与应用

一、引言 随着人机交互技术的不断发展&#xff0c;动态手势识别成为了近年来的研究热点。动态手势识别技术能够识别和理解人类的手势动作&#xff0c;从而实现更自然、更直观的人机交互。本文旨在构建一种基于CNN-RNN的动态手势识别系统&#xff0c;以提高手势识别的准确性和实…

36.基于SpringBoot + Vue实现的前后端分离-高校汉服租赁网站系统(项目 + 论文)

项目介绍 本站是一个B/S模式系统&#xff0c;采用SpringBoot Vue框架&#xff0c;MYSQL数据库设计开发&#xff0c;充分保证系统的稳定性。系统具有界面清晰、操作简单&#xff0c;功能齐全的特点&#xff0c;使得基于SpringBoot Vue技术的高校汉服租赁网站系统设计与实现管理…

Go第三方框架--gin框架(二)

4. gin框架源码–Engine引擎和压缩前缀树的建立 讲了这么多 到标题4才开始介绍源码&#xff0c;主要原因还是想先在头脑中构建起 一个大体的框架 然后再填肉 这样不容易得脑血栓。标题四主要涉及标题2.3的步骤一 也就是 标题2.3中的 粗线框中的内容 4.1 Engine 引擎的建立 见…

Filter、Listener、AJAX

Filter 概念&#xff1a;Filter 表示过滤器&#xff0c;是JavaWeb三大组件(Servlet、Filter、 Listener)之一。 过滤器可以把对资源的请求拦截下来&#xff0c;从而实现一些特殊的功能。 过滤器一般完成一些通用的操作&#xff0c;比如&#xff1a;权限控制、统一编码处理、敏感…

Mac 装 虚拟机 vmware、centos7等

vmware&#xff1a; https://www.vmware.com/products/fusion.html centos7 清华镜像&#xff1a; 暂时没有官方的 m1 arm架构镜像 centos7 链接: https://pan.baidu.com/s/1oZw1cLyl6Uo3lAD2_FqfEw?pwdzjt4 提取码: zjt4 复制这段内容后打开百度网盘手机App&#xff0c;操…

【Python】Scrapy整合FastAPI实现爬虫API 附大量示例

文章目录 前言1. 网页分析入门1.1 基本原理1.2 Scrapy 原理 2. 创建项目2.1 创建Scrapy项目2.2.1 创建Scrapy项目2.2.2 创建Spider2.2.3 执行Demo 2.2 引入FastAPI 2. 获取Cookie3. 数据建模3.1 Scrapy 数据建模3.2 SQLAlchemy 创建实体类 3. 分析网页3.1 xpath 分析3.2 css 分…

计算机进制转换:二进制、八进制、十进制、十六进制。原码、补码、反码。

一、什么是进制 在生活中&#xff0c;我们通常都是使用阿拉伯数字计数的&#xff0c;也就是10进制&#xff0c;以10为单位&#xff0c;遇10进一&#xff0c;所以是由0&#xff0c;1&#xff0c;2、3、4、5、6、7、8、9组成的&#xff1b;而在计算机中&#xff0c;计算机是无法…

AI工具排行榜:最全工具汇总

如今,人工智能技术正在快速崛起,AI助手、语音识别、机器翻译等工具深深渗透到我们的工作和生活中。这些智能工具极大地提高了我们的工作效率,使我们能更加专注于创造性的任务。 本文将为读者推荐一些实用的AI神器,只要掌握其中一个,就能极大地提升你的工作能力,事半功倍。这些…

YOLOv9代码解读[01] readme解读

文章目录 YOLOv9COCO数据集上指标&#xff1a;环境安装训练验证重参数化 Re-parameterization推断相关链接 YOLOv9 paper: YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information github: https://github.com/WongKinYiu/yolov9 COCO数据集上指…

如何使用Python进行网络安全与密码学【第149篇—密码学】

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 用Python进行网络安全与密码学&#xff1a;技术实践指南 随着互联网的普及&#xff0c;网络…

CSS(四)

一、CSS浮动 1.1 传统网页布局的三种方式 网页布局的本质——用 CSS 来摆放盒子。 把盒子摆放到相应位置. CSS 提供了三种传统布局方式(简单说,就是盒子如何进行排列顺序)&#xff1a; 普通流&#xff08;标准流&#xff09; 浮动 定位 1.2 标准流&#xff08;普通流/文档…

【C++】哈希应用之位图

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.位图的概念 2.位…

基于React的低代码平台开发实践

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;在线地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…

day07-缓存商品、购物车

1. 缓存菜品 1.1 问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大。 结果&#xff1a; 系统响应慢、用户体验差 1.2 实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓…

Java 在PDF中插入页眉、页脚

在处理PDF文档时&#xff0c;有时需要为文档中的每一页添加页眉和页脚&#xff0c;以包含一些有用的信息&#xff0c;如文档标题、章节名称、日期、页码等。对于需要自动化处理的场景&#xff0c;或者需要在大量文档中添加一致的页眉和页脚&#xff0c;可以通过编程的方式来实现…

java Web餐馆订单管理系统用eclipse定制开发mysql数据库BS模式java编程jdbc

一、源码特点 JSP 餐馆订单管理系统是一套完善的web设计系统&#xff0c;对理解JSP java 编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发&#xff0c;数据库为Mysql5.0&#xff0c;使…

【超图 SuperMap3D】【基础API使用示例】51、超图SuperMap3D - 绘制圆|椭圆形面标注并将视角定位过去

前言 引擎下载地址&#xff1a;[添加链接描述](http://support.supermap.com.cn/DownloadCenter/DownloadPage.aspx?id2524) 绘制圆形或者椭圆形效果 核心代码 entity viewer.entities.add({// 圆中心点position: { x: -1405746.5243351874, y: 4988274.8462937465, z: 370…

git reset版本回退后悔药(图文例子)

目录 版本回退前期测试样例准备git reset --soft 不撤销add,撤销commit,保留修改git reset --mixed 或 git reset () 撤销add,撤销commit,保存修改git reset --hard 撤销add,撤销commit,不保存修改git reset --merge 取消合并git reset --keep 不撤销add,撤销commit,根据情况判…