Search Unity

ULS : Universal Level of Detail system

Discussion in 'Assets and Asset Store' started by unity3dx, May 4, 2011.

  1. unity3dx

    unity3dx

    Joined:
    Apr 15, 2011
    Posts:
    175
    RELEASED:
    Pro version: http://www.unity3dx.com/index.php/products/uls-pro/
    Free version: http://www.unity3dx.com/index.php/products/uls-free/

    The idea was to make a LOD system that is blazing fast, uses almost no CPU, and can be used on any type of GameObjects.

    While I was doing a forest pack (not finished yet) I came with the idea that in order to have something that is working smoothly on iPhone and is taking as low CPU as possible, I should not have a main manager that calls all the LOD objects, but rather have each object that are like a little robot managing its own LOD.

    You need to create a special GameObject that will includes all the different LOD. Each LOD can be any kind of prefab. In the example of the video, the 1st LOD is a prefab with a rounded box of 500 polys, a spotlight with flare, and it catches and receive shadows. The second LOD is a prefab that has no spotlight and caches shadows. The last one is a simple 86 polys box that has no shadow.

    Everything is possible and each LOD prefab can be anything. Buildings, trees, spaceships with projectors and lights... anything.

    Each Object is prepared by an Editor Script. The editor script will set some variable, like the number of frame the object will check itself, add the necessary scripts, the distances for each LOD, and eventually the wind, or any specifc value. After that, each object is independent and is taking care of itself. The manager can instantiate or erase the LOD pre-generated. Once done you can save your project and all the LOD clones can be moved, and arranged the way you want. When you run the program, each clone will act by itself and optimize its display. The result is really fast even on iPAD 1.



    In this video an equivalent to 20 Millions poly are displayed, 37500 objects, each with the LOD script attached, around 4000 spotlights with flare, shadows, collision (you can see that the sun hides behind the cubes), the first LOD is a rounded cube of about 500 polys. I get more than 40 FPS (average 50 FPS) when I do not record the video.
    My setup is a Laptop with I7 720 CPU and Geforce GTX260M.
    The system is working on iPad/iPhone, I am working on another video specific to these platforms.
     

    Attached Files:

    • $2.png
      $2.png
      File size:
      1 MB
      Views:
      5,354
    Last edited: Jul 17, 2011
  2. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    Looks very nice :)
     
  3. jonbonazza

    jonbonazza

    Joined:
    Nov 6, 2010
    Posts:
    453
    Indeed... You have a potential customer. ;)
     
  4. artzfx

    artzfx

    Joined:
    Apr 28, 2008
    Posts:
    572
    Very nice work.
     
  5. MikeUpchat

    MikeUpchat

    Joined:
    Sep 24, 2010
    Posts:
    1,056
    I thought this almost exact system was about to be built into Unity, the Ninja Camp video showed it running, or was I mistaken?
     
  6. unity3dx

    unity3dx

    Joined:
    Apr 15, 2011
    Posts:
    175
    NO, it is not the Ninja Camp thing...I am quite sure that the LOD groups will not give you anything close to ULS, even if it is better than what we had before... Ninja Camp uses the common approach that is to have different mesh stored and a general manager that switch them depending on the distance from the camera.(tell me if I am wrong), also creating the groups seems a bit of a hassle.

    My LOD system is totally different.

    First, it uses Prefabs. LOD is not only about the number of polygons. Why would you have animated character at far distance? If you have a spaceship close with lights in the reactors, why the one far away would carry the light too? And do you need to have these far trees to have collision with anything?

    ULS allows you the ultimate flexibility to assign whatever you want to your prefabs and display them with LOD, not only the mesh.
    Also ULS do not run a manager that is checking the LOD of all the objects, but an editor script that scan all the LOD objects with the push of a button and will precalculate whatever each object needs to take care of itself, so that the LOD script that is attached to each object is doing almost nothing and is running really fast.

    My approach to the LOD optimization is to pre-calculate in the Editor all the LOD objects and give them a total autonomy.

    This has a lot of advantages:
    1- you do not have a spike when the LOD manager is running, each LOD object will check his status at a random interval precalculated by the editor script for you.
    2- there is no manager that 'blocks' the processing and make the iPhone/iPad exit like other LOD system. iPhone/iPad are sensitive to any slow down and if one function is taking too much time, Apple exit the Application. This cannot happen in any cases with ULS.
    3- Each LOD object is a prefab, that makes it easy to copy, make different versions to test the speed of this prefabs.
    4- ULS uses only prefabs as I said before, it is possible to ajust all retails, including multiple objects together, mix of flares, particles, shadows, collisions etc...
    5- ULS uses tags to manage the differents LOD object, for example grass would be "LODGRASS", trees "LODTREES" etc... this make easy to fold, erase, update, save in a prefab all the LOD object instantiated.
    6- ULS do not instantiate the objects at run time, but in the editor. Once instantiated, you can manipulate the LOD objects, erase, move, plants, etc... but at run time, the LOD objects are loading ready to run, no long and timely initialization is needed.

    I will soon release content packs ULS ready, that means that they can be instantiated with ULS and will manage their LOD by themselves. The first package will the 10 autumn forest trees.
     
    Last edited: May 5, 2011
  7. tarragon

    tarragon

    Joined:
    Dec 28, 2010
    Posts:
    38
    Splendid. How many lines is the code? How long did you spend developing and testing it.


    What you describe is pretty easy to do after some study and has been discussed with exactly this design on these very forums in the past. I am sure you read the very same articles on this forum we all did when designing lod scripts.

    By the way, i am using exactly this setup with prefabs and scripts that run themselves via coroutines that randomize themselves to avoid synchronization and try to do little heuristic to predict when the player moves to relevant boundaries.

    If you try to sell it, please go ahead, but include commented code with ample documentation, not Unity like mockumentation.
     
  8. Demostenes

    Demostenes

    Joined:
    Sep 10, 2010
    Posts:
    1,106
    Problem is, that such system should be in core from the beginning. Not let people to design it by themselves, because everybody have to do it again and again. But no, some manager decided, that stupid fancy effects like deph of field are bigger seller. For any Unity programmer, who knows how Unity works is such system piece of cake. And his one day of work will save thousands of work-days of other people. Everybody who made any game with unity probably have some LOD script of his own. Silly.
     
    Last edited: May 5, 2011
  9. tarragon

    tarragon

    Joined:
    Dec 28, 2010
    Posts:
    38
    /signed
     
  10. unity3dx

    unity3dx

    Joined:
    Apr 15, 2011
    Posts:
    175
    I did it for the Speed forest pack I will be releasing soon. I realized that it should be useful to make it not only for trees, so I have created an editor script to ease the LOD prefabs instantiation, and step by step here we are. Hard to say how much time, not much.
    About the line of code, the LOD script is really small. It should not be big, anyway everything is supposed to be precalculated by the editor. The LOD script just check where it is and what LOD it should be.

    I do not use coroutines. Nothing else than a one page LOD script is necessary to run for each prefab once they have been 'prepared' by the editor. It is a work I can compare to what I was doing with Atari long time ago. You try to pre-calculate everything so that at the execution time, each prefab runs 1 or 2 'if' no more. Then it is really fast. The only thing I cannot precalculate is the distance between the camera and the prefab, but I can spread this on several frames so that at the end the cost is nothing.

    I think the interest of this LOD system will be to be used with content packs I will release later. So that you do not have to work on the LOD, you just instantiate a prefab with ULS and that's it.
     
  11. immFX

    immFX

    Joined:
    Mar 20, 2010
    Posts:
    110
    Sorry, but I don't really understand what's the competitive advantage here.

    From what you say, it seems to me that you assign a scipt to each "LODed" prefab which activates/deactivates the relevant LOD object (and - I may add - could possibly enable/disable the other scripts running on this prefab, to gain some more processing cpu per frame) - all these based on distance from player/camera.

    Then you precalculate bake all distances to a (builtin?) array (for speed).

    And, unless this routine is spread to several frames, there is a cost of running all this for several gameobjects in the same frame.

    Is there something that I miss here?
     
    Last edited: May 6, 2011
  12. maart

    maart

    Joined:
    Aug 3, 2010
    Posts:
    82
    I would love to check this out. How far is this from beeing released.
    Could you upload a video of the workflow of your lod system?
    How much are you charging for this asset?
     
  13. unity3dx

    unity3dx

    Joined:
    Apr 15, 2011
    Posts:
    175
    It will be free and will be released next week.

    @immFx: you will see when it will be released, if you can optimize better let me know I will add your changes and credit you. I think this is the fastest way to do LOD and as well the most easy/convenient.
    But I can be wrong. I hope everyone will use it.
     
    Last edited: May 19, 2011
  14. Josh_Amsterdam

    Josh_Amsterdam

    Joined:
    Feb 22, 2011
    Posts:
    68
    Kudos for freely releasing it to the community! I will definitely check it out!
     
  15. Thunderent

    Thunderent

    Pocket Artist

    Joined:
    Oct 8, 2010
    Posts:
    435
    WoW!
    And it will be free?!
    I'm sure this will help me and the community a lot...thanks,unity3dx!
     
  16. Armillary

    Armillary

    Joined:
    Dec 16, 2009
    Posts:
    189
    This will be a big help for our project, thanks for sharing with the community.
     
  17. maart

    maart

    Joined:
    Aug 3, 2010
    Posts:
    82
    any news on this?
     
  18. nikko

    nikko

    Joined:
    Mar 20, 2009
    Posts:
    436
    Yep, almost ready, I was busy on Smart water for mobile. I should release it within 48h. I will post here when ready on http://unity3dx.com
     
  19. RandAlThor

    RandAlThor

    Joined:
    Dec 2, 2007
    Posts:
    1,293
    Any infos abot the release of your lod system?
     
  20. grfxman

    grfxman

    Joined:
    May 28, 2009
    Posts:
    309
    Has this been released yet?
     
  21. Spectre9000

    Spectre9000

    Joined:
    Aug 30, 2010
    Posts:
    170
    Seems to me all this is a simple script that goes about like...

    (Pseudocode)

    if(distanceSquard>X){Destroy.child; Instantiate(Prefab1);}
    if(distanceSquard>Y){Destroy.child; Instantiate(Prefab2);}
    if(distanceSquard>Z){Destroy.child; Instantiate(Prefab3);}

    Hell, you can make it an array of children and matching distances and put it all in a for loop and run it. Maybe I'm missing something complicated with this, but that's what I'm gathering he does for each and every object. Correct me if I'm wrong.
     
  22. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    If he would do that it would stutter like hell with destroy and instantiate all the time with that many cubes
     
  23. Spectre9000

    Spectre9000

    Joined:
    Aug 30, 2010
    Posts:
    170
    Probably better to use enable/disable more likely, however, he made it seem like he was creating and destroying prefabs dependent on distance.
     
  24. nikko

    nikko

    Joined:
    Mar 20, 2009
    Posts:
    436
    ULS has been released today : v1.0:

    Universal LOD System is an efficient and simple system to manage group of LOD gameobjects. The method used is designed to be as fast as possible. In consequence the time spent to manage the LOD is quasi negligible .

    ULM comes in 2 versions, the free version provide the basic scripts for you to use and some examples. The PRO version provide a simple editor that can easily adapted to your specific needs.

    What is happening when you run Unity.

    Each LOD GameObject will look at their position relatively to the camera, and will update themselves to show the correct LOD. There is no master loop. Each LOD object acts like a robot that decides by itself what it should show to the user.

    Free version: http://www.unity3dx.com/index.php/products/uls-free/
    Pro version ($25) : http://www.unity3dx.com/index.php/products/uls-pro/

    Any questions or issues, ticket: http://www.unity3dx.com/index.php/about/
     
  25. TiG

    TiG

    Joined:
    Feb 28, 2011
    Posts:
    311
    I did not even know that showing so many objects at one time was possible at all. Great work.
     
  26. unity3dx

    unity3dx

    Joined:
    Apr 15, 2011
    Posts:
    175
    Today I release the latest version of ULS PRO with added support for trees. I also release the new Speed Forest Expansion.

    - new update feature. Now you can move the LOD objects in the scene, or the Camera and the Update button will pre-caulculate all the LOD according to the new position.
    - support for Trees, with wind, random size and rotation etc…
    - bug fixes.

    ULS PRO can be found here : http://www.unity3dx.com/index.php/products/uls-pro/

    ULS EXP 1 : Speed Forest can be found here : http://www.unity3dx.com/index.php/products/uls-exp1/

    ULS free can be found here : http://www.unity3dx.com/index.php/products/uls-free/

     
    Last edited: Oct 1, 2011
  27. psyche

    psyche

    Joined:
    May 9, 2011
    Posts:
    10
    Hi everyone!

    I'm using the ULS and it works pretty well in my app, the only limitation, is that
    its only works on a single camera. I would like to use it on my current camera or on my main camera, so i can change camera as i want.
    I had read the reference script for camera.main and camera.current but not succeeded to make it works.
    Any help would be great!

    thanks.

    Here is the code from the ULS free version.

    Code (csharp):
    1.  
    2.  
    3. // *********************************************************************
    4. // Speed LOD manager, set for 5 LOD
    5. // (c) Nikko /Unity3dx.com
    6. // All Rights reserved
    7. // http://unity3dx.com
    8. //*********************************************************************
    9. // How to use: this script needs to be attached to the LOD prefab.
    10.  
    11. //@script ExecuteInEditMode
    12.  
    13.     private enum _Nikko_LOD_LEVEL { LOD0, LOD1, LOD2, LOD3, LOD4,LOD5}
    14.     public var nlod:int;
    15.     public var lodMesh0 : GameObject;
    16.     public var lodMesh1 : GameObject;
    17.     public var lodMesh2 : GameObject;      
    18.     public var lodMesh3 : GameObject;  
    19.     public var lodMesh4 : GameObject;  
    20.     public var mycam : Camera;
    21.     static var current : Camera;    
    22.     public var delaycounter:int;
    23.     public var distancehide:float;
    24.  
    25.     public var distanceLOD1 : float;
    26.     public var distanceLOD2 : float;      
    27.     public var distanceLOD3 : float;    
    28.     public var distanceLOD4 : float;    
    29.    
    30.     private var currentLOD : _Nikko_LOD_LEVEL= _Nikko_LOD_LEVEL.LOD4;  
    31.     private var counter:int;
    32.  
    33.     function getLODNbr()
    34.     {
    35.         return nlod;
    36.     }
    37.     function setLODNbr(v:int)
    38.     {
    39.         nlod=v;
    40.     }
    41.     function getComponentName()
    42.     {
    43.         return "Nikko_LODManager5";
    44.     }
    45.  
    46.  
    47. // Library to access internal values of the LOD manager.
    48.     function setLOD(l:int)
    49.     {
    50.         switch (l)
    51.         {
    52.             case _Nikko_LOD_LEVEL.LOD0:
    53.                 lodMesh0.SetActiveRecursively(true);
    54.                 lodMesh1.SetActiveRecursively(false);
    55.                 lodMesh2.SetActiveRecursively(false);              
    56.                 if (nlod>3) lodMesh3.SetActiveRecursively(false);
    57.                 if (nlod>4) lodMesh4.SetActiveRecursively(false);              
    58.             break;
    59.             case _Nikko_LOD_LEVEL.LOD1:
    60.                 lodMesh0.SetActiveRecursively(false);
    61.                 lodMesh1.SetActiveRecursively(true);
    62.                 lodMesh2.SetActiveRecursively(false);              
    63.                 if (nlod>3) lodMesh3.SetActiveRecursively(false);
    64.                 if (nlod>4) lodMesh4.SetActiveRecursively(false);              
    65.             break;
    66.             case _Nikko_LOD_LEVEL.LOD2:
    67.                 lodMesh0.SetActiveRecursively(false);
    68.                 lodMesh1.SetActiveRecursively(false);
    69.                 lodMesh2.SetActiveRecursively(true);               
    70.                 if (nlod>3) lodMesh3.SetActiveRecursively(false);
    71.                 if (nlod>4) lodMesh4.SetActiveRecursively(false);              
    72.             break;
    73.             case _Nikko_LOD_LEVEL.LOD3:
    74.                 lodMesh0.SetActiveRecursively(false);
    75.                 lodMesh1.SetActiveRecursively(false);
    76.                 lodMesh2.SetActiveRecursively(false);              
    77.                 if (nlod>3) lodMesh3.SetActiveRecursively(true);
    78.                 if (nlod>4) lodMesh4.SetActiveRecursively(false);              
    79.             break;
    80.             case    _Nikko_LOD_LEVEL.LOD4:
    81.                 lodMesh0.SetActiveRecursively(false);
    82.                 lodMesh1.SetActiveRecursively(false);
    83.                 lodMesh2.SetActiveRecursively(false);              
    84.                 if (nlod>3) lodMesh3.SetActiveRecursively(false);
    85.                 if (nlod>4) lodMesh4.SetActiveRecursively(true);               
    86.             break;                 
    87.             case    _Nikko_LOD_LEVEL.LOD5:
    88.                 lodMesh0.SetActiveRecursively(false);
    89.                 lodMesh1.SetActiveRecursively(false);
    90.                 lodMesh2.SetActiveRecursively(false);              
    91.                 if (nlod>3) lodMesh3.SetActiveRecursively(false);              
    92.                 if (nlod>4) lodMesh4.SetActiveRecursively(false);
    93.             break;         
    94.             default:
    95.                 lodMesh0.SetActiveRecursively(false);
    96.                 lodMesh1.SetActiveRecursively(false);
    97.                 lodMesh2.SetActiveRecursively(false);              
    98.                 if (nlod>3) lodMesh3.SetActiveRecursively(false);
    99.                 if (nlod>4) lodMesh4.SetActiveRecursively(false);
    100.         }
    101.     }
    102.    
    103.         // Library to access internal values of the LOD manager.
    104.     function setDistanceLOD(lod:int,dist:float)
    105.     {
    106.         switch (lod)
    107.         {
    108.             case _Nikko_LOD_LEVEL.LOD0:
    109.                 distanceLOD0=dist;
    110.             break;
    111.             case _Nikko_LOD_LEVEL.LOD1:
    112.                 distanceLOD1=dist;
    113.             break;
    114.             case _Nikko_LOD_LEVEL.LOD2:
    115.                 distanceLOD2=dist;
    116.             break;
    117.             case _Nikko_LOD_LEVEL.LOD3:
    118.                 distanceLOD3=dist;
    119.             break;         
    120.             case _Nikko_LOD_LEVEL.LOD4:
    121.                 distanceLOD4=dist;
    122.             break;
    123.             default:
    124.             Debug.LogError("SetDistanceLOD: Wrong LOD value");return;
    125.                
    126.         }
    127.     }
    128.    
    129.     // Change the time when this LOD script will execute.
    130.     function SetCounter(c:int)
    131.     {
    132.         counter=c;
    133.     }
    134.    
    135.    
    136.     function Start()
    137.     {
    138.         // spread the autoupdate within the range of the delay counter variable so that each LOD check itself every x number of frames.
    139.         counter=Random.Range(1, delaycounter);
    140.         // check if some object are too far, if yes, disable them
    141.         var distanceFromObject : float = Vector3.Distance(transform.position, mycam.transform.position);
    142.         if (distanceFromObject  > distancehide)
    143.         {
    144.                 switch (nlod) // each LOD (3,4,5) has to be done separately
    145.                 {
    146.                 case 3:
    147.                     currentLOD = _Nikko_LOD_LEVEL.LOD3;
    148.                     lodMesh0.SetActiveRecursively(false);
    149.                     lodMesh1.SetActiveRecursively(false);
    150.                     lodMesh2.SetActiveRecursively(false);              
    151.                 break;
    152.                 case 4:
    153.                     currentLOD = _Nikko_LOD_LEVEL.LOD4;
    154.                     lodMesh0.SetActiveRecursively(false);
    155.                     lodMesh1.SetActiveRecursively(false);
    156.                     lodMesh2.SetActiveRecursively(false);              
    157.                     lodMesh3.SetActiveRecursively(false);              
    158.                 break;         
    159.                 case 5:
    160.                     currentLOD = _Nikko_LOD_LEVEL.LOD5;
    161.                     lodMesh0.SetActiveRecursively(false);
    162.                     lodMesh1.SetActiveRecursively(false);
    163.                     lodMesh2.SetActiveRecursively(false);              
    164.                     lodMesh3.SetActiveRecursively(false);              
    165.                     lodMesh4.SetActiveRecursively(false);
    166.                 break;
    167.             }
    168.         }              
    169.     }
    170.    
    171.     function LateUpdate()
    172.     {      
    173.        
    174.         /*if (currentLOD == _Nikko_LOD_LEVEL.LOD0)
    175.         {
    176.             // we are on the closest LOD
    177.             // place here your real time effect, for your closest objects, like wind, movements, animations.
    178.         }
    179.         */ 
    180.         counter=counter-1;
    181.         // check that we are at the time we need to check ourself and maybe change our LOD
    182.         if (counter<0)
    183.         {
    184.             counter=delaycounter;
    185.             // quick method to calculate the distance with the camera.
    186.             var distanceFromObject : float = Vector3.Distance(transform.position, mycam.transform.position);
    187.        
    188.             switch (nlod) // each LOD (3,4,5) has to be done separately
    189.             {
    190.            
    191.                                 //************************   LOD 3 *************************
    192.                 case 3:
    193.                     // LOD0 is set here
    194.                     if (distanceFromObject < distanceLOD1  currentLOD != _Nikko_LOD_LEVEL.LOD0)
    195.                     {
    196.                         currentLOD = _Nikko_LOD_LEVEL.LOD0;
    197.                         lodMesh0.SetActiveRecursively(true);
    198.                         lodMesh1.SetActiveRecursively(false);
    199.                         lodMesh2.SetActiveRecursively(false);                  
    200.                         return;
    201.  
    202.                        
    203.                     }
    204.                     // LOD 1 is set here
    205.                     else if (distanceFromObject >= distanceLOD1  distanceFromObject < distanceLOD2  currentLOD != _Nikko_LOD_LEVEL.LOD1)
    206.                     {
    207.                         currentLOD = _Nikko_LOD_LEVEL.LOD1;
    208.                         lodMesh0.SetActiveRecursively(false);
    209.                         lodMesh1.SetActiveRecursively(true);
    210.                         lodMesh2.SetActiveRecursively(false);
    211.                         return;
    212.  
    213.                     }
    214.                     // LOD 2 is set here.
    215.                     else if (distanceFromObject >= distanceLOD2  distanceFromObject  < distancehide  currentLOD != _Nikko_LOD_LEVEL.LOD2)
    216.                     {
    217.                         currentLOD = _Nikko_LOD_LEVEL.LOD2;
    218.                         lodMesh0.SetActiveRecursively(false);
    219.                         lodMesh1.SetActiveRecursively(false);
    220.                         lodMesh2.SetActiveRecursively(true);           
    221.                         return;
    222.                     }              
    223.                     else if (distanceFromObject  > distancehide  currentLOD != _Nikko_LOD_LEVEL.LOD5)
    224.                     {
    225.                         // again if we are here, this object has gone too far: disable it!
    226.                         currentLOD = _Nikko_LOD_LEVEL.LOD3;
    227.                         lodMesh0.SetActiveRecursively(false);
    228.                         lodMesh1.SetActiveRecursively(false);
    229.                         lodMesh2.SetActiveRecursively(false);          
    230.                         return;
    231.                     }
    232.                 break;
    233.                         //************************   LOD 4 *************************
    234.                 case 4:
    235.                     // LOD0 is set here
    236.                     if (distanceFromObject < distanceLOD1  currentLOD != _Nikko_LOD_LEVEL.LOD0)
    237.                     {
    238.                         currentLOD = _Nikko_LOD_LEVEL.LOD0;
    239.                         lodMesh0.SetActiveRecursively(true);
    240.                         lodMesh1.SetActiveRecursively(false);
    241.                         lodMesh2.SetActiveRecursively(false);              
    242.                         lodMesh3.SetActiveRecursively(false);      
    243.                         return;
    244.  
    245.                        
    246.                     }
    247.                     // LOD 1 is set here
    248.                     else if (distanceFromObject >= distanceLOD1  distanceFromObject < distanceLOD2  currentLOD != _Nikko_LOD_LEVEL.LOD1)
    249.                     {
    250.                         currentLOD = _Nikko_LOD_LEVEL.LOD1;
    251.                         lodMesh0.SetActiveRecursively(false);
    252.                         lodMesh1.SetActiveRecursively(true);
    253.                         lodMesh2.SetActiveRecursively(false);
    254.                         lodMesh3.SetActiveRecursively(false);  
    255.                         return;
    256.  
    257.                     }
    258.                     // LOD 2 is set here.
    259.                     else if (distanceFromObject >= distanceLOD2  distanceFromObject  < distanceLOD3  currentLOD != _Nikko_LOD_LEVEL.LOD2)
    260.                     {
    261.                         currentLOD = _Nikko_LOD_LEVEL.LOD2;
    262.                         lodMesh0.SetActiveRecursively(false);
    263.                         lodMesh1.SetActiveRecursively(false);
    264.                         lodMesh2.SetActiveRecursively(true);       
    265.                         lodMesh3.SetActiveRecursively(false);      
    266.                         return;
    267.                     }          
    268.                     // LOD 3 is set here.
    269.                     else if (distanceFromObject >= distanceLOD3  distanceFromObject  < distancehide  currentLOD != _Nikko_LOD_LEVEL.LOD3)
    270.                     {
    271.                         currentLOD = _Nikko_LOD_LEVEL.LOD3;
    272.                         lodMesh0.SetActiveRecursively(false);
    273.                         lodMesh1.SetActiveRecursively(false);
    274.                         lodMesh2.SetActiveRecursively(false);      
    275.                         lodMesh3.SetActiveRecursively(true);
    276.        
    277.                         return;
    278.                     }          
    279.                     else if (distanceFromObject  > distancehide  currentLOD != _Nikko_LOD_LEVEL.LOD5)
    280.                     {
    281.                         // again if we are here, this object has gone too far: disable it!
    282.                         currentLOD = _Nikko_LOD_LEVEL.LOD4;
    283.                         lodMesh0.SetActiveRecursively(false);
    284.                         lodMesh1.SetActiveRecursively(false);
    285.                         lodMesh2.SetActiveRecursively(false);  
    286.                         lodMesh3.SetActiveRecursively(false);              
    287.                         return;
    288.                     }
    289.                 break;
    290.            
    291.                 //************************   LOD 5 *************************
    292.                 case 5:
    293.                     // LOD0 is set here
    294.                     if (distanceFromObject < distanceLOD1  currentLOD != _Nikko_LOD_LEVEL.LOD0)
    295.                     {
    296.                         currentLOD = _Nikko_LOD_LEVEL.LOD0;
    297.                         lodMesh0.SetActiveRecursively(true);
    298.                         lodMesh1.SetActiveRecursively(false);
    299.                         lodMesh2.SetActiveRecursively(false);              
    300.                         lodMesh3.SetActiveRecursively(false);
    301.                         lodMesh4.SetActiveRecursively(false);          
    302.                         return;
    303.  
    304.                        
    305.                     }
    306.                     // LOD 1 is set here
    307.                     else if (distanceFromObject >= distanceLOD1  distanceFromObject < distanceLOD2  currentLOD != _Nikko_LOD_LEVEL.LOD1)
    308.                     {
    309.                         currentLOD = _Nikko_LOD_LEVEL.LOD1;
    310.                         lodMesh0.SetActiveRecursively(false);
    311.                         lodMesh1.SetActiveRecursively(true);
    312.                         lodMesh2.SetActiveRecursively(false);
    313.                         lodMesh3.SetActiveRecursively(false);  
    314.                         lodMesh4.SetActiveRecursively(false);          
    315.                         return;
    316.  
    317.                     }
    318.                     // LOD 2 is set here.
    319.                     else if (distanceFromObject >= distanceLOD2  distanceFromObject  < distanceLOD3  currentLOD != _Nikko_LOD_LEVEL.LOD2)
    320.                     {
    321.                         currentLOD = _Nikko_LOD_LEVEL.LOD2;
    322.                         lodMesh0.SetActiveRecursively(false);
    323.                         lodMesh1.SetActiveRecursively(false);
    324.                         lodMesh2.SetActiveRecursively(true);       
    325.                         lodMesh3.SetActiveRecursively(false);
    326.                         lodMesh4.SetActiveRecursively(false);          
    327.                         return;
    328.                     }          
    329.                     // LOD 3 is set here.
    330.                     else if (distanceFromObject >= distanceLOD3  distanceFromObject  < distanceLOD4  currentLOD != _Nikko_LOD_LEVEL.LOD3)
    331.                     {
    332.                         currentLOD = _Nikko_LOD_LEVEL.LOD3;
    333.                         lodMesh0.SetActiveRecursively(false);
    334.                         lodMesh1.SetActiveRecursively(false);
    335.                         lodMesh2.SetActiveRecursively(false);      
    336.                         lodMesh3.SetActiveRecursively(true);
    337.                         lodMesh4.SetActiveRecursively(false);          
    338.                         return;
    339.                     }          
    340.                     // LOD 4 is set here.
    341.                     else if (distanceFromObject >= distanceLOD4  distanceFromObject  < distancehide  currentLOD != _Nikko_LOD_LEVEL.LOD4)
    342.                     {
    343.                         currentLOD = _Nikko_LOD_LEVEL.LOD4;
    344.                         lodMesh0.SetActiveRecursively(false);
    345.                         lodMesh1.SetActiveRecursively(false);
    346.                         lodMesh2.SetActiveRecursively(false);      
    347.                         lodMesh3.SetActiveRecursively(true);
    348.                         lodMesh4.SetActiveRecursively(false);          
    349.                         return;
    350.                     }
    351.                     else if (distanceFromObject  > distancehide  currentLOD != _Nikko_LOD_LEVEL.LOD5)
    352.                     {
    353.                         // again if we are here, this object has gone too far: disable it!
    354.                         currentLOD = _Nikko_LOD_LEVEL.LOD5;
    355.                         lodMesh0.SetActiveRecursively(false);
    356.                         lodMesh1.SetActiveRecursively(false);
    357.                         lodMesh2.SetActiveRecursively(false);  
    358.                         lodMesh3.SetActiveRecursively(false);      
    359.                         lodMesh4.SetActiveRecursively(false);          
    360.                         return;
    361.                     }
    362.                 break;
    363.            
    364.             }
    365.        
    366.         }          
    367.    
    368.  
    369.     }
    370.    
    371.  
     
  28. unity3dx

    unity3dx

    Joined:
    Apr 15, 2011
    Posts:
    175
    ULS PRO Updated, and new Speed Forest Summer expansion

    Today I release the latest version of ULS PRO with bug fixes and a new structure to be able to handle many new upcoming expansions. I also release the new Speed Forest Summer expansion.



    ULS PRO can be found here : http://www.unity3dx.com/index.php/products/uls-pro/

    ULS EXP 2 Speed Forest Summer : can be found here : http://www.unity3dx.com/index.php/products/uls-exp2/

    ULS EXP 1 Speed Forest Autumn : can be found here : http://www.unity3dx.com/index.php/products/uls-exp1/

    ULS free can be found here : http://www.unity3dx.com/index.php/products/uls-free/
     
  29. unity3dx

    unity3dx

    Joined:
    Apr 15, 2011
    Posts:
    175
    Massive Unity 3.5 updates for Huge City free, Ocean Free, ULS PRO, and all Packs. Also a new ULS compatible pack: Atmospheric Planets.
    Check the news here and update your free or commercial pack: http://unity3dx.com/news/massive-updates/
     
  30. SteveB

    SteveB

    Joined:
    Jan 17, 2009
    Posts:
    1,451
    ...pretty sweet. Safe to assume then this still works well on mobile platforms?

    -Steve