当前位置: 首页 > ai >正文

unity脚本-FBX自动化模型面数校验

根据目前模型资源平均面数预算进行脚本制作,自动化校验模型面数是否符合规范。

*注:文件格式为.cs。需要放置在unity资源文件夹Assets>Editor下。

测试效果(拖一个fbx文件进unity时自动检测):

以下为完整代码

using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System;public class FBXFaceBudgetValidator : AssetPostprocessor
{// 配置:不同前缀对应的面数预算(不区分大小写)private static readonly Dictionary<string, int> FACE_BUDGETS = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase){{"hair_", 4000},{"hat_", 5000},{"headdress_", 5000},{"caps_", 5000},{"clothing_", 6500},{"shoe_", 2000},{"glasses_", 1000},{"mask_", 1500},{"glove_", 1000},{"necklace_", 1000},{"scarf_", 1000},{"bracelet_", 2500},{"waist_", 1000},{"satchel_", 1000},{"backpack_", 2500},{"wing_", 2500},{"cape_", 1000},{"earring_", 300},{"instrument_",3000}};// 配置:忽略校验的文件夹路径private static readonly string[] IGNORE_PATHS = { "Assets/Models/LowPoly" };void OnPostprocessModel(GameObject model){try{string assetPath = assetImporter.assetPath;//Debug.Log($"[校验器] 开始处理: {assetPath}");if (IsInIgnorePath(assetPath)){Debug.Log($"[校验器] 已忽略路径: {assetPath}");return;}string fileName = Path.GetFileNameWithoutExtension(assetPath);var sortedPrefixes = FACE_BUDGETS.Keys.OrderByDescending(p => p.Length);int maxTriangles = -1;string matchedPrefix = "";foreach (var prefix in sortedPrefixes){if (fileName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)){maxTriangles = FACE_BUDGETS[prefix];matchedPrefix = prefix;break;}}if (maxTriangles == -1){string error = $"<color=red>命名错误</color>: {fileName}\n允许的前缀列表:\n{string.Join("\n", FACE_BUDGETS.Keys)}";Debug.LogError(error, model);return;}int totalTriangles = CalculateTriangleCount(model);Debug.Log($"[校验器] 总面数合规: {totalTriangles}");if (totalTriangles > maxTriangles){string error = $"<color=red>面数超标</color>: {fileName} ({matchedPrefix})\n预算: {maxTriangles}, 实际: {totalTriangles}";Debug.LogError(error, model);}}catch (Exception ex){Debug.LogError($"[校验器] 发生异常: {ex}");}}private bool IsInIgnorePath(string assetPath){try{string fullAssetPath = Path.GetFullPath(assetPath).Replace('\\', '/').TrimEnd('/');foreach (var path in IGNORE_PATHS){string fullIgnorePath = Path.GetFullPath(path).Replace('\\', '/').TrimEnd('/') + "/";if (fullAssetPath.StartsWith(fullIgnorePath, StringComparison.OrdinalIgnoreCase)){return true;}}return false;}catch{return false;}}private int CalculateTriangleCount(GameObject model){int triangles = 0;try{foreach (var renderer in model.GetComponentsInChildren<Renderer>(true)){Mesh mesh = null;// 处理SkinnedMeshRendererif (renderer is SkinnedMeshRenderer skinnedRenderer){mesh = skinnedRenderer.sharedMesh;}// 处理普通MeshRendererelse if (renderer is MeshRenderer){var filter = renderer.GetComponent<MeshFilter>();if (filter != null){mesh = filter.sharedMesh;}}if (mesh != null && mesh.triangles != null){triangles += mesh.triangles.Length / 3;}}}catch (Exception ex){Debug.LogError($"[面数计算] 发生异常: {ex}");}return triangles;}
}

http://www.xdnf.cn/news/1021.html

相关文章:

  • vscode本地docker gdb调试python
  • UE5.2+VarjoXR3,Lumen、GI、Nanite无效的两种解决方案
  • SQLiteDatabase 增删改查(CRUD)详细操作
  • 企业微信私域运营,基于http协议实现SCRM+AI完整解决方案
  • autohue.js - 基于 JavaScript 开发的图片背景色提取开源库,能让图片和背景融为一体
  • gbase8s触发器使用
  • CentOS创建swap内存
  • 锂电池4.2V升压24V推荐哪些升压芯片?高效率国产SL4013输入耐压2.7V-25V
  • 黑马点评redis改 part 4
  • List findIntersection getUnion
  • 分别配置Github,Gitee的SSH链接
  • 扩散模型(Diffusion Models)
  • Linux-信号
  • 媒体关注:联易融聚焦AI+业务,重塑供应链金融生态
  • 【k8s】PV,PVC的回收策略——return、recycle、delete
  • 开源模型应用落地-Podcastfy-从文本到声音的智能跃迁-Docker(二)
  • CSS预处理器对比:Sass、Less与Stylus如何选择
  • 如何改电脑网络ip地址完整教程
  • Python常用的第三方模块之数据分析【pdfplumber库、Numpy库、Pandas库、Matplotlib库】
  • Docker 部署 Redis 缓存服务
  • 路由器转发规则设置方法步骤,内网服务器端口怎么让异地连接访问的实现
  • 一键配置多用户VNC远程桌面:自动化脚本详解
  • linux下使用wireshark捕捉snmp报文
  • 开源状态机引擎,在实战中可以放心使用
  • 15.QT-容器类控件|Group Box|Tab Widget|垂直布局|水平布局|网格布局|表单布局|Spacer(C++)
  • Idea 配置 Git
  • Uniapp:swiper(滑块视图容器)
  • 如何将Qt程序打包成应用程序?
  • 流程执行松散,如何强化规范?
  • 【Linux内核设计与实现】第三章——进程管理01