webzepetoku commited on
Commit
b99b94d
·
verified ·
1 Parent(s): 0cd74ba

Update UnityProject/Assets/Editor/TestBuilder.cs

Browse files
UnityProject/Assets/Editor/TestBuilder.cs CHANGED
@@ -16,33 +16,35 @@ public class TestBuilder
16
  {
17
  try
18
  {
19
- Debug.Log("🛠️ [UNITY] Inisialisasi Project...");
20
  AssetDatabase.Refresh();
21
 
 
22
  if (Directory.Exists(ASSETBUNDLE_DIR)) Directory.Delete(ASSETBUNDLE_DIR, true);
23
  if (Directory.Exists(MESH_TEMP_DIR)) Directory.Delete(MESH_TEMP_DIR, true);
24
 
25
  Directory.CreateDirectory(ASSETBUNDLE_DIR);
26
  Directory.CreateDirectory(MESH_TEMP_DIR);
27
 
28
- // 1. SCAN SEMUA PREFAB
29
  string[] prefabPaths = Directory.GetFiles(MAIN_FOLDER, "*.prefab", SearchOption.AllDirectories);
 
 
 
 
30
 
31
- // 2. PAKSA SEMUA MESH AGAR BISA DIBACA (Read/Write Enabled)
32
- // Tanpa ini, SimplifyMesh tidak akan menghasilkan apa-apa!
33
- PrepareMeshesForSimplification(prefabPaths);
34
 
35
- Debug.Log("✨ [UNITY] Memulai perampingan mesh 50%...");
 
36
  foreach (string path in prefabPaths)
37
  {
38
  GameObject go = PrefabUtility.LoadPrefabContents(path);
39
  if (go != null)
40
  {
41
- bool changed = SimplifyMeshInGameObject(go);
42
- if (changed) {
43
- PrefabUtility.SaveAsPrefabAsset(go, path);
44
- Debug.Log($"✅ [SIMPLIFY] {Path.GetFileName(path)} berhasil dirampingkan.");
45
- }
46
  PrefabUtility.UnloadPrefabContents(go);
47
  }
48
  }
@@ -53,7 +55,7 @@ public class TestBuilder
53
  EditorUtility.UnloadUnusedAssetsImmediate();
54
  GC.Collect();
55
 
56
- // 3. BUILD ASSETBUNDLES DENGAN KOMPRESI LZ4
57
  BuildTarget[] targets = {
58
  BuildTarget.Android,
59
  BuildTarget.iOS,
@@ -80,9 +82,9 @@ public class TestBuilder
80
  if (importer != null) importer.assetBundleName = platformName;
81
  }
82
 
83
- Debug.Log($"🚀 [BUILD] Membangun {platformName} dengan kompresi LZ4...");
84
 
85
- // ChunkBasedCompression = LZ4 (Ukuran kecil, performa stabil)
86
  BuildPipeline.BuildAssetBundles(
87
  ASSETBUNDLE_DIR,
88
  BuildAssetBundleOptions.ForceRebuildAssetBundle | BuildAssetBundleOptions.ChunkBasedCompression,
@@ -93,7 +95,7 @@ public class TestBuilder
93
  GC.Collect();
94
  }
95
 
96
- // 4. PACKING KE .ZEPETO
97
  string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
98
  string fileName = $"hairku_{timestamp}.zepeto";
99
  string repackPath = Path.Combine(Directory.GetParent(Application.dataPath).FullName, fileName);
@@ -101,68 +103,78 @@ public class TestBuilder
101
  if (File.Exists(repackPath)) File.Delete(repackPath);
102
  ZipFile.CreateFromDirectory(MAIN_FOLDER, repackPath);
103
 
104
- Debug.Log($"✅ [SUCCESS] File Zepeto Unik Dibuat: {repackPath}");
105
  EditorApplication.Exit(0);
106
  }
107
  catch (Exception e)
108
  {
109
- Debug.LogError($"💀 [FATAL] {e.Message}");
110
  EditorApplication.Exit(1);
111
  }
112
  }
113
 
114
- static void PrepareMeshesForSimplification(string[] prefabPaths)
115
  {
116
  foreach (var path in prefabPaths)
117
  {
118
- // Cari semua referensi mesh di dalam prefab dan aktifkan Read/Write
119
- string[] dependencies = AssetDatabase.GetDependencies(path);
120
- foreach (var dep in dependencies)
121
  {
122
  ModelImporter mi = AssetImporter.GetAtPath(dep) as ModelImporter;
123
- if (mi != null && !mi.isReadable)
124
  {
125
- mi.isReadable = true; // AKTIFKAN READ/WRITE
126
- mi.SaveAndReimport();
 
 
 
127
  }
128
  }
129
  }
130
  }
131
 
132
- static bool SimplifyMeshInGameObject(GameObject go)
133
  {
134
- bool hasChanged = false;
 
 
 
 
 
135
  var meshFilters = go.GetComponentsInChildren<MeshFilter>();
136
  foreach (var mf in meshFilters) {
137
  if (mf.sharedMesh != null) {
 
138
  var meshSimplifier = new MeshSimplifier();
139
  meshSimplifier.Initialize(mf.sharedMesh);
140
- meshSimplifier.SimplifyMesh(0.5f); // Target 50%
 
 
141
  Mesh newMesh = meshSimplifier.ToMesh();
142
- newMesh.name = mf.sharedMesh.name + "_simplified";
143
-
144
  string newPath = $"{MESH_TEMP_DIR}/{go.name}_{mf.name}_{Guid.NewGuid()}.asset";
145
  AssetDatabase.CreateAsset(newMesh, newPath);
 
146
  mf.sharedMesh = newMesh;
147
- hasChanged = true;
148
  }
149
  }
150
 
151
  var skinnedMeshes = go.GetComponentsInChildren<SkinnedMeshRenderer>();
152
  foreach (var smr in skinnedMeshes) {
153
  if (smr.sharedMesh != null) {
 
154
  var meshSimplifier = new MeshSimplifier();
155
  meshSimplifier.Initialize(smr.sharedMesh);
156
- meshSimplifier.SimplifyMesh(0.5f);
 
 
157
  Mesh newMesh = meshSimplifier.ToMesh();
158
- newMesh.name = smr.sharedMesh.name + "_simplified";
159
-
160
  string newPath = $"{MESH_TEMP_DIR}/{go.name}_{smr.name}_{Guid.NewGuid()}_skinned.asset";
161
  AssetDatabase.CreateAsset(newMesh, newPath);
 
162
  smr.sharedMesh = newMesh;
163
- hasChanged = true;
164
  }
165
  }
166
- return hasChanged;
167
  }
168
  }
 
16
  {
17
  try
18
  {
19
+ Debug.Log("🛠️ [UNITY] Inisialisasi Project dengan Analisa Mesh...");
20
  AssetDatabase.Refresh();
21
 
22
+ // 1. Pembersihan Folder Kerja
23
  if (Directory.Exists(ASSETBUNDLE_DIR)) Directory.Delete(ASSETBUNDLE_DIR, true);
24
  if (Directory.Exists(MESH_TEMP_DIR)) Directory.Delete(MESH_TEMP_DIR, true);
25
 
26
  Directory.CreateDirectory(ASSETBUNDLE_DIR);
27
  Directory.CreateDirectory(MESH_TEMP_DIR);
28
 
29
+ // 2. Scan Prefabs
30
  string[] prefabPaths = Directory.GetFiles(MAIN_FOLDER, "*.prefab", SearchOption.AllDirectories);
31
+ if (prefabPaths.Length == 0) {
32
+ Debug.LogError("💀 [UNITY] Gagal: Tidak ada prefab ditemukan.");
33
+ EditorApplication.Exit(1);
34
+ }
35
 
36
+ // 3. Paksa Read/Write Enabled pada Model (PENTING!)
37
+ ForceEnableMeshReadWrite(prefabPaths);
 
38
 
39
+ // 4. Proses Simplifikasi dengan Opsi Agresif
40
+ Debug.Log("✨ [UNITY] Memulai perampingan mesh agresif...");
41
  foreach (string path in prefabPaths)
42
  {
43
  GameObject go = PrefabUtility.LoadPrefabContents(path);
44
  if (go != null)
45
  {
46
+ SimplifyMeshAggressively(go);
47
+ PrefabUtility.SaveAsPrefabAsset(go, path);
 
 
 
48
  PrefabUtility.UnloadPrefabContents(go);
49
  }
50
  }
 
55
  EditorUtility.UnloadUnusedAssetsImmediate();
56
  GC.Collect();
57
 
58
+ // 5. Build AssetBundles dengan Kompresi LZ4
59
  BuildTarget[] targets = {
60
  BuildTarget.Android,
61
  BuildTarget.iOS,
 
82
  if (importer != null) importer.assetBundleName = platformName;
83
  }
84
 
85
+ Debug.Log($"🚀 [BUILD] Mencetak biner LZ4 untuk: {platformName}");
86
 
87
+ // Menggunakan ChunkBasedCompression (LZ4) untuk ukuran optimal
88
  BuildPipeline.BuildAssetBundles(
89
  ASSETBUNDLE_DIR,
90
  BuildAssetBundleOptions.ForceRebuildAssetBundle | BuildAssetBundleOptions.ChunkBasedCompression,
 
95
  GC.Collect();
96
  }
97
 
98
+ // 6. Packing Akhir ke .zepeto
99
  string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
100
  string fileName = $"hairku_{timestamp}.zepeto";
101
  string repackPath = Path.Combine(Directory.GetParent(Application.dataPath).FullName, fileName);
 
103
  if (File.Exists(repackPath)) File.Delete(repackPath);
104
  ZipFile.CreateFromDirectory(MAIN_FOLDER, repackPath);
105
 
106
+ Debug.Log($"✅ [SUCCESS] File Zepeto Dibuat: {repackPath}");
107
  EditorApplication.Exit(0);
108
  }
109
  catch (Exception e)
110
  {
111
+ Debug.LogError($"💀 [FATAL] {e.Message}\n{e.StackTrace}");
112
  EditorApplication.Exit(1);
113
  }
114
  }
115
 
116
+ static void ForceEnableMeshReadWrite(string[] prefabPaths)
117
  {
118
  foreach (var path in prefabPaths)
119
  {
120
+ string[] deps = AssetDatabase.GetDependencies(path);
121
+ foreach (var dep in deps)
 
122
  {
123
  ModelImporter mi = AssetImporter.GetAtPath(dep) as ModelImporter;
124
+ if (mi != null)
125
  {
126
+ bool needsUpdate = false;
127
+ if (!mi.isReadable) { mi.isReadable = true; needsUpdate = true; }
128
+ if (mi.meshCompression == ModelImporterMeshCompression.Off) { mi.meshCompression = ModelImporterMeshCompression.Medium; needsUpdate = true; }
129
+
130
+ if (needsUpdate) mi.SaveAndReimport();
131
  }
132
  }
133
  }
134
  }
135
 
136
+ static void SimplifyMeshAggressively(GameObject go)
137
  {
138
+ // Opsi Simplifikasi agar poligon benar-benar berkurang banyak
139
+ var options = SimplificationOptions.Default;
140
+ options.PreserveBorderEdges = false; // Matikan agar lubang/ujung mesh bisa disimplifikasi
141
+ options.PreserveUVSeamEdges = false; // Matikan jika tekstur sedikit geser tidak masalah demi poligon rendah
142
+ options.PreserveUVFoldoverEdges = false;
143
+
144
  var meshFilters = go.GetComponentsInChildren<MeshFilter>();
145
  foreach (var mf in meshFilters) {
146
  if (mf.sharedMesh != null) {
147
+ int oldVirt = mf.sharedMesh.vertexCount;
148
  var meshSimplifier = new MeshSimplifier();
149
  meshSimplifier.Initialize(mf.sharedMesh);
150
+ meshSimplifier.SimplificationOptions = options;
151
+ meshSimplifier.SimplifyMesh(0.4f); // Target sisa 40% poligon saja
152
+
153
  Mesh newMesh = meshSimplifier.ToMesh();
 
 
154
  string newPath = $"{MESH_TEMP_DIR}/{go.name}_{mf.name}_{Guid.NewGuid()}.asset";
155
  AssetDatabase.CreateAsset(newMesh, newPath);
156
+
157
  mf.sharedMesh = newMesh;
158
+ Debug.Log($"✨ [MESH] {mf.name}: {oldVirt} -> {newMesh.vertexCount} vertices.");
159
  }
160
  }
161
 
162
  var skinnedMeshes = go.GetComponentsInChildren<SkinnedMeshRenderer>();
163
  foreach (var smr in skinnedMeshes) {
164
  if (smr.sharedMesh != null) {
165
+ int oldVirt = smr.sharedMesh.vertexCount;
166
  var meshSimplifier = new MeshSimplifier();
167
  meshSimplifier.Initialize(smr.sharedMesh);
168
+ meshSimplifier.SimplificationOptions = options;
169
+ meshSimplifier.SimplifyMesh(0.4f);
170
+
171
  Mesh newMesh = meshSimplifier.ToMesh();
 
 
172
  string newPath = $"{MESH_TEMP_DIR}/{go.name}_{smr.name}_{Guid.NewGuid()}_skinned.asset";
173
  AssetDatabase.CreateAsset(newMesh, newPath);
174
+
175
  smr.sharedMesh = newMesh;
176
+ Debug.Log($"✨ [SKINNED] {smr.name}: {oldVirt} -> {newMesh.vertexCount} vertices.");
177
  }
178
  }
 
179
  }
180
  }