OBJ文件动态载入Unity中的一个算法小问题

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

FBX、OBJ等格式的3D文件,拖入Unity工程时,都经历了一个内部处理过程以转换成Unity能使用的格式。

通常游戏项目的模型文件都是作为静态资源打包进安装包的。但假设面临在程序运行时,灵活动态获取模型文件,并马上使用的需要,该怎么办呢?

Unity在这块并没有做很好的支持,不要和我说什么AssetBundle,那个也是要预先在Editor里手工处理好才能下载使用的。我是指直接丢过来一个OBJ,程序该如何解析?

 

基本的原理是:利用Unity Mesh类,准备好顶点、法线、面等信息数据,写入Mesh.vertices、Mesh.normals、Mesh.trangles等即可。

这方面有很多老外已经写好了示例工程,网上搜搜都能很容易获取。

(2018.9.12 补充说明:

鉴于经常有人在评论中询问具体的demo和代码,我把找到的参考资料链接贴于此。

OBJ文件格式详解

解析OBJ模型并将其加载到Unity3D场景中

Loading 3d models at runtime in Unity3d

GitHub Project unity-obj-loader

新发现的两个带代码的文章:

unity 加载obj文件的方法

Obj格式解析以及在Unity3D下导入测试

 

但以上不是这篇文章的重点。

 

故事开始在我下载到一个老外的工具工程后,研读了下他的代码,发现其存在两个内部缺陷:

1.对于顶点数超出65000个的情况,没有做很好的处理,仅仅是报错。

        而我要处理的模型有16万顶点,33万面。

2.直接将faces的vertices依次写入Mesh.vertices,然后trangles直接写成{1,2,3,4,5,6,......n}这样的顺序整形数组。

        熟悉3D渲染的应该都知道,模型的顶点索引是记录一份Vector3[],而面的表示只是用前面的顶点索引信息记录一份int[],节省内存空间。作者这种偷懒的解析法,造成了约6倍的重复顶点数,进一步对性能产生压力。

 

为了消除vertices中的重复数据,并重新映射trangles,我一开始写了这么一个算法:

 

List<Vector3> refinedVertexesList = new List<Vector3>();  //新顶点索引容器
List<Vector3> refinedNormalsList = new List<Vector3>();
List<int> trangles = new List<int>();
for (int j = 0; j < tvertices.Length; j++)
{
    if (!refinedVertexesList.Contains(tvertices[j]))
    {
        refinedVertexesList.Add(tvertices[j]);
        refinedNormalsList.Add(tnormals[j]);
        trangles.Add(refinedVertexesList.Count - 1);
    }
    else
    {
        trangles.Add(refinedVertexesList.IndexOf(tvertices[j]));
    }
}

 

大概的思想就是:

新建一个顶点索引列表,

遍历面队列中记录的每个顶点,

假如没加入新索引,就加入,然后修正面index,

假如已经加入了,就只是修正面index。

 

结果一运行,发现程序卡在那了,经测试,整个运算过程处理一个模型要十五分钟左右。。。

 

主要是List的Contains和IndexOf效率都极低,处理6万个顶点,一趟下来就是6万*6万=36亿的次数量级。

然后我试了各种其他容器,Dictionary的问题在于Add极慢,而HashSet虽然Add和Contains都快,但没法得到索引。

 

最后灵机一动,回归最原始的数组,然后就搞定了:

 

List<Vector3> refinedVertexesList = new List<Vector3>();  //新顶点索引容器
List<Vector3> refinedNormalsList = new List<Vector3>();
int[] trangles = new int[od.allFaces.Count];
{
    int[] vis = new int[vertices.Count];
    for (int k = 0; k < od.allFaces.Count; k++) //给总顶点索引中此object faces用到的vertexes做标记
    {
        vis[od.allFaces[k].vi] = 1;
    }

    int[] newVis = new int[vertices.Count];     //用于记录原index对应的新index
    for (int k = 0; k < vis.Length; k++)
    {
        if (vis[k] != 0)
        {
            refinedVertexesList.Add(vertices[k]);
            refinedNormalsList.Add(normals[k]);
            newVis[k] = refinedVertexesList.Count - 1;
        }
    }

    for (int k = 0; k < od.allFaces.Count; k++) //更新faces索引
    {
        trangles[k] = newVis[od.allFaces[k].vi];
    }
}

当然肯定有更刁钻的优化算法,但这个已经将耗时控制在0.1s以下,符合需求了。

 

原理是建立两个最大容量的数组,一个用于记录顶点是否被使用,一个用于记录新旧索引的映射关系。过程中得到新的一份顶点索引和面信息,就ok了。

如此用几十K的内存空间,换到十几分钟的CPU计算时间。

 

算法优化的本质,是操作元素的数量在2万-6万间变动,那么直接按6万的量来开辟空间,多费一点内存,省下了高速Contains()类容器的Add()时间。

所以没事乱用些不合适的容器,是个很傻的行为。

Unity核心8——模型导入 ​支持很多模型格式。比如 .fbx /.dae /.3ds /.dxf /.obj 等等。​ 99%的模型都不是在 Unity 中制作的,都是美术人员在建模软件中制作,如 3DMax、Maya 等等。​ 当他们制作完模型后,虽然 Unity 支持很多模型格式但是官方建议是将模型在建模软件中导出为 FBX 格式后再使用​ 在 Project 窗口选中导入的模型,在 Inspector 窗口进行相关设置,4 个页签分别是Model 模型页签Rig 操纵(骨骼)页签动画页签Materials 材质。 阅读详情

相关推荐

Unity实战(2):模型导入Unity

本文记录的是将模型导入Unity的方法,以SketchUp的模型为例

qq_41904236的博客 8128

unity3d动态加载本地模型

unity3d中在运行状态下动态加载本地模型,fbx,obj等格式都可以加载。可以直接运行。动态加载本地模型。

unity之——AssetBundle在安卓平台的打包与加载解析(超大一个坑!今天给填了)

最近一直在头疼一个问题,自己写的小Demo,利用AssetBundle动态加载的方式在安卓平台显示一个图片的预设。一直不成功的原因是:因为加载路径的问题,在安卓平台下加载不出来assetBundle对象。我是用的AssetBundle.LoadFromFile()的方法加载的,这个路径是AssetBundle.LoadFromFile(Application.dataPath+"!assets/t...

cgy56191948的博客 1万+

Unity动态导入OBJ

Unity动态导入OBJ,.....................................

解析OBJ模型并将其加载Unity3D场景中

各位朋友,大家好,欢迎大家关注我的博客,我是**秦元培**,我的博客地址是[http://qinyuanpei.com](http://qinyuanpei.com)。今天想和大家交流的是解析obj模型并将其加载Unity3D场景中,虽然我们知道Unity3D是可以直接导入OBJ模型的,可是有时候我们并不能保证我们目标客户知道如何使用Unity3D的这套制作流程,可能对方最终提供给我们的就是一个模型文件而已,所以这

素履独行 | 元培的个人博客 4万+

Unity3DUnity3D加载obj格式的模型

创建两个脚本 using UnityEngine; using System.Collections; using System.Collections.Generic; public class GeometryBuffer { private List<ObjectData> objects; public List<Vector3> vertices; public List<Vector2> uvs; public List<Vector3&

虚拟世界 3778

[Unity笔记]热更Part1:关于AB包与热更

对AssetBundle和热更新流程进行了介绍,同时将AA、AB与Resource进行了横向比对。

qq_39377889的博客 1864

Unity资产包逆向解析:UABEA工具核心功能与实战资源替换指南

在游戏开发与资源管理中,Asset Bundle(资产包)是实现资源动态加载、热更新与包体优化的核心技术。其本质是Unity引擎将纹理、模型、音频等资源按照特定序列化格式打包生成的二进制文件。理解资产包的内部结构与序列化原理,对于资源优化、Mod制作、问题调试及逆向工程分析具有重要价值。通过专用工具解析资产包的二进制格式,开发者可以查看、提取与修改其中的资源数据,从而实现对游戏或应用资源的深度定制与问题排查。UABEA(Unity Asset Bundle Extractor)正是这样一款专注于逆向解析Un

weixin_34236869的博客 507

Unity资源逆向实战:AssetStudio核心原理与Lua脚本反编译全解析

在游戏开发与安全研究领域,资源逆向工程是一项关键技术,它涉及对已打包应用的数据提取与解析。其核心原理在于理解资源的序列化格式与数据结构,通过逆向序列化过程将二进制数据还原为可读、可用的资源。这项技术的价值在于支持美术资源分析、逻辑研究、本地化修改与安全审计等多种场景。实践中,Unity引擎的资源管理基于复杂的序列化系统,而AssetStudio作为核心工具,能够解析Unity资源文件头、读取类型树并重建资源引用关系。对于游戏逻辑分析,特别是采用Lua进行热更新的手游,需要进一步处理Lua脚本资源。这包括定位

weixin_34224941的博客 338

Unity光照烘焙太慢?5个实用技巧帮你避免GPU内存爆满

本文针对Unity光照烘焙过程中常见的GPU内存溢出问题,提供了5个实用优化技巧。从显存分配原理到参数优化组合拳,再到场景分割烘焙和分布式烘焙实战配置,帮助开发者有效避免OpenCL错误,提升烘焙效率和质量。特别适合处理复杂场景的Unity开发者参考。

weixin_30872499的博客 463

OBJ动态导入

支持运行时导入OBJ格式文件,亲测可用,可放心下载使用

频繁Instantiate拖慢游戏?:3步教你打造超高效Unity对象池

解决频繁Instantiate导致的性能瓶颈,本文教你用Unity C# 对象池(Object Pool)实现高效对象复用。涵盖适用场景、预加载动态扩容策略,提升游戏运行效率。三步实操,简单易懂,值得收藏。

QuickProceed的博客 1191

Unity与Unreal Engine实战对比:从核心原理到项目选型指南

在游戏开发领域,引擎选型是决定项目成败的关键技术决策。组件化架构与可视化脚本是两大主流引擎的核心设计哲学,前者通过实体-组件系统实现高度模块化,后者通过节点连接降低逻辑开发门槛。这些原理直接影响开发效率、团队协作模式与最终产品性能。从技术价值看,引擎的开放程度、资源管线和工作流决定了项目的定制能力与迭代速度。在应用场景上,独立游戏、移动应用更看重快速原型与跨平台部署,而3A大作、高保真模拟则追求极致图形与深度优化。本文聚焦Unity与Unreal Engine的实战对比,通过分析UGUI+DOTween等热

weixin_34343000的博客 501

Blender与Unity无缝集成:5个核心技巧构建高效3D资产管线

在3D内容创作与游戏开发领域,数据交换与工作流整合是提升生产效率的关键环节。FBX作为行业标准的中间格式,其核心原理在于封装网格、材质、动画等资产数据,实现不同软件间的互操作。精准的数据映射与转换技术,能够确保PBR材质、骨骼动画等复杂资产在跨平台引擎中原汁原味地呈现,这对于构建稳定、可迭代的生产管线具有重要价值。尤其在独立游戏开发、实时可视化等应用场景中,一套健壮的Blender到Unity资产管道,能有效解决模型导入后的材质丢失、法线错误、动画数据错位等常见问题,让开发者从繁琐的调试中解放,更专注于核心

weixin_34128237的博客 398

倾斜摄影与Unity3D数字孪生实战:五步流程与点云避坑指南

数字孪生作为连接物理世界与数字空间的关键技术,其核心在于通过数据驱动实现虚实映射与交互。其技术原理通常涉及三维重建、实时渲染与数据融合,旨在构建一个可感知、可分析、可预测的数字副本。在工程实践中,倾斜摄影建模因其高效率与高真实度,成为大范围实景三维重建的主流方案,而Unity3D引擎凭借其强大的实时渲染与交互开发能力,为数字孪生注入了可操作的“灵魂”。面对海量点云数据导入、模型优化与性能调优等挑战,掌握从数据采集、格式转换到核心功能开发的全流程至关重要。本文聚焦于倾斜摄影与Unity3D的结合,深入探讨点云

weixin_34347651的博客 313

Unity3D中倾斜摄影OSGB模型的第一人称漫游实现方案

倾斜摄影三维建模技术通过无人机多角度拍摄生成高真实度、高细节的三维模型,广泛应用于智慧城市、数字孪生和仿真训练等领域。其核心原理是将真实世界影像转化为由海量三角面片构成的网格模型。然而,这类模型面数极高且缺乏标准游戏场景的结构化碰撞信息,直接用于交互式应用面临性能与物理交互的双重挑战。在游戏开发与三维可视化工程中,第一人称漫游是提供沉浸式体验的关键技术,它依赖于物理引擎的碰撞检测来实现角色的移动与空间感知。本文聚焦于将倾斜摄影模型与Unity引擎的FPSController控制器进行深度适配,通过数据格式转

weixin_33933118的博客 397

Assetbundle2

Assetbundle可以将Prefab封装起来,这是多么方便啊! 而且我也强烈建议大家将Prefab封装成Assetbundle,因为Prefab可以将游戏对象身上带的游戏游戏组件、游戏脚本、材质都封装在一起。当从服务器上将Assetbundle下载以后直接Instantiate就可以放入游戏中。 无论是模型资源还是UI资源,最好是先把他们放在Prefab中,然后在做成Assetbundle ...

weixin_30498807的博客 91

AI驱动2D转3D:PSAI插件实战,零基础快速生成3D模型

3D建模是数字内容创作的核心技术,传统流程依赖专业软件与复杂操作,门槛较高。其原理是通过构建三维网格、UV展开与贴图映射来表现立体对象。随着AIGC技术的发展,AI驱动的2D转3D工具正大幅降低创作门槛,通过深度图估计与三维重建算法,自动从单张图像推断几何结构,生成基础模型与贴图。这类技术的核心价值在于为原型设计、快速可视化及轻度应用场景提供高效解决方案,尤其适合独立开发者、插画师及内容创作者快速验证创意。本文以PSAI插件为例,结合实战流程,解析如何利用此类工具将2D表情包转化为可用3D资产,并探讨其作为

weixin_33836874的博客 381

UE5与FaceGen:从单张照片快速创建可动画3D数字人全流程

3D角色建模与动画是数字内容创作的核心技术之一,其原理在于通过计算机图形学将二维概念转化为具有体积、材质和运动能力的三维实体。这项技术的价值在于极大地扩展了虚拟内容的表现力与交互性,被广泛应用于游戏开发、影视制作、虚拟现实和数字孪生等领域。传统高精度建模流程耗时费力,而基于照片的快速生成方案正成为行业热点。本文聚焦于利用Unreal Engine 5的实时渲染与动画生态,结合FaceGen Modeller的**参数化人脸生成**能力,构建一套高效的本地化数字人生产管线。该流程从标准照片输入开始,通过算法

weixin_33859844的博客 361
上一篇: 每多变幻
犀利叔蓝波
博客等级 码龄16年 46粉丝 84原创
评论 16
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值