Unity - Textures

From NoskeWiki
Jump to: navigation, search


NOTE: This page is a daughter page of: Unity

Unity3D is a multi-platform 3D game engine. This page gives some code snippets and links specific for dealing with Textures in Unity. Note that all my Scripts are in C# because it's the most powerful way to program in Unity.

Textures in Unity

The "Texture" or "Texture2D" object must used to show any 2D images ("pictures") on screen, but can be a little tricky to use. Textures are discussed in the Unity Documentation here.

Loading an Image into Unity as a Texture

To add a Texture direction into Unity, simply drag it anywhere under your "Assets" folder (a subdirectory called "Textures" is the best idea) using a File Explorer, and then you'll see it automatically import as a texture and appear in the Project window in Unity shortly afterwards. Ideally you should try to use images which are a power of 2 along each axis (eg: 2, 4, 8, 16, 32, 64, 128,256, 512 or 1024 in width/height) - if not Unity will want to round this up or down to the nearest power, causing your image to lose quality. If you have a non-standard size but want it preserved well (especially if you want this texture shown in your GUI) you'll want to click it in the Project Window then use the Inspector window to re-import it by selecting Texture Type = "GUI", Format = "Truecolor" and then hitting "Apply". Default settings use pretty heavy compression (to keep the size of your game down) and thus will cause noticeable quality loss - especially if you've used a non-standard sized image.

Displaying Textures on 3D Objects (using a Material)

Once the texture exists in Unity, you'll be able to drag it into the "Texture" tag on various objects. To get it onto any 3D Game Objects (like a Cube) you'll first have to create a new Material. Go: Create > Material, then drag the texture onto the material (in the Inspector window), and then apply the material to the object via the "Mesh Renderer > Materials > Element 0" in the Inspector window. To build up a complex scene with textures you won't want to muck around like this - you'll instead use a 3D program like Cinema 4D (or one of the other supported programs) to create your models and scenes. When you import the model files (by dragging it under Assets), all the textures will be automatically imported and nested under the model file - just make sure you give all the textures different names to prevent any clashes!

Loading an Image into a Texture Instance

I've explained how to add a Texture into Unity, but accessing textures in code is a little trickier. There are a couple of ways to do this. The easy way is using the Inspector window to drag the texture onto an instance of a Script. To do this: first add a new script/class (Assets > Create > C# Script), and in that script you'll create a public instance of Texture:

using UnityEngine;
using System.Collections;
public class Example : MonoBehaviour
  public Texture myTexture;    // We don't assign anything in code - we use the Inspector window.
  public void Awake() {
      renderer.material.SetTexture("_BumpMap", myTexture); 
            // Assigns this texture to our GameObject's Mesh Renderer's Material.

Notice we called " SetTexture" to apply the texture to our Game Object (so we can actually see something happen!). In the next step you'll have to drag the Script from the Project window onto a Game Object in the Hierarchy window. If you hit play now, there will be an error. You must click the Game Object and in the properties window you'll see an empty spot available for "myTexture". Now drag in the desired texture. What's powerful about this feature is that you can reuse the same script on many objects, but use different textures for each. Note however this will only work if you use a "MonoBehaviour".

Another option is to load a resource at run time using a "Resource Folder". Resource Folders are collections of assets that are included in the built Unity player, but are not necessarily linked to any GameObject in the Inspector. Simply create a new folder called "Resources" under the "Assets" folder and drag in an image file. To load this file you can then use the "Resources.Load" function:

using UnityEngine;
using System.Collections;
public class Example
  public Texture myTexture;    // We don't assign anything in code - we use the Inspector window.
  void Example() {
      myTexture = (Texture)Resources.Load("bitmap_file");    // NOTE don't include an extension.

By using this option you can reduce the size of the game executable file. Another way to load files dynamically is by using "Asset Bundles", but this is only available in Unity Pro. See: Loading Resources at RunTime.

A final method to generate Textures on the fly is to load the JPEG or PNG images from a the web, using the code using the "WWW" class and the image's URL.

Drawing Textures in the GUI (HUD)

There appear to be about four ways to draw textures in the GUI (Heads up Display).

The first option is to manually add a "GUI Texture" to your hierarchy. Go: Game Object > Create Other > GUI Texture. You can then drag on any texture/image from the Project window, and set its Position to 0.1,0.1,0 for the bottom left corner and fix its scale. As you can see this requires no code to setup and you may like this option if you're just after a watermark, but I personally hate using these fraction coordinate systems to size and position a texture.

The second option is to create a new "GUISkin Style". In the Project window go: Create > GUI Skin and rename it "MyGUISkin". In the Inspector window, expand "Custom Styles", increase its Size by one then setup your custom style with a new name "MyNewStyle" and set "Normal > Background" to your texture. What's cool about this option is you can also specify a "Hover" (mouse over) and "Active" (mouse down) texture to create an interactive button effect with no code. Next you'll probably want to change the padding, border and margins to all zeros and to actually display this GUISkin Style add this code to your OnGUI script:

void OnGUI() {
  GUI.skin = MyGUISkin;
  if (GUI.Button(new Rect(0,0,50,50), "Text on Image",  " MyNewStyle"))
    Debug.log("Button clicked");
  // OR (if you don't want it clickable):
  GUI.Label(new Rect(100, 0, 50, 50), "", " MyNewStyle");

Notice that you are using proper pixel coordinate which I like, but take note that within OnGui (0,0) is the upper left (not bottom left) and y increases as you go down! Creating a GUI style is your best option if you want to create buttons with a background image. Also notice there is no reference to the texture itself in the code - only the name of the style.

The third option is use the "GUIContent" command to place a texture inside a GUI box, label, button etc. You can use the default style for the box/label/bottom, or create your own if you want to align the image slightly different relatively to the text.

GUI.Label(new Rect(5, 30, 50, 26), new GUIContent("Icon Text", myIconTexture,
      "Tooltip"), "MyOwnStyle");

Here I've assumed something is loaded into the Texture "myTexture". If you want to use the default label style you could simply remove the last argument ("MyOwnStyle"). GUI Content allows you to add one image, text and even a tooltip to any GUI element, although I've yet to figure out how to get the tooltip to appear.

The fourth option I find the simplest to use: "GUI.DrawTexture". If you're looking to put your texture in a fixed location on screen without worry about styles this is your best option! The call looks like this:

GUI.DrawTexture(new Rect(10, 10, 200, 100), yourTexture, ScaleMode.ScaleToFit, true, 0f);

The last three parameters are scaleMode, alphaBlend and imageAspect. Setting the imageAspect to 0 will use the aspect of the original image (which you'll typically want).

Other Pages