Unity动态加载资源 - 从硬盘任意地址加载任意格式3D模型

前言

一、Unity官方给的动态资源加载方式

二、Unity中调用windows资源管理器

三、从资源管理器获得文件地址后复制到Unity指定文件夹

附上全部代码(不完善,仅框架)


前言

Unity官方给的动态资源加载方式就不赘述了。大体分为3种:(1) Resources.Load (2)AssetBundle(3) WWW加载 。 其中前两种大多用在本地资源加载,第三种用在web端从服务器加载。前两种都只能从特定的文件夹下面加载资源,也就是Asset下面特定名字的几个文件夹。

项目需求:打开win资源浏览器,从任意目录打开一个任意格式3D模型,加载进Unity主界面上。


一、Unity官方给的动态资源加载方式

给几个关键的链接和教程(讲的都很详细),以及官方文档(完全没懂在讲啥),有需要的自取


Unity日常 - 资源加载与文件路径_51CTO博客_unity动态加载资源的方式
Unity AssetBundle 打包 四种加载方式 服务器加载_荷兰猪小灰灰的博客-CSDN博客
AssetBundle 工作流程 - Unity 手册

二、Unity中调用windows资源管理器

关键教程链接:

Unity对于window下的资源管理器的基本操作_unity 打开windows资源管理器_以梦为马,不负韶华的博客-CSDN博客

但是这个教程中的文件格式过滤器有问题,会导致在文件打开窗口右下角的“类型选择”下拉表出现乱码以及过滤不正确等问题,具体格式应该如下:

_ofn.filter = "模型文件(*.obj)\0*.obj;"
            + "\0模型文件(*.stl)\0*.stl;"
            + "\0所有支持文件(*.obj *.stl)\0*.obj;*.stl\0";

说一下格式规则:
1、 \0*.obj 中间不能有间隔。
2、说明文字模型文件(*.obj)和给系统看的 “ *.obj”一定要用 “\0” 隔开。
3、不同的类型之间用“;” 隔开。

三、从资源管理器获得文件地址后复制到Unity指定文件夹


这里建立了一个缓存文件夹“ModelsBuffer”具体代码如下: 

 // 如果读取成功,转成OBJ先放入缓存文件夹:Resources/ModelsBuffer;
        bool judge_FileBuffer = false;
        if (LocalDialog.GetOpenFileName(_ofn)){
            String path_Buffer = Application.dataPath + "/Resources/ModelsBuffer/";
            bool judge_Path = false;
            if (!Directory.Exists(path_Buffer)){
                Directory.CreateDirectory(path_Buffer);
                judge_Path = true;
            }
            else {
                judge_Path = true;
            }

            if (_ofn.fileFull.Length != 0 && judge_Path) { 
                String dir_FilenameFull = path_Buffer + _ofn.fileTitle;
                System.IO.File.Copy(_ofn.fileFull, dir_FilenameFull, true);
                AssetDatabase.Refresh();
                judge_FileBuffer = true;
            }
            else{
                Debug.Log("文件路径为空或存在不支持的语言符号种类");
            }
        }

 

切记Copy完文件一定要做一次AssetDatabase.Refresh(),刷新Unity的资产包,这样Unity才能在Resources/ModelsBuffer文件夹下正确获取文件。

然后再从缓存下加载,具体代码如下:

  // 从缓存文件夹下加载模型;
if (judge_FileBuffer){
    String _tempFN = _ofn.fileTitle.Substring(0, _ofn.fileTitle.Length - 4);
    var _obj = Resources.Load<GameObject>("ModelsBuffer/" + _tempFN);
    if (_obj){
        var _objInstant = Instantiate(_obj);
         _objInstant.transform.localScale = Vector3.one * 30;
         _objInstant.transform.localPosition = new Vector3(10f, -11.7f, 174.7f);
    }
}


附上全部代码(不完善,仅框架)


using UnityEditor;
using UnityEngine;
using UnityEngine.UI;

using System;
using System.IO;
using System.Collections;
using System.Runtime.InteropServices;

using FileIO;


// ------------------------------------------------ 主程序运行类 ------------------------------------------------ //

public class LoadFiles_win10 : MonoBehaviour
{

    // ------------------------------------------------ 打开模型;

    // 3.单击后打开文件浏览器:
    public void Click_OpenFileDialog()
    {
        //Debug.Log("getIn Click_OpenFileDialog");

        FileNameStruct _ofn = new FileNameStruct();
        _ofn.structSize = Marshal.SizeOf(_ofn);
        _ofn.filter = "模型文件(*.obj)\0*.obj;"
                    + "\0模型文件(*.stl)\0*.stl;"
                    + "\0所有支持文件(*.obj *.stl)\0*.obj;*.stl\0";
        _ofn.fileFull = new string(new char[256]);
        _ofn.maxFile = _ofn.fileFull.Length;
        _ofn.fileTitle = new string(new char[64]);
        _ofn.maxFileTitle = _ofn.fileTitle.Length;
        _ofn.initialDir = Application.streamingAssetsPath.Replace('/', '\\');//默认路径
        _ofn.title = "载入模型文件";
        _ofn.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000008;


        // 如果读取成功,转成OBJ先放入缓存文件夹:Resources/ModelsBuffer;
        bool judge_FileBuffer = false;
        if (LocalDialog.GetOpenFileName(_ofn)){
            String path_Buffer = Application.dataPath + "/Resources/ModelsBuffer/";
            bool judge_Path = false;
            if (!Directory.Exists(path_Buffer)){
                Directory.CreateDirectory(path_Buffer);
                judge_Path = true;
            }
            else {
                judge_Path = true;
            }

            if (_ofn.fileFull.Length != 0 && judge_Path) { 
                String dir_FilenameFull = path_Buffer + _ofn.fileTitle;
                System.IO.File.Copy(_ofn.fileFull, dir_FilenameFull, true);
                AssetDatabase.Refresh();
                judge_FileBuffer = true;
            }
            else{
                Debug.Log("文件路径为空或存在不支持的语言符号种类");
            }
        }

        // 从缓存文件夹下加载模型;
        if (judge_FileBuffer){
            String _tempFN = _ofn.fileTitle.Substring(0, _ofn.fileTitle.Length - 4);
            var _obj = Resources.Load<GameObject>("ModelsBuffer/" + _tempFN);
            if (_obj){
                var _objInstant = Instantiate(_obj);
                _objInstant.transform.localScale = Vector3.one * 30;
                _objInstant.transform.localPosition = new Vector3(10f, -11.7f, 174.7f);
            }
        }

        // 模型文件读取后转入数据库;
        if (judge_FileBuffer) {
            bool judge_Read = false;
            FileIO_OBJ _io = new FileIO_OBJ();
            judge_Read = _io.read_OBJ(_ofn.fileFull);
        }


    }

    // ------------------------------------------------ 保存模型;
    public void Click_SaveFileDialog()
    {
        Debug.Log("getIn Click_SaveFileDialog");

        FileNameStruct _sfn = new FileNameStruct();

        if (LocalDialog.GetSaveFileName(_sfn))
        {
           
        }
    }


}




// ------------------------------------------- win10 文件浏览器调用类 ------------------------------------------- //

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

//1.OpenFileName数据接收类:
public class FileNameStruct
{
    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 fileFull = 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;
}

//2.系统函数调用类:
public class LocalDialog
{
    //链接指定系统函数       打开文件对话框
    [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern bool GetOpenFileName([In, Out] FileNameStruct ofn);
    public static bool GetOFN([In, Out] FileNameStruct ofn) { return GetOpenFileName(ofn); }
    //链接指定系统函数        另存为对话框
    [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern bool GetSaveFileName([In, Out] FileNameStruct ofn);
    public static bool GetSFN([In, Out] FileNameStruct ofn) { return GetSaveFileName(ofn); }
}

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Unity中,有多种方法可以动态加载图片资源。其中一种常见的方法是使用Unity的Resources功能。通过将图片资源放置在项目的Resources文件夹中,可以使用Resources.Load()方法来加载资源。 另一种方法是使用Unity的AssetBundle功能。AssetBundle是一种将资源打包成独立文件的方式,可以通过WWW类或UnityWebRequest类来加载AssetBundle资源。这种方法可以加载任意路径下的资源,包括项目外的资源。 还可以使用Unity的AssetDatabase功能。AssetDatabase只能在Editor环境中使用,可以加载Assets目录下的资源。这种方法适用于开发过程中需要在Editor环境中加载资源的情况。 最后,还有一种方法是使用UnityWebRequest类,它是WWW类的升级版本。UnityWebRequest可以加载任意路径下的资源,包括项目外的资源。 以上是在Unity动态加载图片资源的几种常见方法。具体的使用方法和优缺点可以参考Unity的API文档。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Unity实现动态资源加载的4种方式](https://blog.csdn.net/qq_35711014/article/details/89891139)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值