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

news2025/7/15 7:49:58

效果预览:

此处利用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 中创建带有缩放效果的滚动视图(具有吸附效果的实现与优化)

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

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

相关文章

IntelliJ IDEA上svn分支管理和使用

IntelliJ IDEA上svn分支管理和使用 从Subversion下载trunk下的代码 选择项目创建分支 右键 Subversion --> branch or Tag … 选择Repository Location:需要创建的项目 选择Any Location 分支的位置和名字 详细查看截图 切换到分支 选择项目右键Subversion --> Update …

初阶数据结构:链表相关题目练习(补充)

目录 1. 单链表相关练习题1.1 移除链表元素1.2 反转链表1.3 链表的中间结点1.4 链表的倒数第k个结点1.5 合并两个有序链表1.6 链表分割1.7 链表的回文结构1.8 相交链表1.9 判断一个链表中是否有环1.10 寻找环状链表相遇点1.11 链表的深度拷贝 1. 单链表相关练习题 注&#xff1…

低功耗微处理器复位检测电路D706,工作温度范围-40~+80℃,可与μP监控产品兼容

近年来&#xff0c;微处理器在IT业控制领域和智能化产品中得到了广泛的应用。在系统和产品的开发设计过程中&#xff0c;为了提高其抗干扰能力&#xff0c;使用μP监控是首选技术措施之一。监控芯片可为系统提供上电、掉电复位功能&#xff0c;也可提供其它功能&#xff0c;如后…

SpringBoot 自定义注解实现操作日志记录

文章目录 前言正文一、项目结构介绍二、核心类2.1 核心注解2.1.1 CLog 日志注解2.1.2 ProcessorBean 处理器bean 2.2 切面类2.3 自定义线程池2.4 工具类2.4.1 管理者工具类 2.5 测试2.5.1 订单创建处理器2.5.2 订单管理者2.5.3 订单控制器2.5.4 测试报文2.5.5 测试结果 附录1、…

Docker部署前后端服务示例

使用Docker部署js前端 1.创建Dockerfile 在项目跟目录下创建Dockerfile文件&#xff1a; # 使用nginx作为基础镜像 FROM nginx:1.19.1# 指定工作空间 WORKDIR /data/web# 将 yarn build 打包后的build文件夹添加到工作空间 ADD build build# 将项目必要文件添加到工作空间&a…

【Python】FastAPI 项目创建 与 Docker 部署

文章目录 前言&需求描述1. 本地FastAPI1.1 Python 环境准备1.2 本地 Pycharm 创建FastAPI项目 2. Python FastAPI 部署2.1 服务器配置Python环境2.2.1 下载与配置Git、Pyenv等工具2.2.2 下载与配置Python 2.2 FastAPI 打包成镜像2.2.1 项目准备所需环境文件2.2.2 编写Docke…

python matplotlib 三维实体圆柱图

环境 python:python-3.12.0-amd64 包: matplotlib 3.8.2 import matplotlib.pyplot as plt import matplotlib as mpl import numpy as np from mpl_toolkits.mplot3d import Axes3D import matplotlib.ticker as tickerdef map_rate(X: list, to_min: float, to_max: float)…

Restful风格解释

示例对比 传统风格开发 Restful风格开发 结论&#xff1a; 传统风格开发中&#xff0c;前端不同操作使用不同的url来访问后端&#xff0c;使得访问变得麻烦restful风格中&#xff0c;前端使用相同的url来访问后端&#xff0c;但是用数据传送方式进行区分&#xff08;get为请求…

DataGrip2023配置连接Mssqlserver、Mysql、Oracle若干问题解决方案

1、Mssqlserver连接 本人连的是Sql2008&#xff0c;默认添加时&#xff0c;地址、端口、实例、账号、密码后&#xff0c;测试连接出现错误。 Use SSL&#xff1a;不要勾选 VM option&#xff1a;填写&#xff0c;"-Djdk.tls.disabledAlgorithmsSSLv3, RC4, DES, MD5withR…

c#使用log4net的3种调用方法

https://blog.csdn.net/summer_top/article/details/107961245 第一步&#xff1a;下载log4net。 右键项目引用&#xff0c;进入管理NuGet包。 搜索log4net&#xff0c;下载安装。 第二步&#xff1a;创建LogHelper类。 public class LogHelper { private LogHelp…

说一说kong日志级别

Kong官网&#xff1a;The Platform Powering the API World | Kong Inc. Kong Gateway&#xff1a;Kong Gateway | Kong Docs Kong Admin API&#xff1a;Admin API - Kong Gateway - v3.4.x | Kong Docs Kong 企业版社区&#xff1a;API Community for Developers and Industr…

ad18学习笔记十六:如何放置精准焊盘到特定位置,捕抓功能的讲解

网上倒是一堆相关的指导 AD软件熟练度提升&#xff0c;如何设置板框捕捉&#xff1f;_哔哩哔哩_bilibili 关于Altium Designer 20 的捕抓功能的讲解_ad捕捉设置-CSDN博客 AD软件捕捉进阶实例&#xff0c;如何精确的放置布局元器件&#xff1f;_哔哩哔哩_bilibili AD绘制PCB…

android游戏开发大全pdf,赶紧学起来

面经分享 第一部分是我前端面试的经验总结&#xff0c;第二部分是我认为比较有思考空间的题目 经验总结 一份漂亮的简历&#xff0c;需要包括以下部分&#xff08;排版由上而下&#xff09; 个人亮点&#xff08;专精领域&#xff0c;个人博客&#xff0c;开源项目&#xff09…

jmeter 压测数据库

当前版本&#xff1a; jmeter 5.6.3mysql 5.7.39 简介 JMeter 是一个开源的 Java 应用程序&#xff0c;主要用于进行性能测试和负载测试。它支持多种协议&#xff0c;包括但不限于 HTTP、HTTPS、FTP、JDBC 以及各种 Web Services。对于数据库的压力测试可以使用 JDBC 协议与数…

Python算法题集_组合总和

Python算法题集_组合总和 题39&#xff1a;组合总和1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【值传递回溯】2) 改进版一【引用传递堆栈回溯】3) 改进版二【过程值列表缓存遍历后检索】 4. 最优算法5. 相关资源 本文为Python算法题集之一的…

【办公类-22-07】周计划系列(3-2)“信息窗+主题知识(优化)” (2024年调整版本)

作品展示&#xff1a; 背景需求 前文对“2023年2月”的一套信息窗主题知识的文件系列&#xff0c;进行第一次的提取。获得基础模板。 【办公类-22-07】周计划系列&#xff08;3-1&#xff09;“信息窗主题知识&#xff08;提取&#xff09;” &#xff08;2024年调整版本&…

面试官问我Redis怎么测,我哪知道!

有些测试朋友来问我&#xff0c;redis要怎么测试&#xff1f;首先我们需要知道&#xff0c;redis是什么&#xff1f;它能做什么&#xff1f; redis是一个key-value类型的高速存储数据库。 redis常被用做&#xff1a;缓存、队列、发布订阅等。 所以&#xff0c;“redis要怎么测试…

理解计算着色器中glsl语言的内置变量

概要 本文通过示例的方式&#xff0c;着重解释以下几个内置变量&#xff1a; gl_WorkGroupSizegl_NumWorkGroupsgl_LocalInvocationIDgl_WorkGroupIDgl_GlobalInvocationID 基本概念 局部工作组与工作项 一个3x2x1的局部工作组示例如下&#xff0c;每个小篮格子表示一个工作项…

简单了解B树和B+树

目录 B树 B树 B树和B树的结构示意图 总结 B树和B树是两种非常重要的树状数据结构&#xff0c;它们广泛应用于数据库和文件系统的索引结构中。这两种数据结构能够帮助我们高效地管理、查询以及更新大量的数据。下面&#xff0c;我将简单介绍它们,以及他们之间的区别。 B树 B…

【leetcode】链表的中间节点

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家刷题&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 点击查看题目 思路: slow和fast都初始化为head&#xff0c;之后slow每走1步&#xff0c;fast走2步…