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

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;}
}

相关文章:

  • c语言数据结构------------归并排序(终)
  • Jenkins的地位和作用
  • 《AI大模型应知应会100篇》第32篇:大模型与医疗健康:辅助诊断的可能性与风险
  • 【人脸识别】百度人脸识别H5方案对接
  • Spring AOP + Logback + MDC全链路日志追踪
  • Cesium学习笔记——坐标系统及坐标转换
  • 实用生活c语言脚本
  • Android如何通过aspectj打造一个无侵入式动态权限申请框架
  • webpack基础使用了解(入口、出口、插件、加载器、优化、别名、打包模式、环境变量、代码分割等)
  • IDEA创建Gradle项目然后删除报错解决方法
  • 调整IntelliJ IDEA中当前文件所在目录的显示位置
  • [原创](现代Delphi 12指南):[macOS 64bit App开发]:在Mac App Store外创建、部署与公证
  • CoinNexus Chain 推出泰利风暴,开启 Web3.0 智能金融元宇宙科技新时代
  • Lua 第8部分 补充知识
  • webrtc使用
  • 自然语言处理 | 语言模型(LM) 浅析
  • 【MCP Node.js SDK 全栈进阶指南】中级篇(2):MCP身份验证与授权实践
  • AI数字人:品牌营销的新宠与增长密码(6/10)
  • 【Linux】计算机基本知识补充
  • 使用PyTorch构建神经网络笔记
  • 山东省检察院答澎湃:惩治网络售假,强化“全链条”刑事打击
  • 涡虫首上太空,神舟二十号任务将开展3项生命科学实验
  • 经济日报:锚定重点领域和关键环节,上海浦东谋划高水平对外开放
  • 被指违反代理协议遭南航暂停售票资格,去哪儿网:今起恢复
  • 南部战区回应菲护卫艇非法侵入中国黄岩岛领海:依法警告驱离
  • 运油-20亮相中埃空军联训