Archive for July, 2013

Masking textures using shaders NGUI

If you follow this blog, you know that I am having some problems with Unity3d and NGUI. Mostly it’s because I was so familiar with Flash/AS3 that I am feeling kinda lost. But I am getting better at this 2D in a 3D world thing. One of the thing that I miss the most is masks. In Flash they are very easy to use and with them you can do a plethora of effects and animations. Now with bitmap based technologies, it is not such a simple task to implement a mask.


NGUI Panels have the option of being clipped panels, which means that only a rectangle of the panel will be shown. This is great for some cases, like when you need your masked region to be a rectangle, but for most masking cases it won’t work. Also, it doesn’t allow nested clipping which is a bummer.

Using another camera

Also, this guy created a shader that allows you to do similar masking as in Flash. It looks good, and it does the desired effect, but there is one drawback, for every mask, you need a new camera… That makes it very hard to manage in a large project or if you have multiple masks. I would use clipping more than this technique because it is easier to deal with.

Transparency shader

Now, this is the technique I devised that allows you to have multiple textures masked at the same time each with their own masks. This is really good if you load images (thumbnails) from a server and need them to be masked.

To do it we need to create a new shader. We start that by taking the Unlit – Transparent Colored shader and we will add two lines of code to it. First we will give it another texture for input. Secondly, we will take the output of the shader, use its rgb colors, but use the alpha of the new input texture we added.  Here is the code :

Shader "Unlit/Transparent Colored with mask" {
  Properties {
    _MainTex ("Base (RGB), Alpha (A)", 2D) = "white" {}
    _AlphaTex ("Yeahyeah", 2D) = "white" {}
    LOD 100
      "Queue" = "Transparent"
      "IgnoreProjector" = "True"
      "RenderType" = "Transparent"
    Pass {
      Cull Off
      Lighting Off
      ZWrite Off
      Fog { Mode Off }
      Offset -1, -1
      ColorMask RGB
      AlphaTest Greater .01
      Blend SrcAlpha OneMinusSrcAlpha
      ColorMaterial AmbientAndDiffuse
      SetTexture [_MainTex] {
        Combine Texture * Primary
      SetTexture [_AlphaTex] {
        Combine previous, texture

So that is the shader, but now we have to use it. This is actually what I found to be the most difficult part because there is a lot of documentation about how to make shaders, but not how to use them. So in the next chunk of code, we will create a texture in NGUI, give it a shader. After that we will feed the shader the textures it need to calculate the mask.

_newTexture = NGUITools.AddWidget<UITexture>(gameObject);
_newTexture.pivot = UIWidget.Pivot.TopLeft;
_newTexture.material = new Material(Shader.Find("Unlit/Transparent Colored with mask"));
_newTexture.mainTexture = myTexture2D;
//now we give the shader the textures
_newTexture.material.SetTexture(<wbr />"_MainTex", testRed);
_newTexture.material.SetTexture(<wbr />"_AlphaTex", testAlpha);

In this testRed is the image we want to mask and testAlpha is the alpha channel we want our previous image to use.

So here you have it, I will add pictures later to illustrate it better, but for now that’s how it is. Note that with this technique you can’t really animate or nest the masks, but you can have a lot of them at the same time.

UPDATE : If you are using a version of NGUI that is higher than 2.64, you should probably use this shader instead.

, , , , , , , ,


Creating new GameObjects

I don’t know what you want when you create new GameObjects for 3D, but for my UI stuff, I need the new instance to be a child of the GameObject that I have selected in the hierarchy. When you use the command provided by the Unity editor, it creates the new GameObject at the root of your project. Plus when you move that GameObject (haha I wrote MovieClip at first) in the hierarchy, its position and scale will change according to the parent’s values. So basically, I was spending my time moving new GameObject and setting their position to (0,0,0) and scale to (1,1,1).

When I had enough of it, I took matters in my own hands and created a little panel that will create a new GameObject as a child of the GameObject selected in the editor. It also sets it position to 0 and scale to 1. Bam! Here is the code for it:

public class CreateGameObject : EditorWindow{
	[MenuItem("zedia/Utility/GameObject Creator")]
	public static void ShowWindow() {
		EditorWindow.GetWindow<CreateGameObject>("GameObject Creator");
	void OnGUI (){
		GUILayout.Label("GameObject Creator4", EditorStyles.boldLabel);
		GUILayout.Label("Creates a new GameObject under the selected GameObject in the Hierarchy,", EditorStyles.label);
		GUILayout.Label("with local position (0,0,0) and local scale (1,1,1)", EditorStyles.label);
		var retainValue = GUILayout.Button("Add GameObject To:");
		GameObject sel = EditorGUILayout.ObjectField(Selection.activeGameObject, typeof(GameObject), true, GUILayout.Width(140f)) as GameObject;
		if (retainValue){
	public static void CreateTheEmptyGameObject(){
		GameObject newGameObject = new GameObject();
		newGameObject.transform.parent = Selection.activeGameObject.transform;
		newGameObject.transform.localScale = new Vector3(1,1,1);
		newGameObject.transform.localPosition = new Vector3(0,0,0);
		Selection.activeObject = newGameObject;
	void OnSelectionChange () { Repaint(); }

Now, that was what I wanted, but it would have been even better if it could listen for a keyboard shortcut. So I set out to do just that in the previous little panel except it didn’t work. Something was preventing me from receiving the events from the keyboard (I can Debug.Log, but as soon as I execute code it doesn’t work). So I decided I would just create a MenuItem associated with a keyboard shortcut. Here is what the code look likes:

using UnityEngine;
using System.Collections;
using UnityEditor;
public class CreateGameObjectCommand : MonoBehaviour {
	[MenuItem("zedia/Utility/GameObject Creator Command #%m")]
	static void CreateGameObject () {
		GameObject newGameObject = new GameObject();
		newGameObject.transform.parent = Selection.activeGameObject.transform;
		newGameObject.transform.localScale = new Vector3(1,1,1);
		newGameObject.transform.localPosition = new Vector3(0,0,0);
		Selection.activeObject = newGameObject;

So here you go; either a panel in the editor or a shortcut or both if you want to. Just grab the code and put the files in a folder named Editor, and Unity will add a menu for you. I hope Unity3D changes their default behavior for creating new GameObject but until then, we will make it work ourself!

, , , ,


Parse error: syntax error, unexpected ';' in /homepages/25/d169645162/htdocs/wp-content/themes/fusion/footer.php on line 13