Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loading a PNG image as a texture at runtime in Unity3d

I'm using a series of PNG images as sprites to create animations on a plane for an augmented reality application in Unity. The PNG images are loaded as textures, and the textures are applied to a plane to create an animation sequence that tracks with an augmented reality target.

Here is the script that is attached to the plane and controls the animation sequence.

File PNGSequence.js

#pragma strict
var tecture : Texture[];

var changeInterval : float = 0.06;
var isRunning = false;
var isLooping = false;

function Start () {
    var isRunning = true;
}

function Update () {
    if( isRunning == true) {
        Animation ();
    }
}

function Animation () {
    var index : int = Time.time/changeInterval;
    index = index % tecture.Length;
    renderer.material.mainTexture = tecture[index];
    if ( index == tecture.Length-1){
        if( isLooping == false){
            isRunning = false;
        }
           renderer.material.mainTexture = tecture[0];
    }
}

Textures are assigned by drag-and-drop of PNG files in the editor and everything works fine if I limit the PNG count. As my texture count increases, however, I'm getting out of memory errors on Android.

I would like to load the PNG files as textures at run time to limit the number memory, but I'm having trouble getting the code working.

I've tried LoadImage.

var imageTextAsset : TextAsset = Resources.Load("test.png");
var tex = new Texture2D (4, 4);
tex.LoadImage(imageTextAsset.bytes);
renderer.material.mainTexture = tex;

I've also tried loading the image directly as a texture (since this seems to work with the editor).

renderer.material.mainTexture = Resources.LoadAssetAtPath"Assets/Images/test.png",Texture);

No luck with either. Any suggestions on how to accomplish this?

EDITED

I was able to get this working thanks to the link provided by Xerosigma. I had an issue with paths (and I suspect with the Texture requirement on load).

Outside of loading the PNG textures, I also discovered that Unity does not do memory management on textures. To recover memory, textures need to be manually unloaded after use.

Textures are all placed in a "Resources" folder. The resources folder can be placed anywhere in the Assets hierarchy - I created several individual folders for each of my PNG sequences to organize them, then added a Resources folder within each to hold the actual PNGs.

Textures are assigned through the editor by specifying a texture count (ie. 100), a base name ("texture_" for instance), and zero padding.

File PNGSequenceRunTime.js

#pragma strict

var imageCount : int = 0;
var imageNameBase : String = "";
var imageNameZeroPadding : int = 0;

var changeInterval : float = 0.06;
var isRunning = false;
var isLooping = false;

private var texture : Texture = null;

function PlayRocket () {
    isRunning = true;
}

function Start () {
    var isRunning = false;
    var fileName : String = imageNameBase + ZeroPad(0,imageNameZeroPadding);
    texture = Resources.Load(fileName);
}

function Update () {
    if( isRunning == true) {
        PNGAnimation ();
    }
}

function PNGAnimation () {
    var index : int = Time.time/changeInterval;
    index = index % imageCount;
    var fileName : String = imageNameBase + ZeroPad(index,imageNameZeroPadding);
    Resources.UnloadAsset(texture);
    texture = Resources.Load(fileName);
    renderer.material.mainTexture = texture;


    if ( index == imageCount-1){
        Debug.Log("End of Animation");
        Debug.LogWarning("End of Animation");
        if( isLooping == false){
            isRunning = false;
        }
        fileName = imageNameBase + ZeroPad(0,imageNameZeroPadding);
        Resources.UnloadAsset(texture);
        texture = Resources.Load(fileName);
        renderer.material.mainTexture = texture;
    }
}

function ZeroPad(number : int, size : int) {
    var numberString : String = number.ToString();
    while (numberString.Length < size) numberString = "0" + numberString;
    return numberString;
}
like image 643
Jason George Avatar asked Apr 04 '13 20:04

Jason George


People also ask

How do I use an image as a texture Unity?

You can also use an image or texture as a material. Prepare an image of your choice and add it to the Project window. Create a material file and open the Inspector window. Drag and drop an image onto the square to the left of Albedo to make it a material.

Can you import PNG into Unity?

Get a standard image file such as a PNG or JPG that you want to use, save it, and then drag the image into the Assets region of Unity. Next, drag the image from the Assets into the Scene Hierarchy.


2 Answers

In C#:

// Load all textures into an array
Object[] textures = Resources.LoadAll("Textures", typeof(Texture2D));

// Load a single texture
Texture2D texture = Resources.Load("Texture") as Texture2D;

renderer.material.mainTexture = texture;

Hope it helps. You should be able to convert it into JS no problem. Just look at the Unity documentation.

http://docs.unity3d.com/Documentation/ScriptReference/Resources.html

like image 113
Nestor Ledon Avatar answered Oct 19 '22 08:10

Nestor Ledon


I achieved the same thing by placing any sequence of .png images (with an alpha channel) in a folder Resources/Sequence1 inside the main Assets folder. The output is a seamless movie playing with transparency exactly according to the alpha channels of the images.

This code is applied to a plane which is assigned a default New Material with Transparent/Diffused shader. This shader supports PNG images with alpha as transparency. You just have to give the name of the folder which contains the images to the variable framespath.

#pragma strict

var framespath: String = "";
var vidframes: Object[];
var count: int;

function Start () {

    vidframes = Resources.LoadAll(framespath, Texture);
    Debug.Log(vidframes.Length);

    count = 0;
    renderer.material.mainTexture = vidframes[count];
}

function Update () {
    count++;
    renderer.material.mainTexture = vidframes[count];
    if (count == vidframes.Length-1)
    {
        count = 0;
    }
}
like image 22
user3004240 Avatar answered Oct 19 '22 09:10

user3004240