【Unity】实现从Excel读取数据制作年份选择器

效果预览:

此处利用Excel来读取数据来制作年份选择器,具体步骤如下。

如果只是制作年份选择器可以参考我这篇文章:构建简单实用的年份选择器(简单原理示范)

目录

效果预览:

一、 Excel准备与存放

1.1 Excel准备

1.2 存放Excel

1.3 读取Excel准备

二、场景准备 

三、编写脚本 

四、总结 


一、 Excel准备与存放

1.1 Excel准备

打开Excel,填写内容,保存命名为“年份”。示例如下:

1.2 存放Excel

将命名为“年份”的excel文件存放在Assets根目录下

1.3 读取Excel准备

读取Excel的几种方式可以参考这篇文章:读取Excel的几种方式

此处使用DLL插件读取

将所需插件放入Plugins文件夹中

二、场景准备 

 场景包括显示年份的背景和字体等内容,具体可以参考这篇文章: 构建简单实用的年份选择器(简单原理示范)

三、编写脚本 

此处编写了两个脚本,分别是ExcelTool和YearAdsorption,ExcelTool实现读取Excel内容并记录,YearAdsorption来实现生成年份。

using System.Data; // 引入System.Data命名空间,用于处理数据表
using System.IO; // 引入System.IO命名空间,用于文件操作
using Excel; // 引入Excel命名空间,用于读取Excel文件
using UnityEngine; // 引入UnityEngine命名空间,用于Unity相关功能

public class ExcelTool : MonoBehaviour
{
    public static string[] YearsItemsStr;//用来存放Excel中的年份
    public static int YearsItemsNum; //用来存放Excel中的年份数量
    void Start()
    {
        ReadExcel("/年份.xlsx"); // 调用读取Excel方法,并传入文件路径
    }

    // 读取Excel文件
    public void ReadExcel(string xmlName)
    {
        FileStream stream = File.Open(Application.dataPath + xmlName, FileMode.Open, FileAccess.Read, FileShare.Read); // 打开Excel文件流
        //IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream);//读取 Excel 1997-2003版本
        IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream); // 使用OpenXml读取 Excel 2007及以后的版本

        DataSet result = excelReader.AsDataSet(); // 将Excel数据读取到DataSet中

        if (stream != null)
        {
            stream.Close(); // 关闭文件流
        }

        //DataSet可以包含多个数据表,索引从0开始,所以result.Tables[0]代表第一个表格。
        int[] counts = GetCount(result.Tables[0]); // 获取Excel表格的行数和列数
        int rows = counts[0]; // 行数
        int columns = counts[1]; // 列数
        YearsItemsNum = rows - 1;//记录年份数量
        Debug.Log("Excel年份数YearsItemsNum:" + YearsItemsNum);
        YearsItemsStr = new string[rows - 1];
        Debug.Log("row:" + rows + "...col:" + columns); // 打印行数和列数信息

        // 遍历Excel表格并打印内容
        for (int i = 1; i < rows; i++)//将表头"年份"不包括在内于是i!=0
        {
            for (int j = 0; j < columns; j++)
            {
                Debug.Log(result.Tables[0].Rows[i][j].ToString()); // 打印单元格内容
                YearsItemsStr[i-1] = result.Tables[0].Rows[i][j].ToString();
            }
        }
    }

    // 获取数据表的行数和列数
    private int[] GetCount(DataTable dt)
    {
        int i = dt.Rows.Count; // 获取行数
        for (int m = 0; m < dt.Rows.Count; m++)
        {
            if (string.IsNullOrEmpty(dt.Rows[m][0].ToString())) // 判断第一列是否为空
            {
                i = m; // 如果为空,记录有效行数
                break;
            }
        }

        int j = dt.Columns.Count; // 获取列数
        for (int n = 0; n < dt.Columns.Count; n++)
        {
            if (string.IsNullOrEmpty(dt.Rows[0][n].ToString())) // 判断第一行是否为空
            {
                j = n; // 如果为空,记录有效列数
                break;
            }
        }
        return new int[] { i, j }; // 返回行数和列数的数组
    }
}

using UnityEngine;
using UnityEngine.UI;

public class YearAdsorption : MonoBehaviour
{
    public GameObject yearTextPrefab; // 预设的年份Text对象
    public ScrollRect scrollRect;
    public float scaleDifference = 0.5f; // 缩放差异
    public RectTransform contentRectTrans; // Scroll Rect Content的RectTransform


    private RectTransform[] items;//用来存放生成的年份
    //int yearsCount = 40; // 年份总数
    float viewPortSize;
    float center;
    int itemCount;
    void Start()
    {
        // 获取ScrollView的视图大小300;
        viewPortSize = scrollRect.viewport.rect.height;
        Debug.Log("ScrollView的视图大小:" + viewPortSize);
        // 计算ScrollView的中心位置
        center = scrollRect.transform.position.y;// - viewPortSize / 2;       
        Debug.Log("ScrollView的中心位置:" + center);

        Debug.Log("YearAdsorption的YearsItemsNum:" + ExcelTool.YearsItemsNum);
        for (int i = 0; i < ExcelTool.YearsItemsNum; i++)//int i = 0; i < yearsCount; i++
        {
            GenerateYearText(ExcelTool.YearsItemsStr[i]);//1950+iint.Parse(ExcelTool.YearsItemsStr[i])
            Debug.Log("YearAdsorption年份:" + ExcelTool.YearsItemsStr[i]);
        }
        //for (int i = 0; i < yearsCount; i++)//int i = 0; i < yearsCount; i++
        //{
        //    GenerateYearText((1950 + i).ToString());//1950+iint.Parse(ExcelTool.YearsItemsStr[i])
        //}

        // 获取ScrollView中的所有子对象
        itemCount = scrollRect.content.childCount;
        items = new RectTransform[itemCount];
        for (int i = 0; i < itemCount; i++)
        {
            items[i] = scrollRect.content.GetChild(i).GetComponent<RectTransform>();
            //Debug.Log("items[i]: " + i);
        }
    }

    void Update()
    {
        foreach (RectTransform item in items)
        {
            // 计算每个项目的中心位置
            float itemCenter = item.transform.position.y;// - item.rect.height / 2;
            //Debug.Log("每个项目的中心位置: " + itemCenter);
            // 计算每个项目相对于ScrollView中心的偏移量
            float distanceFromCenter = Mathf.Abs(center - itemCenter);

            // 根据偏移量计算缩放比例
            float scale = Mathf.Clamp(1 - distanceFromCenter * scaleDifference / viewPortSize, 0.5f, 1f);
            //Debug.Log("根据偏移量计算缩放比例: " + scale);
            // 应用缩放
            item.localScale = new Vector3(scale, scale, 1f);
        }


        // 如果用户停止滑动,则吸附到最近的年份
        if (scrollRect.velocity.magnitude <= 20.0f)
        {
            SnapToNearestYear();
            Debug.Log("不移动了!");
        }
    }
    private void GenerateYearText(string year)
    {
        GameObject yearText = Instantiate(yearTextPrefab, contentRectTrans);
        yearText.transform.SetAsFirstSibling();
        yearText.transform.GetComponent<Text>().text = year.ToString();
    }

    void SnapToNearestYear()
    {
        RectTransform closestItem = null;

        foreach (RectTransform item in items)
        {
            float distance = Mathf.Abs(center - item.position.y);
            if (distance < 35)// 根据需求调整阈值
            {
                closestItem = item;
                Debug.Log("装入了一个Item");
            }
        }

        // 将最近的年份吸附到ScrollView的中心
        if (closestItem != null)
        {
            // 计算需要移动的距离
            float distanceToMove = center - closestItem.position.y;

            // 将ScrollView的内容向上或向下移动,使最近的年份对象出现在ScrollView的中心
            scrollRect.content.anchoredPosition += new Vector2(0f, distanceToMove);
        }
    }
}

这里注意两个脚本的执行顺序,ExcelTool需要在YearAdsorption之前执行

修改执行顺序可以参考我这篇文章:如何设置Unity脚本的执行顺序?

将两个脚本挂载Canvas上,拖入相应物体并运行 。

四、总结 

以上实现步骤具体内容可参考以下文章:

如何在 Unity 中创建带有缩放效果的滚动视图?(简单方法)

如何在Unity 中创建带有缩放效果的滚动视图(具有吸附效果的实现与优化)

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

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

相关文章

【问题解决】| conda不显示指示前面的(base)无法在终端激活虚拟环境

1 遇到的问题 就是在安装好conda&#xff0c;配置好环境变量后 可以正常用conda的指令&#xff0c;如创建环境等等 但是不能激活新建的环境&#xff0c;我们知道同时也没有前面的小括号指示当前环境&#xff0c;也没有这个前面的(base) 2 解决方式 有一些方法如&#xff0c…

nginx 日志,压缩,https功能介绍

一&#xff0c; 自定义访问日志 &#xff08;一&#xff09;日志位置存放 1&#xff0c;格式 2&#xff0c; 级别 level: debug, info, notice, warn, error, crit, alert, emerg 3&#xff0c;示例 服务机定义 错误日志存放位置 客户机错误访问 查看错误日志 4&#xff…

table展示子级踩坑

##elemenui中table通过row中是否有children进行判断是否展示子集&#xff0c;通过设置tree-prop的属性进行设置&#xff0c;子级的children的名字可以根据自己的子级名字进行替换&#xff0c;当然同样可以对数据处理成含有chilren的子级list。 问题&#xff1a; 1.如果是根据后…

基于springboot+vue的共享汽车管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

云计算与边缘计算:有何不同?

公共云计算平台可以帮助企业充分利用全球服务器来增强其私有数据中心。这使得基础设施能够扩展到任何位置&#xff0c;并有助于计算资源的灵活扩展。混合公共-私有云为企业计算应用程序提供了强大的灵活性、价值和安全性。 然而&#xff0c;随着分布在全球各地的实时人工智能应…

WPF margin属性学习

一开始margin如下&#xff0c;显示如下&#xff1b; margin有四个值的时候是left、top、right、bottom&#xff1b; 如果是Margin“20,10”&#xff0c;则是指left、right设置为20&#xff0c;top、bottom设置为10&#xff1b; 看上去有些问题&#xff0c;现在top为负&#xf…

JAVA泛型浅析

Java范型generics&#xff0c;是JDK1.5引入的新特性&#xff0c;是一种编译时类型安全检测机制&#xff0c;可以在编译时检测到非法的类型。范型的本质是将类型参数化&#xff0c;将类型指定成一个参数。java中的集合就有使用&#xff0c;并且对外提供的三方库和SDK中使用也极为…

【ElfBoard】基于 Linux 的智能家居小项目

大家好&#xff0c;我是 Hello阿尔法&#xff0c;这段时间参与了保定飞凌嵌入式技术有限公司举办的 ElfBoard 共创社招募活动&#xff0c;并有幸成为了一名共创官&#xff0c;官方寄来了一块 ELF 1 开发板&#xff0c;开箱看这里 ELF 1 开箱初体验。 作为共创官&#xff0c;我…

NoSQL--虚拟机网络配置

目录 1.初识NoSQL 1.1 NoSQL之虚拟机网络配置 1.1.1 首先&#xff0c;导入预先配置好的NoSQL版本到VMware Workstation中 1.1.2 开启虚拟机操作&#xff1a; 1.1.2.1 点击开启虚拟机&#xff1a; 1.1.2.2 默认选择回车CentOS Linux&#xff08;3.10.0-1127.e17.x86_64) 7 …

3DGS学习(六)—— 参数更新

参数更新 参考文章&#xff1a;3dgs中的数学推导 协方差矩阵的参数更新 直接通过pytorch自带的更新机制&#xff0c;通过渲染后计算损失&#xff0c;只能更新2D协方差矩阵 Σ ′ \Sigma^\prime Σ′&#xff0c;再通过公式逆推出3d空间协方差矩阵 Σ \Sigma Σ的值。该过程处…

【Linux】云服务器的Redis被黑

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;Linux ⛺️稳中求进&#xff0c;晒太阳 攻击发现&#xff1a; 这个异常情况是在腾讯云被入侵后&#xff0c;短信提醒发现的。并没有系统的学习过关于服务器安防相关的知识&#xff0c;遇到…

三天学会阿里分布式事务框架Seata-SpringCloud Alibaba分布式基础案例搭建

锋哥原创的分布式事务框架Seata视频教程&#xff1a; 实战阿里分布式事务框架Seata视频教程&#xff08;无废话&#xff0c;通俗易懂版&#xff09;_哔哩哔哩_bilibili实战阿里分布式事务框架Seata视频教程&#xff08;无废话&#xff0c;通俗易懂版&#xff09;共计10条视频&…

10 在线逻辑分析仪的使用

在线逻辑分析仪简介 传统的 FPGA 板级调试是将逻辑分析仪连接到 FPGA 的 IO 引脚上 &#xff0c;然后将内部信号引出至 IO 引脚&#xff0c;再进行板级调试&#xff0c;这种方法的缺点是我们需要一个逻辑分析仪&#xff0c;且还要在 PCB 中预留测试点。在线逻辑分析仪克服了以…

配电房轨道式巡检机器人方案

一、应用背景 在变电站、配电房、开关站等各种室内变配电场所内&#xff0c;由于变配电设备的数量众多、可能存在各类安全隐患&#xff0c;为了保证用电的安全可靠&#xff0c;都要进行日常巡检。 但目前配电房人工巡检方式有以下主要问题&#xff1a; 巡检工作量大、成本高 …

三、西瓜书——神经网络

一、神经元模型 在M-P神经网络模型中&#xff0c;神经元接 收到来自n个其他神经元传递过来的输入信号&#xff0c;这些输入信号通过带权重的连接(connection)进行传递&#xff0c;神经元接收到的总输入值将与神经元的阈值进行比较&#xff0c;然后通过“激活函数”(activation …

【数据结构】C语言实现二叉树的相关操作

树 定义 树&#xff08;Tree&#xff09;是 n (n > 0) 个结点的有限集 若 n 0&#xff0c;称为空树 若 n > 0&#xff0c;则它满足如下两个条件&#xff1a; 有且仅有一个特定的称为根&#xff08;Root&#xff09;的结点其余结点可分为 m(m>0) 个互不相交的有限…

第十三篇【传奇开心果系列】Python的文本和语音相互转换库技术点案例示例:Microsoft Azure的Face API开发人脸识别门禁系统经典案例

传奇开心果博文系列 系列博文目录Python的文本和语音相互转换库技术点案例示例系列 博文目录前言一、实现步骤和雏形示例代码二、扩展思路介绍三、活体检测深度解读和示例代码四、人脸注册和管理示例代码五、实时监控和报警示例代码六、多因素认证示例代码七、访客管理示例代码…

ES6 | (二)ES6 新特性(下) | 尚硅谷Web前端ES6教程

文章目录 &#x1f4da;迭代器&#x1f407;定义&#x1f407;工作原理&#x1f407;自定义遍历数据 &#x1f4da;生成器函数&#x1f407;声明和调用&#x1f407;生成器函数的参数传递&#x1f407;生成器函数案例 &#x1f4da;Promise&#x1f4da;Set&#x1f407;Set的定…

AI大预言模型——ChatGPT在地学、GIS、气象、农业、生态、环境应用

原文链接&#xff1a;AI大预言模型——ChatGPT在地学、GIS、气象、农业、生态、环境应用 一开启大模型 1 开启大模型 1)大模型的发展历程与最新功能 2)大模型的强大功能与应用场景 3)国内外经典大模型&#xff08;ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diff…

【论文阅读】微纳米气泡技术作为CO2-EOR和CO2地质储存技术的新方向:综述

Micro and nanobubbles technologies as a new horizon for CO2-EOR and CO2 geological storage techniques: A review 微纳米气泡技术作为CO2-EOR和CO2地质储存技术的新方向&#xff1a;综述 期刊信息&#xff1a;Fuel 2023 期刊级别&#xff1a;EI检索 SCI升级版工程技术1区…