Tuesday, November 18, 2014

Unity Tutorial: Easy Mesh Combining For Highlights

Guess what devs? After months of head scratching I've put together a quick and dirty way to both
a) Combine meshes of a Unity-build Prefab into a single mesh and
b) Outline the damn thing OnMouseOver like many games in the past have done.

Best part? I did it out of found script pieces and didn't have to ask anyone directly! :D

____________________________________________________________


The Beginner's Problem:

Whether you're in this post for Performance or Graphics, you've probably determined that you've got way too many meshes per-object. Why do we have these problems? Lack of expertise being shared around effectively.

One thing I've noticed is this Mesh issue is something that mostly afflicts beginner to intermediate devs. If you're really hardcore you've been making your models in Blender or Maya from the start and know a bunch of Mesh / Shader / Camera based tricks to optimize both appearance and performance.

When I've seen the beginner Devs ask things like "how do I highlight the whole prefab like in diablo?" the most common answer is "Why don't you just make your whole model in Blender/Maya and import it?"
Sorry guys, but this is NOT REALLY HELPFUL for those of us who have most of our game models worked out in Unity basic shapes and myriad imported meshes.

____________________________________________________________

Mesh Combining

Your Prefab:


  • The Parent Object (one everything else is inside) MUST BE EMPTY 
    • No mesh
    • scripts OK
  • Take out all mesh-ed objects you don't want included in the single mesh
    • ex: things you want to move separately from the mesh
  • Place at (0,0,0) (you can write a compensation so this isn't necessary, but I didn't bother)
The Theory:
What we're doing here follows some basic steps
  1. Make an array of all meshes inside your Prefab
  2. Make a new Mesh that will be placed on the Parent Object
  3. Combine array of meshes into single mesh on Parent Object
  4. Save mesh you've created to a folder (this part took extra research)

The Steps:
How to Implement
  1. Make sure Line 36 directs to a real folder you have
    1. Mine is directed to the folder Experimental under Assets
  2. Place Prefab at 0,0,0
  3. Place script on empty Parent Object
    1. this will add Mesh Filter and Mesh Renderer assets
  4. Press Play
  5. Pres Play again to stop. The Mesh should be saved in the designated folder
  6. At this point you can do whatever you want with the mesh (or make it again by hitting Play again) In a following post I'll be using this Mesh to create a building outline.
____________________________________________________________

The Script



For Copying

using UnityEngine;
using System.Collections;
using UnityEditor;

[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]

public class CombineMeshes : MonoBehaviour {

GameObject highlight;

void Start() {
MeshFilter[] meshFilters = GetComponentsInChildren<MeshFilter>();
CombineInstance[] combine = new CombineInstance[meshFilters.Length];
int i = 0;
while (i < meshFilters.Length) {
Debug.Log (meshFilters[i].gameObject.transform.name);
combine[i].mesh = meshFilters[i].sharedMesh;
combine[i].transform = meshFilters[i].transform.localToWorldMatrix;
//meshFilters[i].gameObject.active = false;
i++;
}



transform.GetComponent<MeshFilter>().mesh = new Mesh();
transform.GetComponent<MeshFilter>().mesh.CombineMeshes(combine);
transform.gameObject.active = true;

saveMesh ();
}

void saveMesh() {
Debug.Log ("Saving Mesh?");
Mesh m1 = transform.GetComponent<MeshFilter>().mesh;
AssetDatabase.CreateAsset(m1, "Assets/Play Assets/Experimental/" + transform.name + ".asset"); // saves to "assets/"
AssetDatabase.SaveAssets();
}
}

____________________________________________________________

Why Not Blender / Maya?

Why not just re-make every asset of your game carefully in the detailed mesh programs? You're more than welcome to but here's my assessment

Blender

  • Blender is a huge free complex program that really is great. It's just so complex and great that I don't have time to learn it all.
  • To be short: the learning curve is too steep. I'd need more time than I have to make assets I'm not happy with. 
  • And to be honest, what little I have learned to make in Blender looks sloppy
On the other hand, I highly suggest Blendswap.com where real Blender artists occasionally deign to share their works with us script plebs. If you have the time and love it, please learn Blender and share with the rest of us. :D

Maya

  • In shortest terms, it costs money. If you've got it, I've heard it's great but still time consuming.

____________________________________________________________


The Journey
I started this journey in an attempt to take building prefabs (made mostly of textured Unity cubes) and highlight/outlining the entire building on mouse-over for selection and info purposes.

Simple right? Anyone who's done this research knows I'm kidding. You can try to do this a couple ways.
Most Common Suggestion: Outline Shaders
Unlikely Suggestion: Post Processing Effects
Even Less Likely: Eldritch Rituals with Camera Values

My list is also in order of complexity. From my research I figured there are two ways to take clusters of meshed objects and highlight only the outside
  1. combine the meshes into one and use an outline shader
  2. somehow identify the cluster of objects with camera effects and have the camera try to place an outline on the right lines.
Somehow the first seemed simpler so I looked into combining meshes.
THIS was suggested to be done in a couple of ways
  1. Export the whole thing with a bought-in asset thingy to a new file type
  2. Use a bought-in ($55) mesh combining package
  3. Use mesh.CombineMeshes,
Not buying something combined with THIS excellent resource
Swayed me toward the solution we chose today.

______________________________________________________________


If you haven't already figured out how I turn this mesh into an outline, stick around for the future post where I explain it. :D

______________________________________________________________


All blog posts by UnityGirl are inspired by my work with Brunelleschi: Age of Architects on the Aesop Games team. Check out our Crowd Funding page(s)!