Spaces:
Sleeping
Sleeping
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 |
-
//
|
| 29 |
string[] prefabPaths = Directory.GetFiles(MAIN_FOLDER, "*.prefab", SearchOption.AllDirectories);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
-
//
|
| 32 |
-
|
| 33 |
-
PrepareMeshesForSimplification(prefabPaths);
|
| 34 |
|
| 35 |
-
|
|
|
|
| 36 |
foreach (string path in prefabPaths)
|
| 37 |
{
|
| 38 |
GameObject go = PrefabUtility.LoadPrefabContents(path);
|
| 39 |
if (go != null)
|
| 40 |
{
|
| 41 |
-
|
| 42 |
-
|
| 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 |
-
//
|
| 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]
|
| 84 |
|
| 85 |
-
// ChunkBasedCompression
|
| 86 |
BuildPipeline.BuildAssetBundles(
|
| 87 |
ASSETBUNDLE_DIR,
|
| 88 |
BuildAssetBundleOptions.ForceRebuildAssetBundle | BuildAssetBundleOptions.ChunkBasedCompression,
|
|
@@ -93,7 +95,7 @@ public class TestBuilder
|
|
| 93 |
GC.Collect();
|
| 94 |
}
|
| 95 |
|
| 96 |
-
//
|
| 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
|
| 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
|
| 115 |
{
|
| 116 |
foreach (var path in prefabPaths)
|
| 117 |
{
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
foreach (var dep in dependencies)
|
| 121 |
{
|
| 122 |
ModelImporter mi = AssetImporter.GetAtPath(dep) as ModelImporter;
|
| 123 |
-
if (mi != null
|
| 124 |
{
|
| 125 |
-
|
| 126 |
-
mi.
|
|
|
|
|
|
|
|
|
|
| 127 |
}
|
| 128 |
}
|
| 129 |
}
|
| 130 |
}
|
| 131 |
|
| 132 |
-
static
|
| 133 |
{
|
| 134 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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.
|
|
|
|
|
|
|
| 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 |
-
|
| 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.
|
|
|
|
|
|
|
| 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 |
-
|
| 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 |
}
|