# VRChat Avatar 究極輕量化、最佳化筆記

VRChat Avatar 究極輕量化、最佳化筆記 (支援 Modular Avatar)
===
---
:::success
:bulb: **懶人包**
複製 (Duplicate) Avatar 身上的三樣東西：
* FX Layer
* Expression Menu
* Expression Parameter

刪掉所有跟開關物件相關的設定。(能保留表情相關的 Blend Shape 設定)

然後複製 Avatar 本身

導入 [anatawa12 AvatarOptimizer (AAO)](#anatawa12-AvatarOptimizer-AAO) 跟 [lilNDMFMeshSimplifier](#lilNDMFMeshSimplifier)
先做 [AAO Trace And Optimize](#總之先來一發全自動吧！AAO-Trace-And-Optimize)，面數還是太多的話，就看 [Remove Mesh By BlendShape](#Remove-Mesh-By-BlendShape) 跟 [Meshia Cascading Avatar Mesh Simplifier](#meshia2) 或**脫掉**。

把剛剛複製出來，並刪完的 FX、參數、選單塞回複製出來的 Avatar，完工。

想追求更好？[把它看完。](#目錄)
:::

每次跟別人對到眼，常聽到電腦好卡的哀號？
參加大型活動，有時因為 Very Poor 被主辦請出去？
串個門子，經常被嗆會走路的衣櫃 or 地圖？
別人看到你，預設居然是 Imposter？
想輕量化 / 最佳化，但怕手殘動到原始檔案？
想看外國的教學，但看外語好痛苦？
### **你來對地方了**
###
本教學會盡量說明最佳化、輕量化所需要的工具以及方法。
以脫離 Very Poor 或更好為目標，一起幫自己的 Avatar 瘦身吧！

> [!Note]附註
> 如果有新資訊，也會逐步更新上來！

這是證明我沒唬爛的附圖 (身體是面數較多的 Chiffon 哦！)
![proof](https://hackmd.io/_uploads/B1kPoHmQyl.png)



## 目錄
* [前言](#前言)
* [本篇介紹的工具](#本篇介紹的工具)
    * [Modular Avatar (MA)](#Modular-Avatar-MA)
    * [anatawa12 AvatarOptimizer (AAO)](#anatawa12-AvatarOptimizer-AAO)
    * [Mantis LOD Editor - Professional Edition](#Mantis-LOD-Editor---Professional-Edition)
    * [Mantis LOD Editor NDMF 化工具](#Mantis-LOD-Editor-NDMF-化工具)
    * [Meshia Cascading Avatar Mesh Simplifier](#Meshia-Cascading-Avatar-Mesh-Simplifier)
    * [lilNDMFMeshSimplifier](#lilNDMFMeshSimplifier)
    * [lilAvatarUtils](#lilAvatarUtils)
    * [TexTransTool](#TexTransTool)
    * [Avatar 批次上傳](#Avatar-批次上傳)
* [事前準備](#事前準備)
    * [VCC 導入 Package](#VCC-導入-Package)
    * [啟用 Actual Perfrmance 視窗](#啟用-Actual-Performance-視窗)
    * [顯示 AvatarUtils 視窗](#顯示-AvatarUtils-視窗)
* [開搞！](#開搞！)
    * [總之先來一發全自動吧！](#總之先來一發全自動吧！AAO-Trace-And-Optimize)
    * [Light (光源)](#Light-光源)
    * [Particle System (粒子系統)](#Particle-System-粒子系統)
    * [Texture Memory (材質記憶體使用量)](#Texture-Memory-材質記憶體使用量)
    * [Skinned Mesh Renderer (蒙皮網格)](#Skinned-Mesh-Renderer-蒙皮網格)
    * [Material Slots (材質欄位)](#Material-Slots-材質欄位)
    * [PhysBones (動骨)](#PhysBones)
        * [PhysBone Component (元件)](#PhysBone-元件數)
        * [PhysBone Transforms (影響骨頭數)](#PhysBone-影響骨頭數)
        * [PhysBone Collider (碰撞體數)](#PhysBone-碰撞體數)
        * [PhysBone Collosion Checks (碰撞偵測數)](#Physbone-碰撞偵測數)
    * [骨頭 (Bones)](#Bones-骨頭)
    * [Polygons (面數)](#Polygons-面數)
        * [Remove Mesh By BlendShape (使用 Blend Shape 移除面數)](#Remove-Mesh-By-BlendShape)
        * [Remove Mesh By Mask (遮罩貼圖移除面數)](#Remove-Mesh-By-Mask)
        * [Remove Mesh By Box (移除方塊內的面數)](#Remove-Mesh-By-Box)
        * [Remove Mesh By UV Tile (使用 UV Tile 移除面數)](#Remove-Mesh-By-UV-Tile)
        * [Mantis LOD Editor NDMF 化工具](#mantis2)
        * [lilNDMFMeshSimplifier](#lilmesh2)
        * [Meshia Cascading Avatar Mesh Simplifier](#meshia2)
    * [批次上傳 Avatar](#批次上傳-Avatar)
* [結語](#結語)
    

## 前言
通常一隻 Avatar 身上，只要穿了兩套以上可開關衣服，就跑不掉 Very Poor 了。
當然，如果你有能力在不 Very Poor 的前提下穿兩套以上的衣服，也是給你拍拍手啦 XDD

以自己經驗，簡單列出我最常看到 Avatar 會 Very Poor 的問題
1. 多到讓 CPU 吃不消的 Skinned Mesh Renderer (蒙皮網格)
2. ~~可以填滿一座泳池~~的材質球 (Material)
4. 走在路上都能踢到的 PhysBones 元件
5. 讓 3D 龍看了直搖頭的面數 (Polygon)
6. 非常「肥美」的貼圖 (Texture)

這些問題其實在 Unity 內就能解決，你不需要會 Blender。
順帶一提，這篇要介紹的幾乎都是 NDMF (Non-Destructive Modular Framework) 體系的工具，最佳化的同時，不會破壞到原始檔案，而且支援用 Modular Avatar (MA) 穿的衣服！要輕量化 / 最佳化並不困難哦！

:::info
:bulb: **冷知識**
最佳化跟輕量化的差異。雖然目的接近。
最佳化是以不影響功能、外觀的前提下，降低電腦負擔。
輕量化則是會稍微犧牲一些功能與外觀，但也能降低電腦負擔。
英文好像都是用 Optimize = 最佳化 = 輕量化 = 優化就是。
(輕量化應該是從日語延伸過來的...？)
:::
附上目前 VRChat 官方的 Performance Rank 標準
> [!Important]重要
> 以下是我已知比較容易超標的數字。
> 詳細資訊請參閱[官方網頁](https://creators.vrchat.com/avatars/avatar-performance-ranking-system/#pc-limits)

| 效能排行 | Excellent | Good | Medium | Poor
| -------- | -------- | -------- | -------- | -------- |
| 面數    | 32,000     | 70,000     |70,000     |70,000  |
|材質記憶體 | 40MB | 75MB | 110MB |150 MB|
|Skinned Mesh | 1 | 2 | 8 | 16 |
| 材質球 | 4 | 8 | 16 | 32 |
| PhsyBone (PB) | 4 | 8 | 16 | 32 |
| PB 影響骨頭數 | 16 | 64 | 128 | 256 |
| PB 碰撞器 | 4 | 8 | 16 | 32 |
| 碰撞檢查數 | 32 | 128 | 256 | 512 |
| 骨頭數 | 75 | 150 | 256 | 400 |
| 光源 | 0 | 0 | 0 | 1 |
| 粒子系統 | 0 | 4 | 8 | 16 |
| 粒子總數量 | 0 | 300 | 1,000 | 2,500 |
| 粒子系統面數使用總量 | 0 |1,000 | 2,000 | 5,000 |
| 粒子系統軌跡 | 停用 | 停用 | 啟用 |啟用 |
| 粒子系統碰撞 | 停用 | 停用 | 啟用 |啟用 |

:::warning
💪 **給挑戰者們**
[Quest 版 Avatar 的規範](https://creators.vrchat.com/avatars/avatar-performance-ranking-system/#mobile-limits)可說是硬到呼天搶地。
只要 Very Poor 會強制不顯示。
如果你能挑戰成功 (至少 Poor)，就代表 PC 模絕對難不倒你！
再一張證明我沒唬爛。這隻 Rusk 是從 PC 模改過來的！
![quest_avatar](https://images.plurk.com/5QVtFDPf5ZR02ywEkt1ba2.png)
:::
LET'S GO!!!\!!!!\!!!!\!!!!\!!!! ~~(Unwelcome School.mp3)~~

## 本篇介紹的工具
工欲善其事，必先利其器。
以下是我們需要使用的 VCC Repo 跟 Package。
只需要做一次導入，以後打開 Unity 就可以用囉。

*透過 VCC 導入的話我是建議常常更新啦 XD*

> [!Important]重要
以下每個工具的標題，都會連結到該工具的網頁，可查閱詳細內容。

---
### [Modular Avatar (MA)](https://modular-avatar.nadena.dev/)
由 bd_ 寫出的知名工具。
本篇文章有些工具是依賴 MA 運作的，所以請先安裝。
:::info
💡**與 VRCFury 共存 (進階者向)**
由於 Fury 跟 MA 互相不知道對方做了甚麼，導致經常發生錯誤。
這邊[參考きくじん的文章](https://note.com/kikjin/n/naee552e57a45#132ca880-dc0f-4ec6-87fa-ec35718a6060)，整理了防止出錯的方法
⚠️<font color=Orange>自己沒實測過，如果出問題，或知道正確答案請告訴我</font>⚠️
請讓工具保持以下的執行順序：
1. MA 和其他新增內容的 NDMF 系工具 (我猜 Mantis 跟 MeshSimplifier 也應該放在這裡，因為是處理尚未整合的物件本身)
2. Fury
3. 所有 NDMF 系最佳化工具 (也就是本篇其他介紹的所有東西，整合、刪除系工具等等)
 
思路上，需要完全理解 MA 跟 Fury 各自做了甚麼事情，
避免讓他們處理同一個區塊。否則一定會出錯。
:::
[VCC 導入用連結](vcc://vpm/addRepo?url=https://vpm.nadena.dev/vpm.json)

---
### [anatawa12 AvatarOptimizer (AAO)](https://booth.pm/ja/items/4885109)
這是由 anatawa12 製作的最佳化工具包。
我在最佳化 Avatar 的愛將，大部分的最佳化都可以在這裡完成。

==這個工具包的更新頻率很高，如果有新功能我卻沒提到，請告訴我。==

[VCC 導入用連結](https://vpm.anatawa12.com/add-repo)

---
### [Mantis LOD Editor - Professional Edition](https://assetstore.unity.com/packages/tools/modeling/mantis-lod-editor-professional-edition-37086)
負責減少 Polygon 的工具。
是我認為所有減面數工具中，品質比較好的工具。
++==是這篇文章中唯一的付費工具，原價 50 美金。==++
但好像還蠻常特價的，手頭不夠充裕的話，可以蹲一下。
底下也有不錯的替代方案，可多方參考。

*嗯？你說你會 Blender？去看其他章節！*

這是在 Unity 商店販售的 Package，透過 Unity 內建的 Package Manager 就可以導入囉。

---
### [Mantis LOD Editor NDMF 化工具](https://booth.pm/ja/items/5409262)
由於上述的工具並不在 NDMF 體系內，甚至不存在於 VRChat 體系內 (SDK 會擋)，ひつぶ便寫出了這個工具，把 Mantis LOD Editor 改成 NDMF 體系。

本工具無法透過 VCC 安裝，請透過上方連結進入 Booth 下載、導入 Unity 中。

---
### [Meshia Cascading Avatar Mesh Simplifier](https://ramtype0.booth.pm/items/6944218)
我們不做資本主義的奴隸！免費的在這！
這是由 Ram.Type-0 所開發，可以一口氣調整 Avatar 內所有 Polygon 的殺手級工具。
大推

[VCC 導入用連結](vcc://vpm/addRepo?url=https%3A%2F%2Framtype0.github.io%2FVpmRepository%2Findex.json)

---
### [lilNDMFMeshSimplifier](https://github.com/lilxyzw/lilNDMFMeshSimplifier)
Another free one!
這是由 lil 所製作，很輕鬆就能減少 Polygon 的工具。

[VCC 導入用連結](https://lilxyzw.github.io/vpm-repos/redirect.html)

---
### [lilAvatarUtils](https://github.com/lilxyzw/lilAvatarUtils)
也是由 lil 所製作的工具包，可以檢查 Avatar 的貼圖、材質球、動畫、Skinned Mesh、PhysBones、PhysBone 碰撞器、光照等等數值。
可以很輕鬆地抓到吃效能的兇手，編譯前 / 後的數值都可以檢查。

這個工具包含在 lil 的 Repo 內，跟著上面的 Repo 一起導入 Package 即可。

---
### [TexTransTool](https://ttt.rs64.net/)
由 Reina_Sakiria 製作的合併材質球工具，只要材質球的 Shader 性質相似，可以很自然地合併這些貼圖 (Atlas 化)。某些情況，材質球數量甚至能壓到只剩 1 顆！

[VCC 導入用連結](vcc://vpm/addRepo?url=https%3A%2F%2Fvpm.rs64.net%2Fvpm.json)

---
### [Avatar 批次上傳](https://github.com/anatawa12/ContinuousAvatarUploader)
最佳化的首要條件，就是不能用 Avatar 當大衣櫃。
如果你的衣服很多，勢必得分成很多 Avatar 個別上傳。
但撰寫文章當下，VRChat SDK 還沒有批次上傳 Avatar 的功能，
如果有東西變更 / 更新到所有 Avatar，一隻一隻重新上傳八成會傳到懷疑人生。
*例如我的 Avatar 已經將近 50 隻...*

這個工具也是由 AAO 作者，anatawa12 所編寫的批次上傳工具。
可以透過製作不同的 Asset，設定要批次上傳的 Avatar 群組。
某種意義上也是一種大衣櫃，只是做在 Unity 內。
VRChat 中還是可以自由取用不同衣服的 Avatar！

這個工具包含在 [AAO](#anatawa12-AvatarOptimizer-AAO) 的 Repo 內，跟著該 Repo 一起導入 Package 即可。

> [!Important]小小呼籲
這個功能其實應該要 SDK 原生才對，[所以請大家一起用力敲碗官方](https://feedback.vrchat.com/feature-requests/p/add-bulk-or-batch-avatar-upload-option-to-sdk)。
另一個敲碗的功能是，[在 VRChat 內用資料夾管理自己上傳的 Avatar](https://feedback.vrchat.com/feature-requests/p/folders-for-uploaded-avatars)←發文者就是 anatawa12 本人。
後者功能官方已經開始追蹤，成功的話，你各位大衣櫃的最後一片拼圖就完成啦！


## 事前準備
### VCC 導入 Package
有些新手可能不熟 VCC 的架構，安全起見還是說一下。
剛從 VCC 導入的 Repo 預設會停用，
請到 `Settings > Packages` 啟用上述的所有 Repo
這麼一來才能在 Project 管理頁面中找到需要用的 Package。

以下是你需要導入的 Package：
* AAO: Avatar Optimizer
* anatawa12's gists pack
* Continuous Avatar Uploader
* lilAvatarUtils
* lilNDMFMeshSimplifier
* Meshia Mesh Simplification
* Modular Avatar
* Non-Destructive Modular Framework
* TexTransTool

---
### 啟用 Actual Performance 視窗
Actual Perfrmance 視窗可以觀看經過編譯後的效能。
由於 NDMF 是非破壞型最佳化，VRChat SDK 只會顯示編譯前的樣子 (通常是 Very Poor)，所以得靠這個視窗去看編譯後的真實效能，最後上傳到 VRChat 的 Avatar 也會是這個狀態。
1. 功能列 `Tools > anatawa12's gist selector`
2. 勾選 `ActualPerformanceWindow` 後，點選下方的 `Apply Changes`
![gist_selector](https://hackmd.io/_uploads/B1gFjuQmye.png)
3. 檢查功能列 `Tools > anatawa12's gist`，`Compute actual Performance on Play` 有勾起來。只要進入 Play-mode，這個工具就會顯示經過編譯後的真實效能狀態 (最終上傳到 VRChat 的狀態)。
![compute_check](https://hackmd.io/_uploads/rJQzhdmmke.png)
![actual_performance](https://hackmd.io/_uploads/S1s5n_XXJl.png)

---
### 顯示 AvatarUtils 視窗
長話短說：
工作列 `Tools > AvatarUtils`
2.0 以前 `Window > _lil > AvatarUtils`
把你要檢查的 Avatar 拖進這個視窗上方，就可以看 Avatar 的各個部位的數值啦。
![avatarutils](https://hackmd.io/_uploads/H1GKMYmm1l.png)

## 開搞！
終於進入正題了。
要輕量化 / 最佳化，並不是一鍵完成的事情，找出==ඞ到底是誰在搞ඞ==就很重要了。

由於 VRChat 的 Performance Rank 是依照 Avatar 的各種數值決定的。
這邊先以 [PC 的規範](https://creators.vrchat.com/avatars/avatar-performance-ranking-system/#pc-limits)來看，從簡單到困難來一個個處理吧！
我會在每個區塊下，再次列出 VRChat 現行的規範。提供各位參考。

>[!Tip]提醒
以下章節的標題，會盡量連結到原文說明網頁，如果想知道更多可以點進去看

> [!Note]提示
> 可以針對自己的需求
> 從[目錄](#目錄)選擇自己想處理的部分，並跳至該章節
> 但建議先跑一次下面的 AAO Trace And Optimize
> 可以省去很多麻煩

---
### 開搞前記得備份，Avatar 或專案炸了，頭痛的不是我，而是你哦～⭐️
![backup-your-projects](https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExc2lyemV3ZjVicWs0cHBlZDZocGN3aHU5dHFzNDUyeWl3Z2NxN3IyNiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/PmV9Xtp8hhQPkjLhre/giphy.gif)


---
### [總之先來一發全自動吧！(AAO Trace And Optimize)](https://vpm.anatawa12.com/avatar-optimizer/en/docs/reference/trace-and-optimize/)
~~馬上打臉自己。~~
這個自動最佳化元件，預設情況下可以幫你搞定很多基本問題：

* 合併 Skinned Mesh
* 固定目前狀態的 Blend Shape，並將其刪除
* 刪除未使用的物件
* 刪除沒有實質作用的 end 骨
* 刪除沒有作用的 PhysBone
* Animator 最佳化

==為你的最佳化的打出漂亮的第一槍吧！==
1. 於 Hierarchy，選擇 Avatar 物件本身，在 Inspector 下方按 `Add Component`。
2. 選擇並新增`AAO Trace And Optimize`
3. 搞定

> [!Note]提醒
> 該元件會先檢查 Avatar 的 Animator。
> 如果你的選單有開關物件的功能，可能造成部分內容無法完全執行。

可以先進入 Play-mode 看看結果如何。
如果在這一關就達成你的目標，恭喜你！
不行或是想往高級別挑戰的話，就繼續看吧。

裡面有些選項可以改，後面有需要我會再提。
等不及的可以先參考官方說明文件 (↑標題連結↑)。

---
### [Light (光源)](https://creators.vrchat.com/avatars/avatar-optimizing-tips/#limit-the-number-of-lights-your-avatar-uses)
這個東西，**沒事不要放**。

除非你很怕恐怖世界，需要一盞明燈，這盞燈往前打就可以了，你不會需要兩個的。
如果嫌自己 Avatar 太暗，請調整你的 Shader，而不是幫自己打燈。
~~聽說 DPS, SPS 什麼的要很多燈，才能達成人與人的連結的樣子...我什麼都不知道哦~~

| 效能排行 | Excellent | Good | Medium | Poor
| -------- | -------- | -------- | -------- | -------- |
| 光源 | 0 | 0 | 0 | 1 |

---
### [Particle System (粒子系統)](https://creators.vrchat.com/avatars/avatar-optimizing-tips/#reduce-the-emission-amountamount-of-particle-systems)
這個沒辦法最佳化，請參照官方文章，適當控制數量即可。
*這真的蠻重的，拜託省著用啊...*

根據不同的限制，可以從這些地方著手：
* Particle Systems (粒子系統)
很簡單，控制系統數量即可
* Total Particles Active (粒子總數量)
所有 Particle 總數，可以在 Max Particles 中找到。
根據需求，調整 Particle 最大數量即可。(Poor 的極限是 2500 個，超出去就會 Very Poor)
* Mesh Particle Active Polys (粒子系統面數使用總量)
有些人會使用立體模型當作 Particle，這邊就是你的模型面數限制
* Particle Trails Enabled (粒子系統軌跡)
粒子型拖尾效果，例如走路時 Particle 系統會留在原地之類。
請根據需求調整。
* Particle Collision Enabled (粒子系統碰撞)
控制 Partlcie 要不要開啟碰撞功能。
根據需求開關即可。(粒子型拖尾渲染器)
* 粒子型拖尾效果著色器限制，限制蠻嚴格，請省著用。
除了限制高，一個 Trail 也會吃掉兩個材質球。
* Line Renderers (線條型拖尾渲染器)
線條型拖尾效果著色器限制，限制跟粒子型相同，請省著用。

| 效能排行 | Excellent | Good | Medium | Poor
| -------- | -------- | -------- | -------- | -------- |
| 粒子系統 | 0 | 4 | 8 | 16 |
| 粒子總數量 | 0 | 300 | 1,000 | 2,500 |
| 粒子系統面數使用總量 | 0 |1,000 | 2,000 | 5,000 |
| 粒子系統軌跡 | 停用 | 停用 | 啟用 |啟用 |
| 粒子系統碰撞 | 停用 | 停用 | 啟用 |啟用 |
| 粒子型拖尾渲染器 | 1 | 2 | 4 | 8 |
| 線條型拖尾渲染器 | 1 | 2 | 4 | 8 |

---
### Texture Memory (材質記憶體使用量)
這是我們 Avatar 最厲害的 VRAM 殺手――**材質貼圖**。
> [!Tip]小知識
無論原檔是 PNG、JPG、PSD，解析度多高或多低，
==最終的 VRAM 使用量，只會依 Unity 內的設定而改變==。

找到材質球中使用到的貼圖 (Texture) 並選擇它，在 Inspector 可以調整以下內容：

---
#### 最大尺寸 (Max Size)
1. 打開選單開始調低解析度，並按下 `Apply` 檢視結果。
※建議從 4k 以上的開始調，那真的很肥
2. 一直重複第上述步驟，將所有貼圖調到你能接受最低的解析度。
再強調一次，==越低越好！==

> [!Note]調整技巧
> 根據 [lil 的經驗分享](https://qiita.com/lilxyzw/items/9aab99f976295971b8b0#%E8%A7%A3%E5%83%8F%E5%BA%A6%E3%82%92%E4%B8%8B%E3%81%92%E3%82%8B)
> 以下翻譯他對於解析度的推薦設定：
> * 解析度基本上以 2048 以下為主。
> * 鞋子等等不明顯的東西，可以壓到 512 附近。
> * 多數情況下，遮罩貼圖即使壓到 128 也不容易注意到。
> * 根據 MatCap 的部位，也有使用到 32 這種等級的解析度。
> * 「降解析度後很在意雜訊...」的情況，將貼圖設定成 High Quality 試試。

#### 壓縮 (Compression)
1. 打開選單調整壓縮程度，按下 `Apply` 檢視結果。
2. 視情況勾起 `Use Crunch Compression`，品質根據你能接受的範圍調整。

> [!Note]調整技巧
> 一樣引用 [lil 的說明](https://qiita.com/lilxyzw/items/9aab99f976295971b8b0#%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88%E8%A8%AD%E5%AE%9A%E3%82%92high-quality%E3%81%AB%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B)。
> Normal 對紅色頻道 (R Channel) 的破壞很大，皮膚等貼圖推薦用使用 High。但隨著品質提高，容量也有可能增加。
> 以下幾點請注意：
> * 如果貼圖不含透明頻道 (A Channel)，使用 High 會造成該貼圖 VRAM 使用量加倍。
> * 如果貼圖包含透明頻道，容量則不會影響 (臉部、服裝等等很常用)。
> * 如果 Normal 跟 High 的大小相同，Normal 在編譯時會比較好壓縮。
> 
> Crunch Compression 雖然能減少下載大小，但有三個壞處：
> * 對貼圖造成破壞
> * 需要使用額外資源解壓縮
> * VRAM 使用量不變
>
> 因此 Crunch Compression 基本上不推薦使用。
> Kuriko 加註：如果你的下載大小爆掉，還是可以用一下啦...w

---


我理解 Avatar 身上材質貼圖細節越多越好。但一張 4k 貼圖就會吃掉 21MB 上下的 VRAM (如果一顆材質球使用兩張 4k 貼圖，使用量就會加倍)，而且不只貼圖，模型本身也會需要 VRAM，要爆掉其實很容易。

你每壓一層解析度，貼圖 VRAM 使用量會變成原本的 1/4，這是穩賺不賠的做法啊。
反之只要往上調一個解析度，貼圖 VRAM 使用量也會變成原本的 4 倍。

外加大多數玩家的 VRAM 其實不多。根據 [Steam 統計](https://store.steampowered.com/hwsurvey/Steam-Hardware-Software-Survey-Welcome-to-Steam)，目前所有玩家顯卡的 VRAM，以 8GB 為最大宗。
我是呼籲盡量把單個 Avatar 的 VRAM 使用量壓在 75MB 以下 (Good)，真的不難，尤其是跑活動用的模型，壓在 40MB (Excellent) 以下的話，大家都很輕，不管是中、高階顯卡，應該都能跑得很輕鬆吧！

| 效能排行 | Excellent | Good | Medium | Poor
| -------- | -------- | -------- | -------- | -------- |
|材質記憶體 | 40MB | 75MB | 110MB |150 MB|

---
### [Skinned Mesh Renderer (蒙皮網格)](https://vpm.anatawa12.com/avatar-optimizer/en/docs/reference/merge-skinned-mesh/)
`AAO Trace And Optimize` 雖然預設會自動處理，但他會先檢查你的 Animator。如果 Animator 中有可開關物件的 Animation，就會跳過不整合。

在這邊就卡關八成會很幹吧？
繼續往下看吧。

只要能配合身體骨架變形的模型，一個可見的模型物件就是一個 Skinned Mesh。

合併它們的好處，除了在 CPU 處理上可以降低負擔，一部分的 Material Slots 在這裡也會同步合併。
例：若物件 A、物件 B、物件 C 使用同一個材質球，不合併會被算做三個 Material Slots，合併後就只會算成一個。

唯一的代價是，會無法開關其中某個特定物件。(也就是沒辦法穿脫衣服)

如果還是想保留一部分可開關的衣服，或是想全部整合，請跟著以下步驟處理：
1. 在 Avatar 物件本身的 `AAO Trace And Optimize` 中，取消勾選`合併 Skinned Mesh`。
![uncheck_skinnedmesh](https://hackmd.io/_uploads/Hkwad9Qmyl.png)
2. 在 Hierarchy，對 Avatar 物件點滑鼠右鍵，選擇 `Create Empty` 新增一個空白物件，命名隨意，這邊先以 `MergeMesh` 為例。
3. 選擇 `MergeMesh` 物件，在 Inspector 下方按 `Add Component`。
4. 選擇並新增 `AAO Merge Skinned Mesh`。
5. 上述動作會同步新增一個 Skinned Mesh Render，記得先綁一下 Root Transform (通常是 `Hips`) 跟接收光照資訊用的 Anchor Override 物件，建議讓它跟頭部綁的 `Body` 相同。否則光照很有可能會出問題。(臉黑身體亮之類)
![skinned_mesh_settings](https://hackmd.io/_uploads/SyMFPoE7Jx.png)
6. 在 Inspector 右上角，按下鎖頭圖示，暫時讓 Inspector 固定顯示該物件。
![lock](https://hackmd.io/_uploads/ryMy8qXmJx.png)
7. 根據 [anatawa12 的說明](https://vpm.anatawa12.com/avatar-optimizer/ja/docs/reference/merge-skinned-mesh/#notes)，由於臉部的 Blend Shape 數量通常最多，如果全部合併的話，電腦的處理負擔反而會比較大。因此在 Hierarchy，把頭部 `Body` 以外，你想合併的 Skinned Mesh 的物件選起來，拖曳至剛才元件中，Skinned Renderers 下方的`添加元素`。通常建議頭髮、身體等等基本上不會開關的物件都可以合併，總之越多越好。
如果你夠闊氣，全部扔進去是最好的！但別把 `Body` 扔進去啊 XD (除非你想挑戰 Excellent)
![drag_skinnedmesh](https://hackmd.io/_uploads/Hy7Jw577kg.png)
8. 搞定 (記得解除第 4 步的鎖頭！)
9. (Extra) 一開始有提到，`AAO Trace And Optimize` 會刪除合併過 Skinned Mesh 中的 Blend Shape，若想保留原有 Blend Shape，請取消勾選`Optimize BlendShape`。但...
![uncheck_blendshape](https://hackmd.io/_uploads/rJQkBsmQJe.png)

> [!Caution]注意
> Skinned Mesh 合併後的 Blend Shape 由於路徑產生變化，會造成現有的 Animation 故障，取消前請三思。

個人是強烈建議固定即可，重新寫 Blend Shape 路徑跟做 Animation 真的很費時費力 XD
抑或是不合併該 Skinned Mesh，這樣就不會影響 Blend Shape 路徑。

:::warning
💪給挑戰者們
想挑戰 Excellent，請把 `MergeMesh` 改成 `Body`。
並將原本的 `Body` 一併扔進去，這麼一來就可以完全整合。
但剛剛有提到，如果 Blend Shape 太多，還是會造成些微效能下降。
(雖然不影響 Performance Rank)
因為衣服都固定了，原本 Blend Shape 失去用途、路徑也變了。
所以建議，在不需要使用 Blend Shape 的物件中，加入 `Freeze BlendShape` 元件，
勾起所有 Blens Shape，編譯時即可固定目前外觀並刪除 Blend Shape。
:::
| 效能排行 | Excellent | Good | Medium | Poor
| -------- | -------- | -------- | -------- | -------- |
|Skinned Mesh | 1 | 2 | 8 | 16 |
---
### [Material Slots (材質欄位)](https://ttt.rs64.net/en/docs/Tutorial/AtlasTexture-Tutorial)
一開始提過了材質貼圖 (Texture)，但要讓這些貼圖進入 Avatar 中，就是 Material Slots 的職責。

> [!tip]小知識
> Material Slots (材質欄位)
> Material (材質球)
> 這兩個名字看起來類似，但定義上有些差異：
> * 材質球是以檔案為單位，主要在 Unity 端編輯
> * 材質欄位是編譯後的實際數量，主要影響 VRChat 的效能等級
> 
> Unity 在編譯 Avatar 時，會將材質球填裝至有使用它的 Mesh / Skinned Mesh 上。
> 也就代表，只要有多個 Mesh / Skinned Mesh 都使用了同一顆材質球，
> 材質欄位使用量依舊會隨之上升。
> 大概像這樣吧...？
> ![image](https://hackmd.io/_uploads/H12av8O5lg.png)
>
> 
> 所以...[記得整合 Skinned Mesh 啊！](#Skinned-Mesh-Renderer-蒙皮網格)
> 感謝夜嵐蝶 Alma 的知識補充！

> [!Tip]再一個小知識
> 把材質球中貼圖顯示出來的東西，就是 Shader。

要減少 Material Slot 的方式有兩種：
1. 合併 Skinned Mesh
2. 合併材質球 (Atlas 化)

合併 Skinned Mesh 在前面已經說過了，可以回去看看→[傳送門](#Skinned-Mesh-Renderer-蒙皮網格)

合併材質球，就需要召喚我們的新工具：[TexTransTool](https://ttt.rs64.net/)
這個工具厲害的點在於，可以將各種不同的材質貼圖重新排列成一張貼圖。(貼圖 Atlas 化)

由於它也支援 NDMF 架構，只有在編譯的過程才會進行。所以不用擔心破壞原始貼圖。

順帶一提，如果是 Quest 用 Avatar，由於可使用的 Shader 有限，例如日系模常使用的 Toon Lit，這個 Shader 可設定的參數少得可憐 (連半透明都沒有)，就可以使用這個工具完美合併。

:::info
💡 **追記**
工具更新支援材質球分組了，可以更加有效地控制並合併你的材質球囉！
:::

1. 在 Avatar 物件上，按下滑鼠右鍵。選擇 `TexTransTool > TTT Atlas Texture`。
2. Avatar 中，會多一個 `AtlasTexture` 物件。在它的 Inspector 中，會顯示所有該 Avatar 有使用到的材質球。
3. 在 `SelectedMaterial` 中，把你想要合併的材質球勾選起來
![SelectedMaterial](https://hackmd.io/_uploads/S1cgBzJEee.png)
4. (若有需要) 在 `MergeMaterialGroups` 中，針對不同性質的材質球進行分類
例如：皮膚、頭髮、衣服、半透明材質、玻璃、金屬等等...
![MergeMaterialGroups](https://hackmd.io/_uploads/rJkcrz1Vel.png)
外層的 Elements 是分組，Group 中的 Elements 是合併目標的材質球。
考慮到有些性質相似的材質球設定不完全相同，在 Reference 可以指定一顆材質球作為設定基準。
5. 點選下方 <KBD>(NDMF) Enable Optimizing-Phase Preview</KBD> 可以預覽合併後的樣子。
6. 完成！

:::warning
⚠️ **重要**
記得善用 Group 功能，分類你的材質球
由於貼圖合併後，會共用相同的材質球，代表 Shader 設定會完全一樣。
如果沒有分類，一口氣全部合併的話...
以下是半透明材質球被合併的慘劇：
![atlas_failed](https://images.plurk.com/4O27Ikpp0bWJToxsm5qcez.png)
:::

:::info
💡 **小建議**
有時候，即使合併了性質相似的材質球，卻出現結果跟預期相差甚遠的情況。
這通常是有些材質球，使用了較複雜的設定，導致與其他材質球整合不順。
如果是使用 liltoon 的朋友，可以嘗試透過烘焙 (烘烤) 貼圖解決：
1. 找到設定很複雜的材質球
2. 由於操作不可逆，請先備份該材質球，如果出包還可以拿備用的重試
3. 選擇適合你的烘焙選項，試試看結果。
![bake](https://hackmd.io/_uploads/SkAZQBdqxl.png)
4. 完成！

感謝 Touma 分享的技巧！
:::

:::warning
💪 **給挑戰者們**
Quest 用的 ToonLit 與 Toon Standard 著色器，由於不支援半透明貼圖，
即使不整合貼圖，還是會發生一樣的悲劇。
可以嘗試使用 [AAO Remove Mesh By Mask](#Remove-Mesh-By-Mask) 或 [AAO Remove Mesh By UV Tile](#Remove-Mesh-By-UV-Tile)。
除了能移除無法正常運作的材質球，也可能會省一些貼圖、面數哦！
:::

| 效能排行 | Excellent | Good | Medium | Poor
| -------- | -------- | -------- | -------- | -------- |
| 材質球 | 4 | 8 | 16 | 32 |
#### ...我稍微提一下下 Shader (著色器)
雖然這東西不會影響 Performance Rank，
但著色器有時因為某些特殊設定，還是會把顯卡燒得哀哀叫。
如果你聽過或遇過 Shader 炸房，那就是其中一種。
設定時請多加注意。**別當機掰人。**

另外，VRChat 的 Safety 設定中，有關閉 Shader 的功能。
如果其他玩家關了你的 Shader，在他們眼中，你的 Shader 會進入 Fallback 狀態，這東西可以在 Unity 的 Shader 中預先寫入。
可以參考[官方文章](https://creators.vrchat.com/avatars/shader-fallback-system/)瞭解詳情。
(就我所知，[liltoon](https://booth.pm/zh-tw/items/3087170) 自己就可以在 Inspector 中，[事先設定 Fallback Shader](https://lilxyzw.github.io/lilToon/ja_JP/base/vrchat.html)，有興趣的話可以參考一下)

---
### PhysBones
使頭髮、服裝隨風飄逸，給人嚕到爽的獸耳，捏起那吹彈可破的臉頰，甚至讓你「波濤洶湧」。
背後的重要功臣，都是我們的 PhysBone 元件。
> [!note]附註
> PhysBone 簡稱 PB。

這個環節稍微複雜些，會分別說明影響 Performance Rank 的四個要素：
1. [PhysBone 元件數 (Components)](#PhysBone-元件數)
2. [PhysBone 影響骨頭數 (Transforms)](#PhysBone-影響骨頭數)
3. [PhysBone 碰撞體數 (Colliders)](#PhysBone-碰撞體數)
4. [PhysBone 碰撞偵測數 (Collision Checks)](#Physbone-碰撞偵測數)

---
#### PhysBone 元件數

在開始最佳化前，先說明 PB 的兩種實裝方式：
1. 直接建立在 Transform 中
這是最簡單的實裝方式。把元件直接放在要動的 Transform 本身，其子級的 Transform 也會跟著動起來。
![physbone_onRoot](https://hackmd.io/_uploads/B1aTXoBmJl.png)
優點是安裝簡單 (不須設定 Root Transform)，但由於這種實裝方式會散在 Armature 中的四處，缺點也就是管理困難。
2. 建立在空白物件內，手動指定 Root Transform
![physbone_onEmptyObject](https://hackmd.io/_uploads/ryPLEoSQJg.png)
優缺點基本上是反過來，透過建立類似資料夾的架構，管理、啟用 / 停用、刪除 PB 都很方便。缺點是實裝時，需額外指定要動起來的 Root Transform。

這是個酷東西，但數量太多的話，Very Poor 還是會降臨的。
要讓它減少，有兩個做法：合併它 & 刪掉他。

**是的，只有這兩個選項。**

在忍痛刪除 PB 前，我們可以先試著合併它們。

---
##### [合併 PhysBone](https://vpm.anatawa12.com/avatar-optimizer/en/docs/reference/merge-physbone/)
先說明 PB 可以合併的條件：
1. 不同的 PB 之間，他們的上一級必須有共同的 Root Transform，超越兩級就不行囉 (所以別肖想用 `Hips` 搞定一切啊 XD)
2. 要合併的 PB 們，設定的數值必須**完全一致**。

以上的條件，面對不同實裝方式的 PB，合併方式其實很相似。
但這邊會個別獨立說明。

:::info
:information_source: 注意
由於 PB 有一次只能抓一邊的限制。
也就代表，如果要抓合併過的耳朵，一次只能抓一邊，同時抓兩邊有一邊會沒反應。

但搖晃跟碰撞部分完全不受影響！
耳朵只要嚕一嚕就很香了吧？不要抓啦，<font color=Pink>很痛耶 >△<</font>
:::
---
###### 建立在 Transform 中的 PhysBone
這邊以 Rusk 為例，她所有的 PB 都是透過這個方式實裝。
1. 先展開 Armature，找到裝有 PB 的 Transform。
2. 找到數值設定相同的 PB，這裡以 `Hair_Side_L` 與 `Hair_Side_R` 為例。
![physbone_merge_hair_side](https://hackmd.io/_uploads/r1VbXhH7kx.png)
3. 由於這兩個 PB 的設定值完全相同，也有共同的 Root Transform：`Head`，所以這就是可以合併的對象。
4. 在共同的 Root Transform `Head` 上按下滑鼠右鍵，選擇 `Create Empty` 新增一個空白物件，命名隨意，為了方便管理，這裡先命名 `Hair_Side`。
5. 將 `Hair_Side_L` 與 `Hair_Side_R` 拉至 `Hair_Side` 層級內，讓這兩個 PB 與 Root Transform 之間，多一個層級。(這不會破壞原有骨架，放心！)
6. 在 `Hair_Side` 物件，到 Inspector 點選 `Add Component`，新增 `AAO Merge PhysBone`。(跟 Merge Skinned Mesh 一樣，在這裡記得先按右上方鎖頭固定顯示哦！)
7. 將下方的 `Hair_Side_L` 與 `Hair_Side_R` 拖拉至 `AAO Merge PhysBone` 中的`添加元素`。
至目前為止，應該會看到這個情況。
![physbone_merge_hair_side_result](https://hackmd.io/_uploads/r1bjB2Sm1l.png)
8. 完成！其他有相同條件的 PB 也請重複以上步驟進行合併吧！

---
###### 建立在空白物件中的 PhysBone
這邊以 Chiffon 為例，她所有的 PB 都是透過這個方式實裝。
1. 展開裝有 PhysBone 的物件，檢查裡面所有 PhysBone 的 Root Transform 位置。
2. 找出有符合合併條件的 PB 物件。這邊以 `Ear_L` 跟 `Ear_R` 為例。(他們的設定值完全相同，共通的上一層 Transform 都是 `Head`)
![physbone_merge_ear](https://hackmd.io/_uploads/HyFBaeLm1e.png)
3. 新增一個空白物件，命名一樣隨意，這邊也先命名成 `Ear` (由於不受骨架限制，擺放位置完全自由，但為了整理方便，我還是會整理在 `PB` 物件內)
4. 將 `Ear_L` 跟 `Ear_R` 拉至 `Ear` 物件中。
5. 選擇 `Ear` 物件，到 Inspector 點選 `Add Component`，新增 `AAO Merge PhysBone`。(跟 Merge Skinned Mesh 一樣，在這裡記得先按右上方鎖頭固定顯示哦！)
6. 將下方的 `Ear_L` 與 `Ear_R` 拖拉至 `AAO Merge PhysBone` 中的`添加元素`。
至目前為止，應該會看到這個情況。
![physbone_merge_ear_result](https://hackmd.io/_uploads/HJKjfvLQJg.png)
6. 完成！其他有相同條件的 PB 也請重複以上步驟進行合併吧！

---
##### 停用 PhysBone 元件
殘酷時刻到來。
如果合併完成，編譯後還是超標的話，就開始找不重要的 PB，停用它吧。

兩個停用方向供參考：
1. 給你捏、拽的 PB，例如臉頰。說真的，會捏的人真的不多，關了吧。
2. 東西太小，移動幅度又不大的 PB，真的看不出來，關了吧。

還有一個終極作法，如果 PB 影響的物件本身關閉後，整體不會太醜的話，就直接把物件刪掉。好處多多，省面數又省 PB。
刪除物件後，一開始的 `AAO Trace And Optimize` 一旦偵測到 PB 的 Transform 中沒有對應的 Skinned Mesh，在編譯過程會自動幫你處理掉。(就說它很神吧)
    
---
| 效能排行 | Excellent | Good | Medium | Poor
| -------- | -------- | -------- | -------- | -------- |
| PhsyBone 元件數 | 4 | 8 | 16 | 32 |
---
#### [PhysBone 影響骨頭數](https://creators.vrchat.com/avatars/avatar-dynamics/physbones/#transforms)

如果你處理完了 PB，這個問題可能會比較不容易發生。
但總是有個萬一，例如一個 PB 底下有狗幹多的骨頭。就會發生影響骨頭數太多的問題。

但這個做法有個缺陷：有些比較尾端的骨頭會不能動...
**==...有另一個更好的做法==→[超～級好的做法。](#Bones-骨頭)**

* 檢查真實影響骨頭總數量
    1. 還記得[顯示 AvatarUtils 視窗](#顯示-AvatarUtils-視窗)的方法吧？請把它叫出來。
    2. 把你的 Avatar 拖曳到該視窗上方，可以看到 Avatar 的各種數值。
    3. 切到 `PhysBone` 頁面，就能列出所有的 PB 元件。
    4. 避免讓沒用到的 PB 元件影響判讀，請先進入一次 Play-Mode，讓 AAO Trace And Optimize 把沒作用 PB 從列表上移除，再關閉 Play-mode。
視窗會留下有實際作用的 PB，比較好尋找目標。(暫時別重整，不然會回到原始狀態)

* 找出太不明顯的尾端骨頭，加入 Ignore 清單中以無視它。
    1. 以 Rusk 衣服的右側抽繩為例，先選擇它的 PB 物件 `String_R`。
    2. 在 Inspector 中，可以看到 `Ignore Transforms` 底下有個 `Size`，這是設定要處理多少跟子骨頭。由於這次的 PhysBone 只有一根子骨頭，所以就把 `Size` 設定為 `1`，隨之也會出現一個空白欄位 `Element 0`。
(設定 `2` 會再出現 `Element 1`，以此類推。適用於一個 PB 元件下，有多根子骨頭)
![physbone_transform_string_r](https://hackmd.io/_uploads/ry5m8ZPQJx.png)
    3. 展開 `String_R` 的所有子骨頭，按住 `Alt` 鍵，展開 `Stringe_R` 的話，就能一次展開所有子骨頭。
    4. 將最尾端的 `String_R.003_end`，拖曳至 `Element 0` 的右側 `None (Transform)`。在 Scene 視窗中，也可以發現 PB 的末端節點少了一塊。看到的畫面會是這樣。
![physbone_transform_string_r_ignored](https://hackmd.io/_uploads/HJ3VPbvQJe.png)
    5. 完成
    
這麼一來，由於無視了這個末端骨頭，你的 PB 影響骨頭數就會減少 1 塊。
>[!tip]小知識
如果把上一級 `String_R.003` 放到 `Element 0` 的話，就會連帶 `String_R.003_end` 一起無視。影響骨頭數也會減少 2 塊呦！

但如同剛才說明的代價，實際遊玩中，這個被無視的 Transform 只會跟著上一級的 Transform 一起移動，本身並不會變形。在視覺上會是硬的。(起碼不會固定在原地啦 XD)

這個功能很適合用在一個 PB 下，有非常多的子骨頭的物件，例如下面這件裙子。
雖然看起來砍了很多，但砍掉的 Transform 都很尾端，實際動起來還是很可愛哦！
![physbone_transform_too_much](https://hackmd.io/_uploads/HJZkh-DmJl.png)

> [!note]附註
在 `Ignore Transforms` 最下方有個 `Multi Child Type`，對應了其他兩種處理模式，
可以參考[官方文章](https://vrc.school/docs/Avatars/PhysBones/#multi-child-type)，有影片說明不同模式處理子骨頭的模式，就不細提了。

---
| 效能排行 | Excellent | Good | Medium | Poor
| -------- | -------- | -------- | -------- | -------- |
| PB 影響骨頭數 | 16 | 64 | 128 | 256 |
---
#### [PhysBone 碰撞器數](https://creators.vrchat.com/avatars/avatar-dynamics/physbones/#vrcphysbonecollider)
這要突破 Very Poor 應該蠻難的啦...

碰撞體數，其實也就是我們常說的 Collider。
但這邊的 Collider 只會跟指定它的 PB 互動。
例如抬腿時，只要裙子有指定大腿的 Collider，碰到裙子就會跟著飄起來。
或是手臂往內擠壓時，只要胸部有指定手臂的 Collider，能擠壓胸部之類。

通常這會爆掉的主因，是你穿的衣服也附上了自己的 Collider，但大多數情況下，Avatar 本身其實就內建了許多 Collider 讓你使用。自然沒有必要讓兩個位置幾乎相同的 Collider 同時存在。(當然如果衣服本身有特殊設計，需要使用自己的 Collider 就是例外。)

以這件衣服為例，它在大腿的部分使用了自帶的 Collider。
![physbone_collider_came_with_cloth](https://hackmd.io/_uploads/HyL5sGPm1e.png)
但 Chiffon 的素體本身就設有很完善的 Collider。
![physbone_collider_from_Chiffon](https://hackmd.io/_uploads/Hy0yhzvX1l.png)

改善它的方式很簡單：
1. 用鎖頭固定 PB 的 Inspector。
2. 找到 Avatar 本體附帶，位置、性質相同的 Collider。
4. 把原本衣服自帶的 Collider 一個個替換成 Chiffon 的 Collider。
5. 刪掉衣服自帶的 Collider 元件。
6. 完成。

就這樣，超級簡單吧？

| 效能排行 | Excellent | Good | Medium | Poor
| -------- | -------- | -------- | -------- | -------- |
| PB 碰撞器 | 4 | 8 | 16 | 32 |

---
#### Physbone 碰撞偵測數
這裡的的最佳化需要結合調整 PB 影響骨頭數跟 Collider 的數量。
因為這個數值只是所有 PB 中的影響骨頭數，以及其指定的 Collider 的總和。

* 來計算一下吧！
假設一個 PB 下，有 32 個影響骨頭數，並設有 2 個 Collider。
碰撞偵測數就是 32×2=64。所有 PB 的碰撞偵測數計算方式皆為如此。
將所有會使用到的 PB 元件的碰撞偵測數加總起來，便為最終結果。

這個數字跟 Collider 一樣，其實蠻難爆掉的 XD
| 效能排行 | Excellent | Good | Medium | Poor
| -------- | -------- | -------- | -------- | -------- |
| 碰撞偵測數 | 32 | 128 | 256 | 512 |

---
### Bones (骨頭)
當影響身體骨架的 Transform (骨頭) 太多，也會導致 Very Poor 發生。
雖然一開始提到的 AAO Trace And Optimize 可以解決大部分的骨頭數量。
但例如，跟身體骨架無關，完全是衣服自己的骨頭太多 (裙子、緞帶、頭髮等等)。會需要手動處理。
這個技巧可以直接應用到 PhysBone 的骨頭上，也能當作是最佳化 PhysBone 的副章節吧。

#### [合併骨頭 (AAO Merge Bone)](https://vpm.anatawa12.com/avatar-optimizer/en/docs/reference/merge-bone/)
嘿對，又是我們的 AAO，這個工具的作用是，將目標骨頭，融合至上一個父級骨頭，藉此減少一根骨頭，如果這個骨頭同時有應用在 PhysBone 上，也可以同步減少一個 PhysBone 影響骨頭數。
同時，這可以避免掉設定 PhysBone Ignore 時，指定的骨頭以下，都不能動的問題。
可說是一舉三得啊！

特別感謝 Touma 與夜嵐蝶 Alma 介紹的技巧：
1. 找到想融合的對象，這邊以這套衣服的裙子為例。可以看到它的骨頭數量非常可觀。
![skirts](https://hackmd.io/_uploads/S1QsG15cxg.png)
2. 在 Hierarchy 展開裙子下所有子骨頭，按住鍵盤的 <kbd>Alt</kbd> + 滑鼠右鍵，展開 `SkirtA`，即可一次全部展開。
3. 根據自己的需求，選擇想要融合的骨頭。
最簡單、無腦的方式，就是間隔選擇，像這樣：
![bone_select](https://hackmd.io/_uploads/H1UYSkc9gg.png)
4. 選好後，在右方的 Inspector 下方按 `Add Component`，找到並選擇 `AAO Merge Bone`，可以一次幫這些骨頭統一新增元件。
5. 搞定。

> [!Important]有件事情要注意
由於融合了將近一半的骨頭，若有設定 PhysBone，可能導致動態效果比原始版本僵硬了不少，可以透過調整 PhysBone 的設定值，讓動態盡量跟原本的服裝相同。
以我改裙子的心得，降低 Pull、Momentum、Immobile，效果好像比較明顯。

> [!Tip]經驗分享
承上，這件裙子，我融合的骨頭並非完全間隔，而是選擇上半部，移動幅度較小的骨頭，下半部移動幅度大的反而盡量保留。這也是最佳化的概念吧，在不嚴重影響外觀的前提，盡量降低負荷。
![bone_sel_2](https://hackmd.io/_uploads/Sy0fiyc9lg.png)
只要調整得當，效果其實很不錯！
![bone_opt](https://images.plurk.com/4r4FSQYUCSjETDuCnypQM.gif)
![bone_result](https://hackmd.io/_uploads/BJo8iy55gx.png)

由於這個處理技巧，同時能減少 PB 影響骨頭數，為了方便參考一併附上

| 效能排行 | Excellent | Good | Medium | Poor
| -------- | -------- | -------- | -------- | -------- |
| 骨頭數 | 75 | 150 | 256 | 400 |
| PB 影響骨頭數 | 16 | 64 | 128 | 256 |


---
### Polygons (面數)
最終大魔王，**Polygon**。

面對這個經常害你 Very Poor 的東西，工具的作者們也是絞盡了腦汁在寫。
方法非常多，所以篇幅也比較大，讓我們開始吧！

> [!tip]朗報
> 以下所有工具都是 NDMF 體系，所以使出組合技是沒問題的！

---
* AAO 系
    1. [Remove Mesh By BlendShape](#Remove-Mesh-By-BlendShape)
    2. [Remove Mesh By Mask](#Remove-Mesh-By-Mask)
    3. [Remove Mesh By Box](#Remove-Mesh-By-Box)
    4. [Remove Mesh By UV Tile](#Remove-Mesh-By-UV-Tile)
* Mantis LOD Editor
    * [Mantis LOD Editor NDMF 化工具](#mantis2)
* lil 系
    * [lilNDMFMeshSimplifier](#lilmesh2)
* Meshia 系
    * [Meshia Cascading Avatar Mesh Simplifier](#meshia2)

---
#### [Remove Mesh By BlendShape](https://vpm.anatawa12.com/avatar-optimizer/en/docs/reference/remove-mesh-by-blendshape/)
有幫 Avatar 穿過衣服的人，應該都遇過衣服作者，要求使用 Blend Shape 隱藏身體的一部分，以防止穿模。
但 Blend Shape 將身體隱藏後，裡面所蘊藏的面數並不會消失。只是被擠壓成一坨小到看不見的東西。但這些還是會算進你 Avatar 的面數裡。所以需要使用這個工具，將使用 Blend Shape 隱藏的面數直接砍掉。

這邊以 Rusk 為例：
1. 選擇有 Blend Shape 的物件，在 Inspector 下方按 `Add Component`。
2. 找到並選擇 `Remove Mesh By BlendShape`
3. 在出現的元件中，會列出該 Skinned Mesh 中所有的 Blend Shape
4. 根據 Rusk 的衣服，會需要隱藏 `kisekae_Upper Arm`、`kisekae_Lower Arm`、`kisekae_Chest`、`kisekae_Spine`、`kisekae_Lower Leg`、`kisekae_Foot`。
在 `Remove Mesh By BlendShape` 中，也將這些 Blend Shape 一併勾起來。
![removemesh_blendshape](https://hackmd.io/_uploads/SJpUkODXkg.png)
5. 完成！

針對面數較多的素體，可以節省很多面數哦！

---
#### [Remove Mesh By Mask](https://vpm.anatawa12.com/avatar-optimizer/en/docs/reference/remove-mesh-by-mask/)
使用遮罩貼圖移除面數。
通常用於多個物件卻做在同一個 Skinned Mesh 中
可以根據該物件的原始 UV，針對需要移除的部位，做一張遮罩貼圖，塗白或塗黑都可。
或是該物件本身就使用了不同的材質球。可以直接用一張全白或全黑的貼圖砍掉不需要的部分。

>[!tip]如果目標是材質球內的所有面數
>作者有提供另一個 Remove Mesh By UV Tile 功能，除了處理真正的 UV Tile 外，也可以移除整個材質球內的面數，流程更簡單→[傳送門](#Remove-Mesh-By-UV-Tile)

這邊以我的雙馬尾為例，它使用了兩顆材質球處理緞帶跟頭髮。
![removemesh_mask_before](https://hackmd.io/_uploads/Sky3-Ow7yg.png)
1. 選擇要處理的物件，在 Inspector 下方按 `Add Component`。
2. 找到並選擇 `Remove Mesh By Mask`
3. 找到要移除的 Mesh 所在的材質球。
這次我要移除的是緞帶，對應的是位於第 1 材質球 `twin 1`。
4. 在 `Remove Mesh By Mask` 中，勾起 `套用於第 1 個材質槽`
![removemesh_mask_target](https://hackmd.io/_uploads/Byt1VOD7kl.png)
5. 選擇你的遮罩貼圖，如果是我的情況，可以選擇右方新增一張全白或全黑的貼圖。
6. 移除模式可以選擇 `Remove Black` 或 `Remove White`
因為我這次是一張全黑貼圖，所以選擇 `Remove Black`
7. 看到緞帶消失了，完成！
![removemesh_mask_complete](https://hackmd.io/_uploads/BkRTNdvmkx.png)
用不到的材質球 在編譯時會自動移除。可以留著沒關係。

---
#### [Remove Mesh By Box](https://vpm.anatawa12.com/avatar-optimizer/en/docs/reference/remove-mesh-by-box/)
如果有些 Mesh，沒辦法靠 Blend Shape 砍，你在貼圖中又找不到對應的位置。就可以暴力點，用一個方塊去砍面數。

這邊用這件衣服舉例，我想要盡量移除它的緞帶
![removemesh_box_before](https://hackmd.io/_uploads/rJlyudwXyg.png)
1. 選擇衣服的物件，在 Inspector 下方按 `Add Component`。
2. 找到並選擇 `Remove Mesh in Box`
3. 然後你可能會看到以下獵奇畫面。
![removemesh_box_default](https://hackmd.io/_uploads/HkF_d_wX1l.png)
因為它會給一個預設的 Box，只要這個物件進入 Box 內的面數會遭到移除。
4. 很明顯這不是我們要的結果，所以要花點時間編輯 Box 的大小、位置、數量。
5. 在 `Remove Mesh in Box` 元件內，Box 的右側，可以設定 Box 的數量。
因為這次要移除緞帶，但不影響到衣服本身，所以我得使用兩個 Box
6. 調整好大小跟尺寸
![removemesh_box_result](https://hackmd.io/_uploads/SJwNqOw71e.png)
7. 完成！

除了衣服，所有你想刪除的物件，都可以透過這個工具移除掉。
甚至有時想讓面數刪的更乾淨。
可以同時使用 `Remove Mesh By Mask` 跟 `Remove Mesh in Box` 達成組合技，讓面數砍得更精準！
![removemesh_box_combo](https://hackmd.io/_uploads/Bk1Uiuv7yx.png)

---
#### [Remove Mesh By UV Tile](https://vpm.anatawa12.com/avatar-optimizer/en/docs/reference/remove-mesh-by-uv-tile/)
:::info
💬 Need Your Help!
文章剛寫好時，這個功能才推出，還沒摸得很熟，如果有人知道詳細用法，請告訴我。
目前已知，UV Tile 使用一張格狀的貼圖，分別對應到不同的物件上。用此工具可以進行 Mesh 移除...的樣子。請原諒我的無知 QQ
:::

跟 `Remove Mesh By Mask` 有點類似，但這個更暴力。

一樣以移除雙馬尾上的緞帶為例
1. 選擇要處理的物件，在 Inspector 下方按 `Add Component`。
2. 找到並選擇 `Remove Mesh By UV Tile`
3. 找到要移除的 Mesh 所在的材質球。
要移除的是緞帶，對應的是位於第 1 材質球 `twin 1`。
4. 展開 `Material Slot 1`，把 `Tile 0` 勾起來
5. 緞帶消失了，完成！
![rremovemesh_uv_result](https://hackmd.io/_uploads/Bk184BdXJg.png)
用不到的材質球 在編譯時會自動移除。可以留著沒關係。

---
#### 對模型本體減少面數

如果面數依舊超標，就需要對本體減少面數了
以下工具，減少面數的演算法各有千秋，可以多方嘗試，找到最適合的方案

---
#### [Mantis LOD Editor NDMF 化工具](https://booth.pm/ja/items/5409262) <a id="mantis2"></a>
資本主義的力量，優點是模型不容易出現破洞，缺點是調整時會很卡。
    
1. 選擇你要砍面數的物件，在 Inspector 下方按 `Add Component`。
2. 找到並選擇 `NDMF Mantis LOD Editor`
3. 按下最下方的 `Preview`，可以即時預覽砍面數的狀況。
4. 按住 `Quality` 右側的滑桿，開始往左拉。
元件下方的 `Triangles` 能顯示原始面數跟目前的面數。
5. 在你可以接受的範圍內，努力降低面數。
元件上方的勾勾會影響不同的砍面數模式，
可以根據自己的需求，嘗試各種組合，得到最好的結果。
7. 就這樣！ 

重複上述步驟，在各個物件上東砍砍西砍砍。
如果想快點找到面數較多的物件，可以用叫出 [AvatarUtils](#顯示-AvatarUtils-視窗)，使用 Renderers 頁面列出各個物件的面數，從肥的開始砍，效果會比較好。

![image](https://hackmd.io/_uploads/ByTDkYwQJx.png)

---
#### [lilNDMFMeshSimplifier](https://github.com/Whinarn/UnityMeshSimplifier/wiki/Mesh-Simplifier-API#simplificationoptions) <a id="lilmesh2"></a>
免費、簡單，優點是導入後會立刻看到成效，缺點是看不到面數，數值上會有點難抓

1. 選擇你要砍面數的物件，在 Inspector 下方按 `Add Component`。
2. 找到並選擇 `NDMF Mesh Sinplifier`
3. 按住 `Quality` 右側的滑桿，開始調整。
`0` 品質最差，`1` 是沒有砍
4. 在你可以接受的範圍內，努力降低面數。
元件下方的勾勾會影響不同的砍面數模式，
可以根據自己的需求，嘗試各種組合，得到最好的結果。
5. 就這樣！ 

重複上述步驟，在各個物件上東砍砍西砍砍。
一樣可以叫出 [AvatarUtils](#顯示-AvatarUtils-視窗)，使用 Renderers 頁面列出各個物件的面數，從最肥的開始砍！

![lilmesh_result](https://hackmd.io/_uploads/ryRYyViQyg.png)

---
#### [Meshia Cascading Avatar Mesh Simplifier](https://ramtype0.github.io/Meshia.MeshSimplification/docs/en/vrchat/meshia-cascading-avatar-mesh-simplifier.html) <a id="meshia2"></a>

相見恨晚的殺手級工具
優點是在一個元件內就能動到所有模型的面數，懶人的福音。缺點是模型還蠻容易破洞，不太適合大量砍面數

1. 在 Avatar 物件上，按下滑鼠右鍵。選擇 `Meshia Mesh Simplification > Meshia Cascading Avatar Mesh Simplifier`。
2. Avatar 中，會多一個 `Meshia Cascading Avatar Mesh Simplifier` 物件。在它的 Inspector 中，會包含一個與物件同名的元件
3. 於 Target Trangle Count 輸入你的目標面數，或是在右邊選擇他的面數 Preset。
4. 如果你的總面數已經超出目標面數，下方模型會開始依照比例進行自動調整。
以下分享幾個調整技巧，可以自由使出組合技
    * 拉動滑桿，或是輸入數字，調整特定物件的面數。其他物件會根據設定的目標面數，根據比例繼續自動調整。
    * 針對已經不想再調整面數的物件，啟用右方的鎖頭，固定該物件的面數。調整其他物件時，就不會繼續影響該物件。
    * 按下右方齒輪，調整減面數的演算邏輯
        * 如果手指等等很常注視的地方出現太明顯的破洞。可以勾起 `Preserver Border Edges` 試著將洞補起來。
        * 其他還有很多選項，可以根據需求自行嘗試
    * 如果喜歡一個個手動調整，可以關閉 `Enable Auto Adjust`，停止全體模型的面數調整。也能適時點選 <kbd>Adjust</kbd> 按鈕，自動調整尚未鎖定物件的面數。
5. 透過開關下方 `Enable NDMF Preview` 預覽刪減前後的樣子。
6. 找到屬於你的甜蜜點，完成！

> [!tip]小技巧
> 這個工具好像不會計算其他 NDMF 工具處理過的結果，導致實際面數可能會低於你設定目標面數。
> 這時可以適時調高目標面數，讓模型接近你想要的結果。
> ![image](https://hackmd.io/_uploads/B15LSsv8gl.png)
    
感謝 Vistanz 的推薦這個工具。

---


| 效能排行 | Excellent | Good | Medium | Poor
| -------- | -------- | -------- | -------- | -------- |
| 面數    | 32,000     | 70,000     |70,000     |70,000  |

只要低於 70,000 面就能符合 Good 的標準欸，壓這個很划算吧？

---
嗯？你說做了之後，面數還是壓不下來？
[![image](https://hackmd.io/_uploads/ByYRMeFQkl.png)](https://www.youtube.com/watch?v=bqWfosgn_QI)
衣服不要穿這麼多，買衣服時也請慎選。
有些作者會販售頁面提到自己的衣服面數，可以做為購買時的參考。
如果沒有標，就請自求多福了。\\|/

## [批次上傳 Avatar](https://github.com/anatawa12/ContinuousAvatarUploader/blob/master/README.ja.md)
辛辛苦苦幫 Avatar 瘦身，但想到自己有一狗票穿著不同衣服的 Avatar。
要一個個在 SDK 按 Build & Upload 會很痛苦對吧。(除非你有鋼鐵般的精神)

這篇文章要介紹的最後一個工具：[Continuous Avatar Uploader](https://github.com/anatawa12/ContinuousAvatarUploader)
透過設定 Asset，幫你一次上傳一堆 Avatar。
1. 在 Hierarchy 選擇你要上傳的 Avatar 們。
這次我先選擇這些 Avatar
![continuous_select](https://hackmd.io/_uploads/S11Hy8_Q1x.png)
2. 對他們點選滑鼠右鍵，選擇 `Continuous Avatar Uploader > Group from Selection`
3. 選擇儲存的位置，位置跟命名隨意，這次我選擇創一個 `Closet` 資料夾，檔名取 `Rusk_PC_A_1`。
4. 在 Project 視窗，找到該資料夾，按一下 `Rusk_PC_A_1` 這份檔案。
5. 在 Inspector 可以看到剛才我們加入的所有 Avatar。
6. 勾選該 Avatar 要上傳的平台，這次我們所有的 Avatar 都是做給 PC 的，就一個個全部勾選 `PC Windows`。
![image](https://hackmd.io/_uploads/HJ_sYjvUgl.png)
7. 先到 `VRChat SDK > Show Control Panel` 叫出 SDK 視窗。
8. 回到剛才的視窗，按下 `Upload All`，就開始批次上傳啦！
![image](https://hackmd.io/_uploads/ryWJMIOmkg.png)
由於是一隻一隻編譯跟上傳，會需要一些時間。去喝杯肥宅快樂水吧！

> [!tip]小補充
> 如果要在 Asset 中新增 Avatar，將 Avatar 物件拖曳至下 Asset 下方的 `Avatar to Add` 就可以新增 Avatar 囉！

:::info
:information_source: 經驗分享
透過功能列 `Tools > Continuous Avatar Uploader`，
可以叫出步驟 8 的上傳視窗，放入不同的 Asset 一併上傳。
我個人會把 Avatar 分散至不同的 Asset 管理。
一個 Asset 中，建議放 5~10 隻 Avatar 就好。
如果上傳途中出現錯誤，可以從出錯的 Avatar 那組 Asset 開始重新上傳。
有點類似存檔點的概念吧。
例如當下我有 48 套衣服，如果在第 32 套衣服出錯，全部重傳應該會很崩潰吧 XD
![upload_multi_asset](https://hackmd.io/_uploads/r1JnPJbEyg.png)
:::

## 結語
文章也來到了尾聲
讓我們一起把 VRChat 變成性能友善的地方吧！
有其他想問的地方，可以來 [Twitter](https://twitter.com/kuriko_tw) 找我，會在能力範圍盡量回答。

最後讓大家看看我的究級最佳化 Rusk！
![rusk_excellent](https://hackmd.io/_uploads/By3FESDmke.png)
![rusk_excellent2](https://hackmd.io/_uploads/Syxm7LuXJg.jpg)

## 謝謝大家！
貧乳才是王道。
![no_big_oppai](https://hackmd.io/_uploads/HkAhBUO71g.jpg)
(***<font color=red>不要曬</font>奶 ji！***)
(***<font color=red>反對</font>大歐派！***)