使用Unity做一个电脑可直接运行的点名神器,可直接导入Excel文档使用哦文末源码

Posted 呆呆敲代码的小Y

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Unity做一个电脑可直接运行的点名神器,可直接导入Excel文档使用哦文末源码相关的知识,希望对你有一定的参考价值。

  • 📢博客主页:https://blog.csdn.net/zhangay1998
  • 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
  • 📢本文由 呆呆敲代码的小Y 原创,首发于 CSDN🙉
  • 📢未来很长,值得我们全力奔赴更美好的生活✨


📢前言

好久没有做一些小案例玩了,今天突发奇想要做一个 点名神器 玩一下!

其实点名这个功能做出来很简单,不过就是在一个名单库里面随机一个数值显示出来就好啦!

下面一起看一下这个小案例是怎样做出来的吧!


🍓Unity做一个电脑和手机都可以直接用的【点名神器】,可导入Excel文档直接使用

大家应该都Unity可以打包成电脑直接运行的exe文件,也可以打包成手机直接运行的APP文件

所以我就想着做一个功能稍微多一点点的点名神器

那就是加入一个可选择的Excel文档,我们可以事先在Excel文档中加入所有需要被点名的名单即可

下面我就一步一步来做给大家看一下吧!博主使用的Unity版本为:2020.3.8 f1c1


🍋第一步,打开Unity新建一个项目

打开UnityHub新建一个项目,新版本的Unity都需要使用UnityHub来运行程序,还没下载UnityHub的推荐下载哦~
设置一下项目名称路径,然后点击创建即可!


然后等待新创建的Unity加载完毕即可~


🍊第二步,怎样读取Excel文档中的数据并使用

  • 做这个点名器的思路很简单,就是从一个名字库里面随机读取一个名字显示到UI上即可!

  • 这个 名字库 的实现方法有很多种,可以直接创建一个List列表,将所有的名字数据录入,然后读取即可~

  • 我们可以实现把学生名单放到 Json 或者 Excel等等方式存取,然后在脚本中直接录入List就可以用了

  • 但是我觉得Excel在实际情况中可能用起来更方便,毕竟 使用电脑的人都会用Excel,但是却不一定会使用Json 等等方式!

  • 说了一堆废话,只是表达一下使用Excel文件的意义~ 下面一起来看看怎样读取Excel文件吧!

首先,在unity中想读取Excel文件要先导入库文件 Excel.dllICSharpCode.SharpZipLib 库文件
官方链接: http://exceldatareader.codeplex.com/

Excel文件示例:

导入库文件 Excel.dllICSharpCode.SharpZipLib 之后,在Unity中创建一个脚本StudentDemo

示例代码如下:

using System.IO;
using Excel;
using System.Data;
using UnityEngine;

public class StudentDemo : MonoBehaviour
{
    void Start()
    {
        FindXLSX();
    }
    
    void FindXLSX()
    {
        FileStream stream = File.Open(Application.dataPath, FileMode.Open, FileAccess.Read);
        IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);

        DataSet result = excelReader.AsDataSet();

        int columns = result.Tables[0].Columns.Count;
        int rows = result.Tables[0].Rows.Count;

        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < columns; j++)
            {
                string nvalue = result.Tables[0].Rows[i][j].ToString();
                Debug.Log(nvalue);
            }
        }
    }

}

该脚本的作用就是通过 File.Open 读取指定文件路径下的 Excel文件

然后再通过库文件中的方法,将Excel中的数据保存成Unity可使用的string字符串形式,然后通过遍历就可以拿到数据使用了

比如上述脚本执行的结果为:

然后接下来就可以创建一个列表来调用这个名单啦!


🍇第三步,将学生名单导入到List列表中 并随机显示某个名字

  • 在上一步中我们通过读取Excel文件拿到了学生姓名的数据
  • 那接下就是将这个名单合理利用,达到我们想要的一个效果啦!

我们先在场景中搭建一个简单的UI,待会用来显示点名的功能

先在场景添加两个Button按钮三个Text文本
Button分别用来随机名单 和 开始点名,Text文本用来显示标题、名单列表 和 点名

然后把相机的渲染模式设置为纯色模式,简单的选个颜色

简略效果如下

然后需要继续在脚本中添加代码,完整代码如下:

using System.IO;
using Excel;
using System.Data;
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;

public class StudentDemo : MonoBehaviour
{
    public Button FindXLSXBtn;
    public Button startNameBtn;

    public Text NameText;
    public Text NameSum;

    private List<string> StudentNameList;
    private int aName;
    private bool ISrandom = true;
    private bool IsOK = true;

    private void Start()
    {
        StudentNameList = new List<string>();
        FindXLSXBtn.onClick.AddListener(FindXLSX);
        startNameBtn.onClick.AddListener(startName);
        StudentNameList.Add("再来一次!");
    }
    private void Update()
    {
        if (!ISrandom)
        {
            NameText.text = StudentNameList[Random.Range(0, StudentNameList.Count)];
        }

    }

    void FindXLSX()
    {
        ISrandom = false;

        if (IsOK)
        {
            IsOK = false;
            FileStream stream = File.Open(Application.dataPath + "/StudentName.xlsx", FileMode.Open, FileAccess.Read);
            IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);

            DataSet result = excelReader.AsDataSet();

            int columns = result.Tables[0].Columns.Count;
            int rows = result.Tables[0].Rows.Count;

            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < columns; j++)
                {
                    string nvalue = result.Tables[0].Rows[i][j].ToString();
                    StudentNameList.Add(nvalue);
                    // Debug.Log(nvalue);
                    NameSum.text += nvalue + "\\n";
                }
            }
        }
          
    }
    /// <summary>
    /// 点名开始
    /// </summary>
    void startName()
    {
        ISrandom = !ISrandom;
        aName = Random.Range(0, StudentNameList.Count);
        NameText.text = StudentNameList[aName];
    }
}

代码解析:

在代码中添加了对应的Button的点击事件,创建了一个List列表用来存储从Excel文件中读取的名单,在遍历的时候将名单添加进List中

然后让Text文本通过 Random.Range方法 制造一个随机数,最小值为0,最大值为List列表的最大索引

然后在Update中通过Random.Range随机显示名单

然后再写一个点名的方法,随机读取一个列表中的数值显示到我们的点名名单中即可

其中通过两个boolISrandomIsOK 用于控制不用二次读取名单 和Update中的随机显示

挂载脚本后的实际效果如下:

OK,那我们现在只要能拿到Excel文件就可以正常的读取学生名单并随机读取了!

但是现在还有个问题,我们的Excel文件路径是写死的,现在读取的Excel文档是我在工程中实现放好的!

那这样的话就只能用我自己的Excel中的学生名单了,并没有什么卵用嘛~

那下一步就是添加一个可以自己读取Excel的方法,一起往下看吧!


🍈第四步,打开文件夹并选择Excel文件

我们现在读取Excel文件并随机显示名字的方法已经实现了,还差最后一步

那就是怎样让Unity打开文件夹并选择Excel文件

这个功能我并没有找到一个 官方的API 可直调用的方法,所以就使用了一个其他的打开文件夹的方案

新建一个脚本OpenFileName,代码如下:

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]

public class OpenFileName
{
    public int structSize = 0;
    public IntPtr dlgOwner = IntPtr.Zero;
    public IntPtr instance = IntPtr.Zero;
    public String filter = null;
    public String customFilter = null;
    public int maxCustFilter = 0;
    public int filterIndex = 0;
    public String file = null;
    public int maxFile = 0;
    public String fileTitle = null;
    public int maxFileTitle = 0;
    public String initialDir = null;
    public String title = null;
    public int flags = 0;
    public short fileOffset = 0;
    public short fileExtension = 0;
    public String defExt = null;
    public IntPtr custData = IntPtr.Zero;
    public IntPtr hook = IntPtr.Zero;
    public String templateName = null;
    public IntPtr reservedPtr = IntPtr.Zero;
    public int reservedInt = 0;
    public int flagsEx = 0;
}

public class WindowDll
{
    [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern bool GetOpenFileName([In, Out] OpenFileName ofn);
    public static bool GetOpenFileName1([In, Out] OpenFileName ofn)
    {
        return GetOpenFileName(ofn);
    }
}

只需要知道这个脚本是用来调用系统接口的就好啦~ 不需要理解太多(大神请便)

然后继续在我们的StudentDemo 脚本中添加代码,添加一个新方法,代码如下:

 public void OpenFileWin()
    {
        ofn.structSize = Marshal.SizeOf(ofn);

        ofn.filter = "All Files\\0*.*\\0\\0";

        ofn.file = new string(new char[256]);

        ofn.maxFile = ofn.file.Length;

        ofn.fileTitle = new string(new char[64]);

        ofn.maxFileTitle = ofn.fileTitle.Length;
        string path = Application.dataPath;
        path = path.Replace('/', '\\\\');
        //默认路径  
        ofn.initialDir = path;
        //ofn.initialDir = "D:\\\\MyProject\\\\UnityOpenCV\\\\Assets";  
        ofn.title = "Open Project";

        ofn.defExt = "xlsx";//显示文件的类型  
        //注意 一下项目不一定要全选 但是0x00000008项不要缺少  
        ofn.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000200 | 0x00000008;//OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST| OFN_ALLOWMULTISELECT|OFN_NOCHANGEDIR  

        if (WindowDll.GetOpenFileName(ofn))
        {
            Debug.Log("Selected file with full path: {0}" + ofn.file);
        }
    }

这个方法就是用来启动系统窗口的,放在Button点击事件上直接调用该方法就可以调用打开文件夹的功能了!

然后我们在脚本中新加一个Button,加上点击事件执行上面我们刚添加的方法即可!

该脚本完整代码如下:

using System.IO;
using Excel;
using System.Data;
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using System.Runtime.InteropServices;

public class StudentDemo : MonoBehaviour
{
    public Button OpenFileWinBtn;
    public Button FindXLSXBtn;
    public Button startNameBtn;

    public Text NameText;
    public Text NameSum;

    private List<string> StudentNameList;
    private int aName;
    private bool ISrandom = true;
    private bool IsOK = true;
    private OpenFileName ofn;

    private void Start()
    {
        ofn = new OpenFileName();
        StudentNameList = new List<string>();

        OpenFileWinBtn.onClick.AddListener(OpenFileWin);
        FindXLSXBtn.onClick.AddListener(FindXLSX);
        startNameBtn.onClick.AddListener(startName);
        StudentNameList.Add("再来一次!");
    }
    private void Update()
    {
        if (!ISrandom)
        {
            NameText.text = StudentNameList[Random.Range(0, StudentNameList.Count)];
        }

    }

    void FindXLSX()
    {
        ISrandom = false;

        if (IsOK)
        {
            IsOK = false;
            FileStream stream = File.Open(ofn.file, FileMode.Open, FileAccess.Read);
            IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);

            DataSet result = excelReader.AsDataSet();

            int columns = result.Tables[0].Columns.Count;
            int rows = result.Tables[0].Rows.Count;

            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < columns; j++)
                {
                    string nvalue = result.Tables[0].Rows[i][j].ToString();
                    StudentNameList.Add(nvalue);
                    // Debug.Log(nvalue);
                    NameSum.text += nvalue + "\\n";
                }
            }
        }
   
    }
    /// <summary>
    /// 点名开始
    /// </summary>
    void startName()
    {
        ISrandom = !ISrandom;

        aName = Random.Range(0, StudentNameList.Count);
        NameText.text = StudentNameList[aName];
    }

    public void OpenFileWin()
    {
        ofn.structSize = Marshal.SizeOf(ofn);

        ofn.filter = "All Files\\0*.*\\0\\0";

        ofn.file = new string(new char[256]);

        ofn.maxFile = ofn.file.Length;

        ofn.fileTitle = new string(new char[64]);

        ofn.maxFileTitle = ofn.fileTitle.Length;
        string path = Application.dataPath;
        path = path.Replace('/', '\\\\');
        //默认路径  
        ofn.initialDir = path;
        //ofn.initialDir = "D:\\\\MyProject\\\\UnityOpenCV\\\\Assets";  
        ofn.title = "Open Project";

        ofn.defExt = "xlsx";//显示文件的类型  
        //注意 一下项目不一定要全选 但是0x00000008项不要缺少  
        ofn.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000200 | 0x00000008;//OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST| OFN_ALLOWMULTISELECT|OFN_NOCHANGEDIR  

        if (WindowDll.GetOpenFileName(ofn))
        {
            Debug.Log("Selected file with full path: {0}" + ofn.file);
        }
    }

}

这个案例其实只用到了两个脚本,一个是OpenFileName,另一个是StudentDemo,直接挂载到场景中就可以啦!

效果演示如下:


🍉最后一步,打包成PC端可用的exe文件

一个基本的点名小案例我们就已经差不多做完啦,还差最后一步,打包成可直接用的exe文件

这一步很简单,一般都会做啦。

点击菜单键:File -> Build Setting ,然后将场景添加到Build之后,点击Player Setting,在面板上改一下Produce Name和 Company Name

老版本的Unity还需要自己去下面的属性面板自己改一下 PakecageName ,新版本就不需要啦!

最后点击Build,然后选择一个文件夹保存就好啦!
打包好的程序如下:

然后我们点击这个exe文件就可以运行了,运行效果如下:

提示:我在打包完成之后发现Excel文件并不能被读取数据,这算是一个严重的问题,导致我们的名单库不能正常使用从而导致无法随机选取一个名单。我在网上查了下发现是因为打包之后的exe文件是不能调用Excel的DLL文件,所以我这里是导入了其他的dll文件才使得打包好的exe文件也可以正常使用!下面的源码工程中都有,可自行体验!


🎁资源下载

本文中提到的excel相关的DLL文件案例源码打包好的exe文件 全部都放到这个资源里啦

有需求的小伙伴可以下载自己体验一下哦!尤其是需要用到点名的老师们

可以打开该exe文件然后上传学生名单的Excel文件就可以直接点名了哦!!

点击资源下载


💬总结