Created
November 17, 2017 11:02
-
-
Save empika/f1ec6735b1959738e79c30c6d88088ae to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
#if UNITY_EDITOR | |
using UnityEditor; | |
#endif | |
using UnityEngine; | |
using UnityEngine.Rendering; | |
namespace Code.Utils | |
{ | |
public class MeshUtils | |
{ | |
public static GameObject SpriteToMesh(GameObject spriteObject) | |
{ | |
SpriteRenderer spriteRenderer = spriteObject.GetComponent<SpriteRenderer>(); | |
if (spriteRenderer == null) | |
{ | |
return null; | |
} | |
GameObject content = new GameObject(spriteObject.name); | |
content.isStatic = true; | |
Transform holderTransform = content.transform; | |
holderTransform.SetParent(spriteObject.transform); | |
holderTransform.localPosition = Vector3.zero; | |
holderTransform.localScale = Vector3.one; | |
holderTransform.localRotation = Quaternion.identity; | |
Mesh mesh = new Mesh(); | |
mesh.vertices = Array.ConvertAll(spriteRenderer.sprite.vertices, i => (Vector3)i); | |
mesh.uv = spriteRenderer.sprite.uv; | |
mesh.triangles = Array.ConvertAll(spriteRenderer.sprite.triangles, i => (int)i); | |
mesh.RecalculateBounds(); | |
mesh.RecalculateNormals(); | |
mesh.RecalculateTangents(); | |
MeshRenderer meshRenderer = content.AddComponent<MeshRenderer>(); | |
MaterialPropertyBlock block = new MaterialPropertyBlock(); | |
block.SetTexture("_MainTex", spriteRenderer.sprite.texture); | |
block.SetColor("_Color", spriteRenderer.color); | |
meshRenderer.SetPropertyBlock(block); | |
meshRenderer.sharedMaterial = spriteRenderer.sharedMaterial; | |
meshRenderer.sortingLayerID = spriteRenderer.sortingLayerID; | |
meshRenderer.sortingOrder = spriteRenderer.sortingOrder; | |
meshRenderer.shadowCastingMode = ShadowCastingMode.Off; | |
meshRenderer.receiveShadows = false; | |
spriteRenderer.enabled = false; | |
MeshFilter meshFilter = content.AddComponent<MeshFilter>(); | |
meshFilter.sharedMesh = mesh; | |
return content; | |
} | |
public static GameObject CombineMeshes(GameObject parentObject, GameObject[] objectsToCombine, string name, | |
Vector3 position, Material material, Texture2D texture) | |
{ | |
if (objectsToCombine.Length > 0) | |
{ | |
GameObject combinedObject = new GameObject(); | |
combinedObject.transform.SetParent(parentObject.transform); | |
combinedObject.transform.localPosition = Vector3.zero; | |
combinedObject.transform.localScale = Vector3.one; | |
combinedObject.name = name; | |
CombineInstance[] combine = new CombineInstance[objectsToCombine.Length]; | |
for (int i = 0; i < objectsToCombine.Length; i++) | |
{ | |
combine[i].mesh = objectsToCombine[i].GetComponent<MeshFilter>().sharedMesh; | |
Matrix4x4 parentTransform = parentObject.transform.worldToLocalMatrix; | |
combine[i].transform = parentTransform * objectsToCombine[i].transform.localToWorldMatrix; | |
} | |
combinedObject.isStatic = true; | |
MeshFilter filter = combinedObject.AddComponent<MeshFilter>(); | |
MeshRenderer renderer = combinedObject.AddComponent<MeshRenderer>(); | |
filter.sharedMesh = new Mesh(); | |
filter.sharedMesh.name = "Tiles"; | |
filter.sharedMesh.CombineMeshes(combine, true); | |
filter.sharedMesh.RecalculateNormals(); | |
filter.sharedMesh.RecalculateBounds(); | |
filter.sharedMesh.RecalculateTangents(); | |
MeshRenderer currentMeshRenderer = objectsToCombine[0].GetComponent<MeshRenderer>(); | |
MaterialPropertyBlock currentPropertyBlock = new MaterialPropertyBlock(); | |
currentMeshRenderer.GetPropertyBlock(currentPropertyBlock); | |
renderer.sharedMaterial = material; | |
renderer.sortingLayerID = currentMeshRenderer.sortingLayerID; | |
renderer.sortingOrder = currentMeshRenderer.sortingOrder; | |
renderer.shadowCastingMode = ShadowCastingMode.Off; | |
renderer.receiveShadows = false; | |
MaterialPropertyBlock block = new MaterialPropertyBlock(); | |
renderer.GetPropertyBlock(block); | |
block.SetTexture("_MainTex", texture); | |
block.SetColor("_Color", currentPropertyBlock.GetVector("_Color")); | |
renderer.SetPropertyBlock(block); | |
#if UNITY_EDITOR | |
UnityEditor.Unwrapping.GenerateSecondaryUVSet(filter.sharedMesh); | |
UnityEditor.EditorUtility.SetDirty(combinedObject); | |
#endif | |
return combinedObject; | |
} | |
return null; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
namespace Code.Game.Behaviours.Sprites | |
{ | |
[ExecuteInEditMode] | |
public class SpriteBaker : MonoBehaviour | |
{ | |
public GameObject CombinedSprites; | |
public Material Material; | |
public Texture2D Texture; | |
public void Start() | |
{ | |
if (CombinedSprites) | |
{ | |
MeshRenderer renderer = CombinedSprites.GetComponentInChildren<MeshRenderer>(); | |
MaterialPropertyBlock block = new MaterialPropertyBlock(); | |
block.SetTexture("_MainTex", Texture); | |
renderer.SetPropertyBlock(block); | |
renderer.sharedMaterial = Material; | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using Code.Game.Behaviours.Sprites; | |
using Code.Game.World.Environment; | |
using Code.Utils; | |
using UnityEditor; | |
using UnityEngine; | |
namespace Editor.Game.Behaviours.Sprites | |
{ | |
[CustomEditor(typeof(SpriteBaker))] | |
public class SpriteBakerEditor : UnityEditor.Editor | |
{ | |
private SpriteBaker spriteBaker; | |
private SerializedProperty materialProperty; | |
private SerializedProperty textureProperty; | |
private SerializedProperty combinedSpritesProperty; | |
private void OnEnable() | |
{ | |
spriteBaker = (SpriteBaker) target; | |
materialProperty = serializedObject.FindProperty("Material"); | |
textureProperty = serializedObject.FindProperty("Texture"); | |
combinedSpritesProperty = serializedObject.FindProperty("CombinedSprites"); | |
} | |
public override void OnInspectorGUI() | |
{ | |
serializedObject.Update(); | |
EditorGUILayout.PropertyField(materialProperty); | |
EditorGUILayout.PropertyField(textureProperty); | |
EditorGUILayout.PropertyField(combinedSpritesProperty); | |
if (GUILayout.Button("Create combined mesh")) | |
{ | |
if (spriteBaker.CombinedSprites != null) | |
{ | |
DestroyImmediate(spriteBaker.CombinedSprites); | |
spriteBaker.CombinedSprites = null; | |
} | |
createCombinedMesh(); | |
} | |
if (GUILayout.Button("Save mesh")) | |
{ | |
if (spriteBaker.CombinedSprites != null) | |
{ | |
MeshFilter meshFilter = spriteBaker.CombinedSprites.GetComponent<MeshFilter>(); | |
if (meshFilter && meshFilter.sharedMesh) | |
{ | |
if (PrefabUtility.GetPrefabType(meshFilter.sharedMesh) == PrefabType.None) | |
{ | |
ProjectWindowUtil.CreateAsset(meshFilter.sharedMesh, | |
string.Format("{0}_{1}_mesh.asset", spriteBaker.gameObject.name, | |
spriteBaker.Material.name)); | |
} | |
// TODO, what do we do if the mesh already exists? | |
} | |
else | |
{ | |
Debug.Log("No mesh filter or mesh"); | |
} | |
} | |
} | |
if (GUILayout.Button("Revert to sprites")) | |
{ | |
if (spriteBaker.CombinedSprites != null) | |
{ | |
DestroyImmediate(spriteBaker.CombinedSprites); | |
spriteBaker.CombinedSprites = null; | |
foreach (SpriteRenderer spriteRenderer in spriteBaker.GetComponentsInChildren<SpriteRenderer>()) | |
{ | |
spriteRenderer.enabled = true; | |
} | |
} | |
} | |
serializedObject.ApplyModifiedProperties(); | |
} | |
private void createCombinedMesh() | |
{ | |
List<GameObject> gameObjectsToCombine = new List<GameObject>(); | |
SpriteRenderer[] spriteRenderers = spriteBaker.GetComponentsInChildren<SpriteRenderer>(); | |
foreach (SpriteRenderer spriteRenderer in spriteRenderers) | |
{ | |
if (spriteRenderer == null) continue; | |
Animator animator = spriteRenderer.gameObject.GetComponent<Animator>(); | |
if (animator) continue; | |
string materialCompareName = spriteRenderer.sharedMaterial.name.Replace(" (Instance)", ""); | |
if (materialCompareName == spriteBaker.Material.name) | |
{ | |
GameObject meshGameObject = MeshUtils.SpriteToMesh(spriteRenderer.gameObject); | |
if (meshGameObject != null) | |
{ | |
gameObjectsToCombine.Add(meshGameObject); | |
} | |
} | |
} | |
Debug.Log("Combining " + gameObjectsToCombine.Count + " meshes for: " + spriteBaker.Material.name); | |
spriteBaker.CombinedSprites = MeshUtils.CombineMeshes( | |
spriteBaker.gameObject, | |
gameObjectsToCombine.ToArray(), | |
string.Format("Mesh_{0}", spriteBaker.Material.name), | |
Vector3.zero, | |
spriteBaker.Material, | |
spriteBaker.Texture | |
); | |
Debug.Log("Destroying individual sprite meshes"); | |
for (int i = 0; i < gameObjectsToCombine.Count; i++) | |
{ | |
DestroyImmediate(gameObjectsToCombine[i]); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment