文章目录

  • Unity 没有内置的人物角色 LOD 管理
  • 可以自己写脚本按距离来控制
  • 扩展、及其问题
  • References

Unity 没有内置的人物角色 LOD 管理

参考了 Unity 论坛上的某个帖子:Level of Detail management (LOD)

虽然 Unity 没有内置的角色 LOD 管理

但是我们可以自己根据距离来切换网格


可以自己写脚本按距离来控制

直接参考:https://pastebin.com/clone/K1S4Zjh0

using UnityEngine;
using System;
using System.Collections.Generic;//[ExecuteInEditMode]
public class CharacterLOD : MonoBehaviour
{public Mesh LOD0;public Mesh LOD1;public Mesh LOD2;public Mesh LOD3;public List<Material> LOD_0_Materials;public List<Material> LOD_1_Materials;public List<Material> LOD_2_Materials;public List<Material> LOD_3_Materials;public float lod0Dist = 10f;public float lod1Dist = 20f;public float lod2Dist = 30f;public float lod3Dist = 50f;public float lodTimer = 0.3f;public Camera camera1;private bool foundCamera;public int currLOD;private float currTimer;public void Start(){GetCamera();currLOD = 0;}void Update(){if (foundCamera == false)GetCamera();//Update LODs TimercurrTimer -= Time.deltaTime;if (currTimer <= 0.0f){UpdateMeshLOD();currTimer = lodTimer; //Reset Timer}}public void UpdateMeshLOD(){if (camera1 == null) return;Vector3 camPos1 = camera1.transform.position;if ((transform.position - camPos1).sqrMagnitude < (lod0Dist * QualitySettings.lodBias) * (lod0Dist * QualitySettings.lodBias)) //LOD 0{if (currLOD != 0){SetLowestLODMesh(QualitySettings.maximumLODLevel);SetLODMaterials(QualitySettings.maximumLODLevel);currLOD = 0;return;}}else if ((transform.position - camPos1).sqrMagnitude < (lod1Dist * QualitySettings.lodBias) * (lod1Dist * QualitySettings.lodBias)) //LOD 1{if (currLOD != 1){SetLowestLODMesh(QualitySettings.maximumLODLevel + 1);SetLODMaterials(GetLowestLODMats(QualitySettings.maximumLODLevel + 1));currLOD = 1;return;}}else if ((transform.position - camPos1).sqrMagnitude < (lod2Dist * QualitySettings.lodBias) * (lod2Dist * QualitySettings.lodBias)) //LOD 2{if (currLOD != 2){SetLowestLODMesh(QualitySettings.maximumLODLevel + 2);SetLODMaterials(GetLowestLODMats(QualitySettings.maximumLODLevel + 2));currLOD = 2;return;}}else if ((transform.position - camPos1).sqrMagnitude < (lod3Dist * QualitySettings.lodBias) * (lod3Dist * QualitySettings.lodBias)) //LOD 3{if (currLOD != 3){SetLowestLODMesh(QualitySettings.maximumLODLevel + 3);SetLODMaterials(GetLowestLODMats(QualitySettings.maximumLODLevel + 3));currLOD = 3;return;}}}public void SetLODMaterials(int lod){Material[] currMats;bool wasSuccess = false;switch (lod){case 0: //LOD 0if (LOD_0_Materials.Count > 0){int existingMatsCount = 0;currMats = new Material[LOD_0_Materials.Count];for (var x = 0; x < LOD_0_Materials.Count; x++){currMats[x] = LOD_0_Materials[x];if (LOD_0_Materials[x] != null)existingMatsCount++;}if (existingMatsCount / LOD_0_Materials.Count > 0.5f) //Atleast 50% of materials exist{GetComponent<Renderer>().sharedMaterials = currMats;wasSuccess = true;} }break;case 1:if (LOD_1_Materials.Count > 0){int existingMatsCount = 0;currMats = new Material[LOD_1_Materials.Count];for (var x = 0; x < LOD_1_Materials.Count; x++){currMats[x] = LOD_1_Materials[x];if (LOD_1_Materials[x] != null)existingMatsCount++;}if (existingMatsCount / LOD_1_Materials.Count > 0.5f) //Atleast 50% of materials exist{GetComponent<Renderer>().sharedMaterials = currMats;wasSuccess = true;}}break;case 2:if (LOD_2_Materials.Count > 0){int existingMatsCount = 0;currMats = new Material[LOD_2_Materials.Count];for (var x = 0; x < LOD_2_Materials.Count; x++){currMats[x] = LOD_2_Materials[x];if (LOD_2_Materials[x] != null)existingMatsCount++;}if (existingMatsCount / LOD_2_Materials.Count > 0.5f) //Atleast 50% of materials exist{GetComponent<Renderer>().sharedMaterials = currMats;wasSuccess = true;}}break;case 3:if (LOD_3_Materials.Count > 0){int existingMatsCount = 0;currMats = new Material[LOD_3_Materials.Count];for (var x = 0; x < LOD_3_Materials.Count; x++){currMats[x] = LOD_3_Materials[x];if (LOD_3_Materials[x] != null)existingMatsCount++;}if (existingMatsCount / LOD_3_Materials.Count > 0.5f) //Atleast 50% of materials exist{GetComponent<Renderer>().sharedMaterials = currMats;wasSuccess = true;}}break;}if (wasSuccess)Debug.Log("[CharacterLOD] " + this.transform.root.name + " Swapped LOD Mats to: " + lod);}public int GetLowestLODMats(int desired){if (desired >= 3){if (LOD_3_Materials.Count > 0)return 3;if (LOD_2_Materials.Count > 0)return 2;if (LOD_1_Materials.Count > 0)return 1;if (LOD_0_Materials.Count > 0)return 0;}if (desired == 2){if (LOD_2_Materials.Count > 0)return 2;if (LOD_1_Materials.Count > 0)return 1;if (LOD_0_Materials.Count > 0)return 0;}if (desired == 1){if (LOD_1_Materials.Count > 0)return 1;if (LOD_0_Materials.Count > 0)return 0;}if (desired == 0){if (LOD_0_Materials.Count > 0)return 0;}return 0;}public void SetLowestLODMesh(int desired){SkinnedMeshRenderer mf1 = GetComponent<SkinnedMeshRenderer>();if (desired >= 3){if (LOD3 != null)mf1.sharedMesh = LOD3;if (LOD2 != null)mf1.sharedMesh = LOD2;if (LOD1 != null)mf1.sharedMesh = LOD1;if (LOD0 != null)mf1.sharedMesh = LOD0;}if (desired == 2){if (LOD2 != null)mf1.sharedMesh = LOD2;if (LOD1 != null)mf1.sharedMesh = LOD1;if (LOD0 != null)mf1.sharedMesh = LOD0;}if (desired == 1){if (LOD1 != null)mf1.sharedMesh = LOD1;if (LOD0 != null)mf1.sharedMesh = LOD0;}if (desired == 0)if (LOD0 != null)mf1.sharedMesh = LOD0;}public void GetCamera(){try{camera1 = Camera.main;foundCamera = true;}catch (Exception e){Debug.Log("[CharacterLOD] Couldn't find Main Camera: " + e.Message);}}
}

扩展、及其问题

上面按距离的方式来处理的话会有一些问题

比如说再 FPS 游戏中就不太好用

因为游戏会有倍镜

而倍镜一般时调整 FOV 来处理的

再使用 LODGroup 中处理的时按屏幕高度比例来处理的话,这种制作时没有问题的

但时 LODGROUP 的方式不设置对 SkinnedMeshRenderer 做处理

因为 SkinnedMeshRenderer 内部有动画信息的状态

所以只能写脚本切换 Mesh 即可,动画骨骼信息不要动他就可以了

然后配上 自己按 FOV 的数值来换算一下,让 FOV 不同大小下也可以比较正常的显示 SknnedMeshRnederer 的 LOD


还有另一个问题,以上这些方式都不能切换骨骼结构

因为如果一个模型骨骼结构很复杂,也时消耗比较大的

但是理论上,我们可以再写一个:再切换 LOD时,可以将前一个LOD的 Animator 状态和 AnimationClip.playTime 同步一下到当前的 LOD 即可,但是不保证会不会抖动,得看 API 得封装够不够好


References

  • Creating LOD Group for character
  • Level of Detail management (LOD)
  • Unity自动生成LOD,人形角色LOD的使用解决动画播放问题 - 这种方式不太好,人物LOD切换时还有动作抖动,但是里面的 LOD 模型生成插件可以使用

Unity - 人物对象的 LOD 管理相关推荐

  1. Unity中对象池的使用

    unity中用到大量重复的物体,例如发射的子弹,可以引入对象池来管理,优化内存. 对象池使用的基本思路是: 将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用.恰当地使用对象池,可以在 ...

  2. 给Unity开发者的C#内存管理(第一部分) C# Memory Management for Unity Developers (part 1 of 3)

    原文地址:http://www.gamasutra.com/blogs/WendelinReich/20131109/203841/C_Memory_Management_for_Unity_Deve ...

  3. 容器,对象生命周期管理的基石

    2019独角兽企业重金招聘Python工程师标准>>> 郑重申明:包括本文在内的很多技术文章,大多出自山外高人,而非Fans. Fans暂时没有能力写作优秀的技术文章,Fans只是转 ...

  4. Unity的对象复用

    2019独角兽企业重金招聘Python工程师标准>>> 对象复用是 用空间换时间的一种典型的做法,对于Unity来说虽然引擎内部有GameObject的对象池,但是 这只是Nativ ...

  5. UNITY 复制对象后局部坐标和世界坐标的变化问题

    UNITY 复制对象后局部坐标和世界坐标的变化问题 void Start () { var pgo = transform.Find ("Button").gameObject; ...

  6. SSH学习-Hibernate对象生命周期管理

    Hibernate对象就是java中的实体对象,管理就是在实体对象的生命周期内被Hibernate的操作,Hibernate对象的生命周期其实就是实体对象的生命周期(从创建到最后被GC回收),期间对实 ...

  7. MinIO对象生命周期管理解析

    目录 前言 对象过期 远程存储层(Tiers)常用分层场景 跨存储介质 跨云类型 公有云 文件迁移实例 Tiers配置 生成周期管理配置 原始桶的tiertest前缀的文件目录 远程存储层目录结构 原 ...

  8. Unity摄像机对象锁定旋转运镜模拟

    问题简述 在3D模式下如何模拟实现Unity摄像机对象锁定旋转运镜,可以分为两个部分,第一是实现对象锁定,第二是实现旋转运镜.对象锁定就是无论摄像机如何运动,始终保持对象位于摄像机成像区域的固定位置, ...

  9. unity人物基础动画应用。行走、待机之类的简单动画切换。

    @[TOC]unity人物基础动画应用 1.将动画或带有动画的,模型导入到unity 直接将项目拖入资源层级就好.这里推荐一个网站,可以给导入网站的模型自动绑骨,并且可挑选动画下载.网站自身也带有很多 ...

最新文章

  1. 信息熵是什么 转 理论吃透的创新解释
  2. html概述和基本结构
  3. [云炬python3玩转机器学习] 6-4 在线性回归模型中使用梯度下降法
  4. js如何获取计算机当前时间,js获取当前系统时间
  5. python selenium自动化面试_18年selenium3+python3+unittest自动化测试教程(上)
  6. canal 入门(1)
  7. 结合nginx源码学习error_page和proxy 指令的关系
  8. Effective_STL 学习笔记(四十五) 注意 count、find、binary_search、lower_bound、upper_bound 和 equal_range 的区别...
  9. simulink仿真实例_推荐几本关于制冷仿真的书籍(制冷仿真必备)
  10. SSM项目实战之二十五:新增订单
  11. 万豪集团发布《重塑餐饮业:行业洞察》报告,分享十大新兴趋势
  12. java接口推送_推送API
  13. 周鸿祎:江湖最后一个大佬
  14. java统计字数_JAVA 仿 MS word 字数统计
  15. outlook查看图片错位异常问题
  16. python爬 歌曲 视频
  17. java 获取jtextfield_如何获取JTextField中的字符数? - java
  18. 运放电路中电容的一些特殊用法
  19. 常见的Android数据传递方法汇总
  20. 【matlab】./和/ .*和* 有什么区别

热门文章

  1. 用C++编写一个简易数学计算器
  2. 茫茫沧海,你终成了我无法逾越的泅渡
  3. 百度收购快钱?消息人士说不大可能
  4. 康定游记-宝宝征服4300米海拔折多山
  5. md5update java_JAVA实现MD5算法
  6. 你用过的每款APP都具有这一特点,但你却不知道……
  7. 达人评测 红米K30s至尊纪念版和iQOO Neo5活力版
  8. Kotlin快速运用第四阶段(集合相关框架)
  9. 微信朋友圈图片显示缩放
  10. 计算机应用基础(专)【7】