Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

unity 2.6 background loading of new scenes and assets

Discussion in 'Editor & General Support' started by alanis, Nov 2, 2009.

  1. alanis

    alanis

    Joined:
    Mar 4, 2009
    Posts:
    99
    hello guys, got a quick question:

    with the new 2.6 version the backgorund loading of new scenes and assets.

    will this mean we will be able to use it as seamless terrain loading?

    like for instance, create multiple terrain blocks in the same scene and or multiple scenes have them load in the background while walkign thru and create a very large worlds?


    if so what will be the best approach to it. an exmaple will be great if possible.


    thanks again, looking forward to this feature.
     
  2. jonas-echterhoff

    jonas-echterhoff

    Unity Technologies

    Joined:
    Aug 18, 2005
    Posts:
    1,666
  3. alanis

    alanis

    Joined:
    Mar 4, 2009
    Posts:
    99
    thanks jonas,

    I will definately take a look at it.

    will post comments in a a couple of hours.

    thank you.
     
  4. jonas-echterhoff

    jonas-echterhoff

    Unity Technologies

    Joined:
    Aug 18, 2005
    Posts:
    1,666
    Oh, and, as I forgot to mention above, we are of course working on better demo materials for these new features, so stay tuned (and check out the provided link in the meanwhile).
     
  5. alanis

    alanis

    Joined:
    Mar 4, 2009
    Posts:
    99
    thanks jonas,

    I have downloaded the demo, but for some reason when I load the project and click on play it throws me and error:

    Assets/Plugins/ZoneLoader.cs(130,17): error CS0246: The type or namespace name `AsynchronousOperation' could not be found. Are you missing a using directive or an assembly reference?


    what is it supposed to do the demo? is it supposed to do a flyby the scenes seamslesly?

    I also tried the webplayer demo aswell, but is just shows a blue screen with my pc specs and fps, but thats it.

    am I missing something?

    i tested it on win xp platform


    thanks again
     
  6. Yann

    Yann

    Joined:
    Oct 20, 2007
    Posts:
    432
    Same behaviour on a Mac.
     
  7. jonas-echterhoff

    jonas-echterhoff

    Unity Technologies

    Joined:
    Aug 18, 2005
    Posts:
    1,666
    Apparently, we renamed some of the APIs shortly before releasing. AsynchronousOperation was renamed to AsyncOperation (to make the name consistent with "LoadLevelAsync"). Maybe there are more, if you get more compiler errors, check the script documentation.
     
  8. alanis

    alanis

    Joined:
    Mar 4, 2009
    Posts:
    99
    ahh, ok, thanks,

    got that part fixed by replacing

    line 130 of ZoneLoader.cs

    AsynchronousOperation async = Application.LoadLevelAdditiveAsynchronous(levelName);

    for:
    AsyncOperation async = Application.LoadLevelAdditiveAsync(levelName);

    so that part is fixed, now I can click on play and it now lets me walktru the island,

    but there are more compiling erros as I am moving from end to end of the island to see how the other scenes load.

    Asynchronous Background loading is only supported in Unity Pro.
    Please use Application.LoadLevel or Application.LoadLevelAdditive instead.
    UnityEngine.Application:LoadLevelAsync(String, Int32, Boolean)
    UnityEngine.Application:LoadLevelAsync(String, Int32, Boolean)
    UnityEngine.Application:LoadLevelAdditiveAsync(String)
    <>c__CompilerGenerated0:MoveNext() (at Assets\Plugins\ZoneLoader.cs:130)

    [..\..\Runtime\Misc\PreloadManager.cpp line 450]




    Map_1-0 could not be found after loading level
    UnityEngine.Debug:LogError(Object)
    <>c__CompilerGenerated0:MoveNext() (at Assets\Plugins\ZoneLoader.cs:148)



    The asset bundle 'file:// + C:/unity3d/StreamingWorldDemo/Assets/../builds/AssetBundles/Map_1-0.unity3d' can't be loaded because another asset bundle with the same files are already loaded
    UnityEngine.WWW:get_assetBundle()
    UnityEngine.WWW:get_assetBundle()
    <>c__CompilerGenerated0:MoveNext() (at Assets\Plugins\ZoneLoader.cs:118)

    [..\..\Runtime\Export\Generated\Utils.cpp line 270]

    I will look at the script recerence to see if I can get this fixed.

    thanks
     
  9. alanis

    alanis

    Joined:
    Mar 4, 2009
    Posts:
    99
    well, I tried like the compiler suggested:
    use Application.LoadLevel or Application.LoadLevelAdditive instead

    but I get even more erors than like stated on previous post:

    C:/unity3d/StreamingWorldDemo/Assets/../builds/AssetBundles/Map_1-0.unity3d' can't be loaded because another asset bundle with the same files are already loaded
    UnityEngine.WWW:get_assetBundle()
    UnityEngine.WWW:get_assetBundle()
    <>c__CompilerGenerated0:MoveNext() (at Assets\Plugins\ZoneLoader.cs:118)

    [..\..\Runtime\Export\Generated\Utils.cpp line 270]




    the "can not be loaded because another asset bundle with the same files are already loaded"
    is this also because of unity pro requirement? or is indeed a 2.6 bug?


    So I guess this streaming background loading is only a unity pro feature, right? is this correct?.
     
  10. jonas-echterhoff

    jonas-echterhoff

    Unity Technologies

    Joined:
    Aug 18, 2005
    Posts:
    1,666
    Well, that error is self-explaining. You cannot use the new Async loading feature in normal Unity, you need Unity Pro to use it.
     
  11. alanis

    alanis

    Joined:
    Mar 4, 2009
    Posts:
    99
    :cry:

    so that means that regular unity version wont support seamless terrain or background loading feature?

    or is there a work around for it without using the Asynchronous?


    thanks
     
  12. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    Well you can just put all into the scene.
    Because AssetBundles are a Pro only feature, so even if you do the loading through loadadditive, you won't be able to use AssetBundles
     
  13. jonas-echterhoff

    jonas-echterhoff

    Unity Technologies

    Joined:
    Aug 18, 2005
    Posts:
    1,666
    Well, you could always use the non-Async version of the LoadLevelAdditive API, but that won't give you smooth background loading, you'll have to wait a second or two for new content to load.

    In real life, I don't think this makes a big difference for free Unity users: You can create fairly big worlds containing multiple terrains, and load them as single levels. When you reach the point where your world requires continuous streaming, you are likely no longer in the domain of Indie users anyways - with such a big world, you'll probably want a team of developers (which requires money), and some versioning system to create it (which requires Pro).
     
  14. alanis

    alanis

    Joined:
    Mar 4, 2009
    Posts:
    99
    thanks guys,

    yes indeed the LoadLevelAdditive works fine for non pro version,
    I was testin git out with this same demo by replacing:

    AsyncOperation async = Application.LoadLevelAdditiveAsync(levelName);


    for
    Application.LoadLevelAdditive(levelName);


    so i noticed the terrain blocks load up on walking thru the edges from current terrain.


    but, here is a question:

    I see in the editor while on play mode when I walk thru the 1st terrain block, only that block is loaded on my my hierarchy tree, so I walk thru one of the ends and I see the new terrain block loads fine, so my question is:

    How would I destroy the previous terrain block I left behind?

    because if I use LoadLevel alone by itself I can not see anything on my starting screen, it loads the fist terrain but after 1 sec it gets destroyed and leaves me on a grey screen, so i had to use LoadLevelAdditive., but this one just keeps on adding the rerrain block sas I advance and they get accumulated.

    you know what I mean, so as I walk thru the next terrain block, I would like to get the previous destryed, and if I wan tto go back get the destroyed load up again and destroy the current.


    thanks
     
  15. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    Code (csharp):
    1. destroy( the previous terrain block I left behind);
    ;-)
     
  16. alanis

    alanis

    Joined:
    Mar 4, 2009
    Posts:
    99
    Hi Dreamora,

    thank you, I tried to use the destroy function but I guess I am doing it wrong, if you look at the code for the scrript zoneloader.cs below,

    on line 130
    where it states the level load:

    // Load Level
    Application.LoadLevelAdditive(levelName);


    right below this is where I used the destroy

    Destroy (gameObject); as per scritp reference guide

    function but It looks like it destroys all current loads , it just leaves me in one 1 block which is the startup terrain block.


    any suggestions?


    thank you for your help


    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System;
    4.  
    5. using Object = UnityEngine.Object;
    6.  
    7. public class ZoneLoader : MonoBehaviour
    8. {
    9.     const float   m_LoadDistance = 1500.0F;
    10.     const float   m_UnloadDistance = 2500.0F;
    11.     public const float m_GridSize = 2000.0F;
    12.     public const int m_ZoneCount = 6;
    13.  
    14.     static public ZoneLoader    ms_Singleton;
    15.  
    16.     static ZoneLoader singleton
    17.     {
    18.     get
    19.     {  
    20.         // @TODO: use FindObjectsOfType to implement improved hotloading of scripts
    21.         if (ms_Singleton == null)  
    22.         {
    23.             GameObject go = new GameObject ("ZoneLoader", typeof(ZoneLoader));
    24.             ms_Singleton = go.GetComponent(typeof(ZoneLoader)) as ZoneLoader;
    25.         }
    26.         return ms_Singleton;
    27.     }
    28.     }
    29.  
    30.     bool          m_IsLoading = false;
    31.     bool          m_IsUnloading = false;
    32.     bool          m_UseWWW = true;
    33.     bool          m_UseWWWCaching = false;
    34.     int           m_CacheVersion = 1;
    35.    
    36.     Vector3       m_PlayerPosition;
    37.     Transform     m_PlayerTransform;
    38.    
    39.     static int    m_ZonesUnloadedSinceLastAssetUnload = 0;
    40.    
    41.     [System.Serializable]
    42.     public class Zone
    43.     {
    44.         public bool m_Loaded = false;
    45.         public bool m_IsLoadable = true;
    46.         public GameObject m_Root;
    47.         public Terrain m_Terrain;
    48.  
    49.         public AssetBundle  m_ZoneBundle;
    50.         public WWW  m_ZoneDownload;
    51.     }
    52.    
    53.     static string GetBaseUrl ()
    54.     {
    55.         if (Application.platform == RuntimePlatform.OSXEditor || Application.platform == RuntimePlatform.WindowsEditor)
    56.             return "file:// + " + Application.dataPath + "/../builds/AssetBundles/";
    57.         if (Application.platform == RuntimePlatform.OSXPlayer)
    58.             return "file:// + " + Application.dataPath + "/../../AssetBundles/";
    59.         else
    60.             return "AssetBundles/";
    61.     }
    62.    
    63.  
    64.     Zone[] m_Zones = new Zone[m_ZoneCount * m_ZoneCount];
    65.    
    66.    
    67.     static public string GetPrefix (string prefix, string postfix, int x, int y)
    68.     {
    69.         return string.Format("{0}{1}-{2}{3}", prefix, x, y, postfix);
    70.     }
    71.  
    72.     static public string GetPrefix (int x, int y)
    73.     {
    74.         return GetPrefix("Map_", "", x, y);
    75.     }
    76.  
    77.     IEnumerator LoadZone (int x, int y)
    78.     {
    79.         ////@TODO: if (!Application.CanStreamedLevelBeLoaded (GetPrefix(x, y)))
    80.        
    81.         if (m_IsLoading)
    82.         {
    83.             Debug.LogError("Already loading zone");
    84.             yield break;
    85.         }
    86.  
    87.         Zone zone = m_Zones[m_ZoneCount*y + x];
    88.  
    89.         // Zone cant be loaded
    90.         if (!zone.m_IsLoadable)
    91.             yield break;
    92.        
    93.         m_IsLoading = true;
    94.        
    95.         string levelName = GetPrefix(x, y);
    96.        
    97.         if (m_UseWWWCaching || m_UseWWW)
    98.         {
    99.             string fullUrl = GetBaseUrl() + levelName + ".unity3d";
    100.             if (m_UseWWWCaching)
    101.                 zone.m_ZoneDownload = [url]WWW.LoadFromCacheOrDownload[/url] (fullUrl, m_CacheVersion);
    102.             else
    103.                 zone.m_ZoneDownload = new WWW (fullUrl);
    104.             yield return zone.m_ZoneDownload;
    105.            
    106.             // Make sure there were no errors in the download
    107.             if (zone.m_ZoneDownload.error != null)
    108.             {
    109.                 Debug.LogError(zone.m_ZoneDownload.error);
    110.                 zone.m_IsLoadable = false;
    111.                 m_IsLoading = false;
    112.                 zone.m_ZoneDownload.Dispose();
    113.                 zone.m_ZoneDownload = null;
    114.                 yield break;
    115.             }
    116.            
    117.             // Load the scene so it becomes accessable from Application.LoadLevel
    118.             zone.m_ZoneBundle = zone.m_ZoneDownload.assetBundle;
    119.             zone.m_ZoneDownload.Dispose();
    120.             zone.m_ZoneDownload = null;
    121.             if (zone.m_ZoneBundle == null)
    122.             {
    123.                 zone.m_IsLoadable = false;
    124.                 m_IsLoading = false;
    125.                 yield break;
    126.             }
    127.         }
    128.  
    129.         // Load Level
    130.         Application.LoadLevelAdditive(levelName);
    131.          
    132.  
    133.  
    134.  
    135.        
    136.        
    137.  
    138.         // Necessary to prevent overwriting of another load level additive following immediately
    139.         // yield return 0;
    140.  
    141.         // Find the root game object containing the level data
    142.         zone.m_Root = GameObject.Find("/" + levelName);
    143.         if (zone.m_Root != null)
    144.         {
    145.             Transform terain = zone.m_Root.transform.Find("Terrain");
    146.             if (terain)
    147.                 zone.m_Terrain = terain.GetComponent(typeof(Terrain)) as Terrain;
    148.  
    149.             zone.m_Loaded = true;
    150.         }
    151.         else
    152.         {
    153.             Debug.LogError(levelName + " could not be found after loading level"); 
    154.         }
    155.  
    156.         // Hookup neighboring terrains so there are no seams in the LOD
    157.         for (int yi=Mathf.Max(y-1, 0);yi<Mathf.Min(y+2, m_ZoneCount);yi++)
    158.         {
    159.             for (int xi=Mathf.Max(x-1, 0);xi<Mathf.Min(x+2, m_ZoneCount);xi++)
    160.             {
    161.                 Terrain curTerrain = GetLoadedTerrain(xi, yi);
    162.                 if (curTerrain != null)
    163.                 {
    164.                     Terrain left = GetLoadedTerrain(xi-1, yi);
    165.                     Terrain right = GetLoadedTerrain(xi+1, yi);
    166.                     Terrain top = GetLoadedTerrain(xi, yi+1);
    167.                     Terrain bottom = GetLoadedTerrain(xi, yi-1);
    168.                     curTerrain.SetNeighbors (left, top, right, bottom);
    169.                 }
    170.             }
    171.         }
    172.        
    173.         m_IsLoading = false;
    174.     }
    175.    
    176.     IEnumerator UnloadZone (int x, int y)
    177.     {
    178.         m_IsUnloading = true;
    179.        
    180.         Zone zone = m_Zones[m_ZoneCount*y + x];
    181.         zone.m_Loaded = false;
    182.        
    183.         if (zone.m_Root)
    184.             Destroy(zone.m_Root);
    185.         else
    186.             Debug.LogError("Root for zone has already been unloaded:" + GetPrefix(x, y));
    187.        
    188.         zone.m_Terrain = null;
    189.         zone.m_Root = null;
    190.        
    191.         yield return 0;
    192.  
    193.         if (m_UseWWWCaching || m_UseWWW)
    194.         {
    195.             zone.m_ZoneBundle.Unload(true);
    196.             zone.m_ZoneBundle = null;
    197.         }
    198.        
    199.         m_ZonesUnloadedSinceLastAssetUnload++;
    200.        
    201.         m_IsUnloading = false;
    202.     }
    203.    
    204.     /// Unload assets at some points
    205.     /// AsynchronousOperation op = Resources.GarbageCollectAssets(-1);
    206.    
    207.     void OnEnable ()
    208.     {
    209.         ms_Singleton = this;   
    210.     }
    211.    
    212.     void Awake ()
    213.     {
    214.         ms_Singleton = this;
    215.         m_Zones = new Zone[m_ZoneCount * m_ZoneCount];
    216.         for (int i=0;i<m_Zones.Length;i++)
    217.         {
    218.             m_Zones[i] = new Zone();
    219.         }
    220.        
    221.         if (m_UseWWWCaching)
    222.         {
    223.             ///////@TODO: REMOVE THIS
    224.             Caching.Authorize ("test", "", 1024*1024*1000, "");
    225.             Caching.CleanCache();
    226.         }
    227.        
    228.         // Precompute which dongs are loadable
    229.         /*
    230.         for (int y=0;y<m_DongCount;y++)
    231.         {
    232.             for (int x=0;x<m_DongCount;x++)
    233.             {
    234.                 Dong dong = m_Dongs[m_DongCount*y + x];
    235.                 dong.m_IsLoadable = CachingManifest.singleton.HasDongInZoneType(x, y, ms_ZoneType);
    236.             }
    237.         }
    238.         */
    239.        
    240.         ms_Singleton = this;
    241.     }
    242.    
    243.     float GetSqrDistance (Vector3 position, int x, int y)
    244.     {
    245.         float minx = x * m_GridSize;
    246.         float maxx = (x+1) * m_GridSize;
    247.         float miny = y * m_GridSize;
    248.         float maxy = (y+1) * m_GridSize;
    249.        
    250.         float xDistance = 0.0F;
    251.         float yDistance = 0.0F;
    252.        
    253.         if (position.x < minx)
    254.             xDistance = Mathf.Abs(minx - position.x);
    255.         else if  (position.x > maxx)
    256.             xDistance = Mathf.Abs(maxx - position.x);
    257.  
    258.         if (position.z < miny)
    259.             yDistance = Mathf.Abs(miny - position.z);
    260.         else if (position.z > maxy)
    261.             yDistance = Mathf.Abs(maxy - position.z);
    262.  
    263.         return xDistance * xDistance + yDistance * yDistance;      
    264.     }
    265.  
    266.     public static void SetPosition (Vector3 position)
    267.     {
    268.         singleton.m_PlayerPosition = position;
    269.     }
    270.  
    271.     public static void SetPlayerTransform (Transform player)
    272.     {
    273.         singleton.m_PlayerTransform = player;
    274.     }
    275.  
    276.     void GetClosestZone (Vector3 position, float closestDistance, out int closestX, out int closestY)
    277.     {
    278.         closestX = -1;
    279.         closestY = -1;
    280.         closestDistance = closestDistance * closestDistance;
    281.         for (int y=0;y<m_ZoneCount;y++)
    282.         {
    283.             for (int x=0;x<m_ZoneCount;x++)
    284.             {
    285.                 Zone zone = m_Zones[m_ZoneCount*y + x];
    286.                 if (!zone.m_Loaded  zone.m_IsLoadable)
    287.                 {
    288.                     float sqrDistance = GetSqrDistance(position, x, y);
    289.                     if (sqrDistance < closestDistance)
    290.                     {
    291.                         closestDistance = sqrDistance;
    292.                         closestX = x;
    293.                         closestY = y;
    294.                     }
    295.                 }
    296.             }
    297.         }
    298.     }
    299.  
    300.  
    301.     void Update ()
    302.     {
    303.         if (m_PlayerTransform)
    304.             m_PlayerPosition = m_PlayerTransform.position;
    305.        
    306.         if (m_IsLoading || m_IsUnloading)
    307.             return;
    308.        
    309.         // Unload any zone that is far enough away
    310.         for (int y=0;y<m_ZoneCount;y++)
    311.         {
    312.             for (int x=0;x<m_ZoneCount;x++)
    313.             {
    314.                 Zone zone = m_Zones[m_ZoneCount*y + x];
    315.                 if (zone.m_Loaded)
    316.                 {
    317.                     float sqrDistance = GetSqrDistance(m_PlayerPosition, x, y);
    318.                     if (sqrDistance > m_UnloadDistance * m_UnloadDistance)
    319.                     {
    320.                         StartCoroutine(UnloadZone(x, y));
    321.                         return;
    322.                     }
    323.                 }
    324.             }
    325.         }
    326.        
    327.         // Try loading the closest zone
    328.         int closestX, closestY;
    329.         GetClosestZone(m_PlayerPosition, m_LoadDistance, out closestX, out closestY);
    330.  
    331.         if (closestX != -1)
    332.             StartCoroutine(LoadZone (closestX, closestY));
    333.     }
    334.    
    335.     Terrain GetLoadedTerrain (int x, int y)
    336.     {
    337.         if ((x >= 0  x < m_ZoneCount)  (y >= 0  y < m_ZoneCount))
    338.         {
    339.             Zone zone = m_Zones[m_ZoneCount*y + x];
    340.             if (zone.m_Loaded)
    341.                 return zone.m_Terrain;
    342.         }
    343.        
    344.         return null;
    345.     }
    346.    
    347. }
    348.  




    EDIT:

    if you notice the variables at the beguining of the script some work and some dont in the none pro verion:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using System;
    5.  
    6. using Object = UnityEngine.Object;
    7.  
    8. public class ZoneLoader : MonoBehaviour
    9. {
    10.    const float   m_LoadDistance = 1500.0F;
    11.    const float   m_UnloadDistance = 2500.0F;
    12.    public const float m_GridSize = 2000.0F;
    13.    public const int m_ZoneCount = 6;
    14.  

    adjusting the m_LoadDistance = 1500.0F;

    to less if will load only 1 block as I am aproaching to next block, so I tried adjusting the m_UnloadDistance = 2500.0F;

    to like 500 or less and it doesnt seems to make any diference. maybe because of the script was designed to be used with pro version.

    so I was looking to add the destroy function instead to unload the left behind terrain blocks
     
  17. kork

    kork

    Joined:
    Jul 14, 2009
    Posts:
    280
    I just downloaded the sample and checked out the code that is actually dividing the big terrain into several scenes (GenerateScenes.cs). I fail to see where the actual dividing process is taking place. From what I see in the code, the unity island terrain is just duplicated into 16 scenes. I am sure I am missing something here, so can someone enlighten me on how the terrain division process actually works? Thanks so much :)
     
  18. minevr

    minevr

    Joined:
    Mar 4, 2008
    Posts:
    1,018
    Downloading.....

    Thanks for share~ :D