Search Unity

Help managing memory

Discussion in '2D' started by fosmark13, Oct 3, 2018.

  1. fosmark13

    fosmark13

    Joined:
    Feb 16, 2015
    Posts:
    91
    hi everyone!
    i already have my game finished and i'm porting it to portable game machines(3ds, vita) i just have a big level made with 2d sprites in all the devices the first level is not even shown, i guess i because there are just too many sprites loaded even if their resolution is something like 512 * 512 in ps vita, i now the ps vita and 3ds have limited memory, so i developed this script to calculate the distance between the player and each texture so if the player is far enough the texture will be unload and if he is closer then it will be loaded again, so this way when the scene is loaded only a few textures will be loaded as well. Please if somebody can see the script and guide me for a better road to accomplish something like this.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityEngine.SceneManagement;
    6.  
    7. public class textureEnabler : MonoBehaviour {
    8.     Transform playerTarget;
    9.     public float distance;
    10.     public Sprite imageToLoad;
    11.     public float renderDistance;
    12.     public string levelTexture;
    13.     public bool assetLoaded = false;
    14.     private SpriteRenderer spriteRendererOnGameObject;
    15.     // Use this for initialization
    16.     void Start () {
    17.         spriteRendererOnGameObject = GetComponent<SpriteRenderer>();
    18.         spriteRendererOnGameObject.sprite = null;
    19.         playerTarget = GameObject.FindGameObjectWithTag("Player").transform;
    20.     }
    21.  
    22.     // Update is called once per frame
    23.     void Update () {
    24.         distance = Vector3.Distance(transform.position, playerTarget.transform.position);
    25.  
    26.             if (Mathf.Abs(playerTarget.position.x - transform.position.x) < renderDistance && !assetLoaded)
    27.             {
    28.                 LoadAsset(levelTexture);
    29.             }
    30.  
    31.             if (Mathf.Abs(playerTarget.position.x - transform.position.x) > renderDistance && assetLoaded){
    32.                 UnLoadAsset(levelTexture);
    33.             }
    34.     }
    35.  
    36.     void LoadAsset(string textureToLoad)
    37.     {
    38.                 var imageOnResources = Resources.Load<Sprite>("levels/level1/actionZone/" + textureToLoad);
    39.                 spriteRendererOnGameObject.sprite = imageOnResources;
    40.                 Debug.Log("Asset loaded");
    41.                 assetLoaded = true;
    42.     }
    43.  
    44.     void UnLoadAsset(string textureToUnload) {
    45.                Resources.UnloadAsset(imageToLoad);
    46.                 spriteRendererOnGameObject.sprite = null;
    47.                 Debug.Log("Asset unloaded");
    48.                 assetLoaded = false;
    49.     }
    50.  
    51. }
    52.  
     

    Attached Files:

  2. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,618
    I would not use Resources.Load, as it will most likely introduce frame-rate hiccups. If you really have to use the Resources API, better use asynchronous API calls:
    https://docs.unity3d.com/ScriptReference/Resources.LoadAsync.html
    ... but even this often causes some hiccup issues. Loading content in Unity smoothly is a real challenge.

    By the way, Unity Technologies themselves recommend against using the Resources API in most cases:
    https://unity3d.com/learn/tutorials/topics/best-practices/resources-folder

    Perhaps a better way would be to use the new Texture Mipmap Streaming feature found in Unity 2018.2 and newer:
    https://docs.google.com/document/d/1P3OUoQ_y6Iu9vKcI5B3Vs2kWhQYSXe02h6YrkDcEpGM/edit

    I haven't used this myself yet, but I believe or hope it won't cause the usual frame-rate hiccups that pretty much every other Unity content loading call is causing.

    The idea would be that you load only higher mip-maps into memory, that are near the visible camera view. Basically what you tried starting to write yourself.
     
  3. fosmark13

    fosmark13

    Joined:
    Feb 16, 2015
    Posts:
    91
    I would try to do use that new feature but a can't update to unity 2018 'cause portable consoles don't support it, i'm stuck in unity 2017 and 5.6, do you now a method to make the scene(in this case level1) not load all the objects in scene? only one part of the scene, maybe this way i can manage memory better
     
  4. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,618
    I don't think this is supported.

    However, you could split the level in several smaller scenes and load/unload these. This could be an automated process before the build, where you take your actual level and generate many smaller scenes from it, which are then used in the build.

    Playdead streams scenes in their game INSIDE. However, this probably also causes hiccups, since there is no load method to my knowledge that is super smooth in vanilla Unity, at least in older versions.

    Here is the talk where Playdead explain how they achieved stutter free loading at 60fps in Unity (spoiler: they modified Unity source code to do that).