- Home /
Making mesh non-readable
It looks like if I generate Mesh from code, then it's always treated as readable, i.e. it's stored in RAM and VRAM. Is there a way to generate mesh and then mark it as non-readable?
I can see that Texture2D.Apply
Texture2D.Apply(bool updateMipmaps = true, bool makeNoLongerReadable = false);
has a parameter makeNoLongerReadable which does exactly that. Can I achieve the same thing for Mesh?
Answer by Paulius-Liekis · Jun 27, 2014 at 04:52 PM
There is a public method:
Mesh.UploadMeshData(bool markNoLongerReadable)
although it's not documented for some reason...
I have a mesh, serialised to a .asset file. When I try and use it, it's not readable. Calling this function, $$anonymous$$esh.Upload$$anonymous$$eshData(false);
$$anonymous$$akes no difference.
Of course not. If an imported mesh is not marked as readable you can not read or write it. The parameter on Upload$$anonymous$$eshData is named markNoLongerReadable. Have you noted the "no longer"? You have to mark your mesh as readable in the mesh importer.
This may be an edge case, as the inspector for the .asset does not have any options (ie. the readable option that is usually on obj, fbx assets etc)
Although I've just realised the OP doesn't fit what I was trying to do (googling for) anyway :)
Answer by IgorAherne · Oct 04, 2017 at 11:01 PM
if you are in the Editor, and require to adjust import settings of many meshes at once, then here is a tool for that:
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Linq;
// Select objects in scene, then press the button to apply needed configuration
// to all mesh-assets at once.
// Igor Aherne 05 oct 2017 facebook.com/igor.aherne
public class TweakMeshAssets : EditorWindow {
bool _isMeshReadable;
HashSet<GameObject> _gameObjectsWithNoAssets = new HashSet<GameObject>();
[MenuItem("Tools/Tweak Mesh Assets from selection")]
static void Init() {
TweakMeshAssets window = EditorWindow.CreateInstance<TweakMeshAssets>() as TweakMeshAssets;
window.Show();
}
public void OnGUI() {
_isMeshReadable = EditorGUILayout.Toggle("is mesh readable", _isMeshReadable);
if(GUILayout.Button("apply configuration to mesh assets of selected Objects")) {
_gameObjectsWithNoAssets.Clear();
//shared meshes, coupled with the gameObjects that carry them:
Dictionary<Mesh, GameObject> meshesOfSelectedObjects = allMeshesOfSeletion();
ToggleIsReadable(meshesOfSelectedObjects);
}
if(GUILayout.Button("select all gameObjects that didn't have assets from the previous Apply")) {
Selection.objects = _gameObjectsWithNoAssets.ToArray();
}
MiscTools.Editor_UIFunctions_Misc.DrawMany_GUI_Spaces(2);
EditorGUILayout.LabelField("Bonus: sometimes the meshes can have a bug, where they are showing as Instance");
EditorGUILayout.LabelField("And don't seem to actually be linked to the actual mesh asset. Use folowing:");
EditorGUILayout.LabelField("NOTICE: BACK UP YOUR SCENE FILE SO U CAN ROLL BACK when using this bonus!!!!!!");
if(GUILayout.Button("revert Selected gameObjects to prefab, but preserve transfrom values (Non-recursive!)")) {
revertSelectedToPrefab_keepTransformVals();
}
}//end OnGUI()
void ToggleIsReadable(Dictionary<Mesh, GameObject> meshesOfSelectedObjects) {
foreach(var kvp in meshesOfSelectedObjects) {
Mesh sharedMesh = kvp.Key;
GameObject gameObj = kvp.Value;
string asset_path = AssetDatabase.GetAssetPath(sharedMesh);
ModelImporter importerForAsset = ModelImporter.GetAtPath(asset_path) as ModelImporter;
if(importerForAsset == null) {
Debug.Log("couldn't find an asset for the mesh belonging to " + gameObj);
_gameObjectsWithNoAssets.Add(gameObj);
continue;
}
importerForAsset.isReadable = _isMeshReadable;
EditorUtility.SetDirty(sharedMesh);
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
void revertSelectedToPrefab_keepTransformVals() {
foreach(GameObject go in Selection.gameObjects ) {
GameObject go_prefabRoot = PrefabUtility.FindPrefabRoot(go);
Vector3 pos = go_prefabRoot.transform.position;
Quaternion rot = go_prefabRoot.transform.rotation;
Vector3 scale = go_prefabRoot.transform.localScale;
Undo.RegisterCompleteObjectUndo(go_prefabRoot,"reverting selected Gos to prefabs, keeping transforms");
PrefabUtility.RevertPrefabInstance(go_prefabRoot);
go_prefabRoot.transform.position = pos;
go_prefabRoot.transform.rotation = rot;
go_prefabRoot.transform.localScale = scale;
EditorUtility.SetDirty(go_prefabRoot);
}
UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty();
}
Dictionary<Mesh, GameObject> allMeshesOfSeletion() {
Dictionary<Mesh, GameObject> meshesOfSelectedObjects = new Dictionary<Mesh, GameObject>();
foreach(object obj in Selection.objects) {
GameObject obj_asGo = obj as GameObject;
if(obj_asGo != null) {
sharedMeshes_fromChildren(obj_asGo.transform, meshesOfSelectedObjects);
continue;
}
}//end foreach obj in selection
return meshesOfSelectedObjects;
}
//recursive, will extract all meshes (will auto-exclude duplicates) from the sub-children.
//Returns shared meshes, coupled with their gameObjects
void sharedMeshes_fromChildren(Transform currTransform, Dictionary<Mesh,GameObject> resultingMeshes) {
for (int i = 0; i < currTransform.childCount; i++) {
Transform child = currTransform.GetChild(i);
sharedMeshes_fromChildren(child, resultingMeshes);
}//end for child transforms
MeshFilter mf = currTransform.GetComponent<MeshFilter>();
if(mf == null) {
return;
}
if(mf.sharedMesh == null) {
return;
}
if(resultingMeshes.ContainsKey(mf.sharedMesh) == true) {
return;
}
resultingMeshes.Add(mf.sharedMesh, currTransform.gameObject);
}
}
Your answer
![](https://koobas.hobune.stream/wayback/20220613150928im_/https://answers.unity.com/themes/thub/images/avi.jpg)