Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Resources.Load Returns Wrong Texture

Discussion in 'Scripting' started by kingsapo, Jun 27, 2016.

  1. kingsapo

    kingsapo

    Joined:
    Sep 6, 2013
    Posts:
    8
    Hello all! I'm having some trouble loading textures from the Resources folder. I'm trying to make a substitute for the built-in Movie Texture, which is bad on performance on anything above 480p video. My idea (as many have had before) is to convert the movie to an image sequence, and swap the frames every fraction of a second based on the framerate. This works very well with a small video, but once I dump a large number of frames (around 6000+) into the Resources folder, the script will load textures at seemingly random points in the video. The filename and path are correct, but it loads a completely different texture, causing the video to randomly stutter around.

    It seems like this may be a limitation of the Resources folder, but I haven't found any documentation to suggest that. It could also be a bug in Unity, so I'm curious if anyone has experienced something like this, or if there's something obvious that I'm doing wrong? I've attached the script used for texture swapping if anyone wants to see it. Thank you for any help you can offer.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class PlayVideoImageSequenceRuntimeLoad : MonoBehaviour {
    5.    
    6.     public string folderName = "Videos";    // folder name which contains all the frames
    7.     public string fileName = "VidTex";        // base file name without any trailing digits
    8.     public string digitsFormat = "0000";    // format the the digits in each frame file name
    9.     public float framesPerSecond = 24.0f;    // set this to the framerate of the original video
    10.     public Material material;                // material to update the texture onto
    11.     public int materialIndex;                // material index for the material to update the material onto (asuming multiple materials on mesh)
    12.     public bool emissive = true;            // if true, new textures will be set to emissive texture on material, otherwise diffuse will be used
    13.  
    14.     private Renderer goRenderer;            // the Renderer on this object
    15.     public int lastFrameIndex = 0;            // index of the last frame displayed
    16.     public int currentFrameIndex = 0;        // index of the current frame being displayed
    17.     public int startFrame = 0;                // first frame in the animation
    18.     public int numberOfFrames = 0;            // number of frames to display
    19.  
    20.     public Texture currentFrameTexture;        // current frame texture being shown
    21.     public string currentFrameString;        // just the digits part of the current frame file name
    22.     public string currentFramePath;            // the whole file name for the current frame
    23.     public string currentFramePathFull;        // the whole file name for the current frame, including the path relative to the Resources folder
    24.     public float currentFrameTime;            // amount of the the current frame has been shown
    25.  
    26.     void Start () {
    27.         goRenderer = GetComponent<Renderer>();
    28.  
    29.         if (material == null) {
    30.             Debug.LogError ("PlayVideoImageSequence: No material found!");
    31.         } else {
    32.             // give the renderer an instance of our material, then set us to use that instance instead of the original
    33.             goRenderer.materials[materialIndex] = new Material(material);
    34.             material = goRenderer.materials[materialIndex];
    35.         }
    36.  
    37.         currentFrameIndex = startFrame;
    38.     }
    39.  
    40.     void Update () {
    41.         // increase/decrease the framerate at runtime for debug purposes
    42.         if (Input.GetKeyUp (KeyCode.Plus) || Input.GetKeyUp (KeyCode.KeypadPlus)) {
    43.             framesPerSecond += 1;
    44.         } else if (Input.GetKeyUp (KeyCode.Minus) || Input.GetKeyUp (KeyCode.KeypadMinus)) {
    45.             framesPerSecond = Mathf.Max (framesPerSecond - 1, 0);
    46.         }
    47.  
    48.  
    49.         // increment the current frame time, and if we are finished showing the current frame, increment the index
    50.         currentFrameTime += Time.deltaTime;
    51.         if (currentFrameTime >= 1.0f / framesPerSecond) {
    52.             currentFrameTime = 0.0f;
    53.             currentFrameIndex += 1;
    54.  
    55.             // reset back to start frame if we go over the max frame
    56.             if (currentFrameIndex >= startFrame + numberOfFrames) {
    57.                 currentFrameIndex = startFrame;
    58.             }
    59.         }
    60.  
    61.         // if the frame has changed...
    62.         if (currentFrameIndex != lastFrameIndex) {
    63.             lastFrameIndex = currentFrameIndex;
    64.  
    65.             // figure out the path to the new texture we want to load (relative to Resources folder)
    66.             currentFrameString = string.Format("{0:" + digitsFormat + "}", currentFrameIndex);
    67.             currentFramePath = fileName + currentFrameString;
    68.             currentFramePathFull = folderName + "/" + currentFramePath;
    69.  
    70.             // load the new texture
    71.             currentFrameTexture = Resources.Load(currentFramePathFull) as Texture2D;
    72.  
    73.             // unload the previous texture
    74.             Resources.UnloadUnusedAssets();
    75.  
    76.             // set the new texture based on if we are using emissive or not
    77.             if (emissive) {
    78.                 material.SetTexture("_EmissionMap", currentFrameTexture);
    79.  
    80.                 // update the dynamic GI for the new emission values from the new texture
    81.                 DynamicGI.UpdateMaterials(goRenderer);
    82.             } else {
    83.                 material.SetTexture("_MainTex", currentFrameTexture);
    84.             }
    85.         }
    86.     }
    87. }
    88.  
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    I don't see how this could be any better on performance...
     
  3. kingsapo

    kingsapo

    Joined:
    Sep 6, 2013
    Posts:
    8
    I know it seems counter-intuitive, but the performance really is better than a Movie Texture, especially for HD video. (thanks for the quick response too!)
     
  4. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    And you're not at all worried about loading 6000 HD textures into memory?
     
  5. kingsapo

    kingsapo

    Joined:
    Sep 6, 2013
    Posts:
    8
    Not if I do it at runtime. There is a version of this that loads all textures at once, and while that does run on some high-end systems it takes forever to load, and like you're saying most systems would run out of memory. My idea is to load each one as it's needed, then delete the old one once it's done and load the new one. Performance really isn't an issue, it's just this Resources.Load loading the wrong texture.