Level Of Detail

Several Methods:

1) LOD Meshes script:

#pragma strict

@AddComponentMenu("Scripts/Misc/LevelOfDetail")

@RequireComponent(MeshFilter)

enum LOD_LEVEL { LOD0, LOD1, LOD2 }

/*

* Script to swap out meshes based on distance (LOD)

* C# version by Rich Hudson 2009 - Kranky Boy Games

* Javascript conversion + optimizations by Leepo - M2H

*/

class LODmeshes extends MonoBehaviour {

public var lodMesh0 : Mesh; public var lodMesh1 : Mesh; public var lodMesh2 : Mesh; public var distanceLOD1 : float; public var distanceLOD2 : float; public var updateInterval : float = 2; private var currentLOD : LOD_LEVEL= LOD_LEVEL.LOD2; private var meshFilter : MeshFilter; private var thisTransform : Transform; function Awake() { meshFilter = GetComponent(MeshFilter); thisTransform = transform; //Distribute load by checkingLOD for every LOD script at a different time var startIn : float = Random.Range(0.0, updateInterval); InvokeRepeating("CheckLOD", startIn, updateInterval); } function CheckLOD() { var distanceFromObject : float = Vector3.Distance(thisTransform.position, Camera.main.transform.position); if (distanceFromObject < distanceLOD1 && currentLOD != LOD_LEVEL.LOD0) { currentLOD = LOD_LEVEL.LOD0; meshFilter.mesh = lodMesh0; } else if (distanceFromObject >= distanceLOD1 && distanceFromObject < distanceLOD2 && currentLOD != LOD_LEVEL.LOD1) { currentLOD = LOD_LEVEL.LOD1; meshFilter.mesh = lodMesh1; } else if (distanceFromObject >= distanceLOD2 && currentLOD != LOD_LEVEL.LOD2) { currentLOD = LOD_LEVEL.LOD2; meshFilter.mesh = lodMesh2; } } }2) Camera-based LOD using clipping planes:

One method of LOD that doesn't require any scripting is actually demonstrated in the 3D Platformer Tutorial:

    • 1. Make a separate camera for each level of detail, and match their near and far clipping planes so that they form a complete frustum.

    • 2. Attach all the cameras to the same parent (or just make them children of the first camera).

    • 3. Set the cameras' render layers to mutually exclusive layers, or sets of layers.

    • 4. Set the depth for each camera so that the closest frustum is highest, and the furthest is lowest.

    • 5. Set the furthest camera's clear flags to "skybox" and all other cameras to "depth only".

    • 6. For each visible GameObject, place the models for each LOD of a given mesh under a common parent.

    • 7. Put each LOD mesh on a layer that will be shown by the corresponding camera.

This way all the culling and swapping is done by Unity's frustum culling, and you never have to touch a script. If you want something to disappear when far away, simply don't put a model on the corresponding layer.

3) LOD prefab:

(see https://sites.google.com/site/drexelgames/courses/gmap345/resource-files for project)

//pragma strict

//Assign the higher res model here

var LODInner: GameObject;

//Assign the lower res one here

var LODOuter: GameObject;

//switch this on when the scene is running to see your triggerzone

var IsTriggerzoneVisible: boolean = true;

function Awake () {

//switch off the higher res mesh-this assumes the player wil initiate in the scene away from the model, and assumes there is only one LOD change. this Prefab has two, so you may see two models simultaneously unless you make the triggerzones larger, or simply customise this script to suit.

LODInner.active=false;

LODOuter.active=true;

//check if user has checked or unchecked visible varible in the inspector (for visually seeing the triggerzone)

if (IsTriggerzoneVisible==false)

renderer.enabled=false;

if (IsTriggerzoneVisible==true)

renderer.enabled=true;

}

function OnTriggerEnter(invader: Collider){

//Only switch LOD for the PLAYER, not the Enemies or other NPCS-change the red text as required

if(invader.name==("First Person Controller")){

//render higher res model when player is inside triggerzone

LODInner.active=true;

LODOuter.active=false;

}

}

function OnTriggerExit(invader: Collider){

if(invader.name==("First Person Controller")){

//render lower res model when player leaves triggerzone

LODInner.active=false;

LODOuter.active=true;

}

}

function Update(){

//this enables us to switch the triggerzone visibility on and off during the game. I recommend deleting this code block once you're happy with all behaviours just to save the engine from constantly checking.

if(IsTriggerzoneVisible==true){

renderer.enabled=true;

return;

}

if(IsTriggerzoneVisible==false){

renderer.enabled=false;

return;

}

}