public static bool SaveTemplate ( LBLandscape landscape, string LBEditorVersion, string landscapeTemplateName, ref bool isSceneSaveRequired, bool createTemplatePackage, bool addMapTexturesToTemplatePackage, bool addLayerHeightmapTexturesToTemplatePackage, bool addLBLightingToTemplate, bool addPathsToTemplate, bool addStencilsToTemplate, bool addPathMeshMaterialsToTemplate ) { bool isSuccessful = false; string landscapeName = landscape.name; // Create a new gameobject in the scene hierarchy that we can turn into a prefab GameObject newTemplateObj = new GameObject(landscapeName + " template"); if (newTemplateObj == null) { Debug.LogWarning("Landscape Builder - could not create temporary gameobject for " + landscapeName + " template"); } else { LBTemplate lbTemplate = newTemplateObj.AddComponent <LBTemplate>(); if (lbTemplate == null) { Debug.LogWarning("Landscape Builder - could not add LBTemplate component " + landscapeName + " template"); GameObject.DestroyImmediate(newTemplateObj); } else { // This is the installed version of LB when the template was created lbTemplate.LBVersion = LBEditorVersion; // This is the version of the landscape when the template was created lbTemplate.LastUpdatedVersion = landscape.LastUpdatedVersion; // The version of Unity that created this template lbTemplate.templateUnityVersion = Application.unityVersion; lbTemplate.useLegacyNoiseOffset = landscape.useLegacyNoiseOffset; // Name of the landscape game object lbTemplate.landscapeName = landscapeName; lbTemplate.size = landscape.size; lbTemplate.start = landscape.start; // Landscape terrain settings Vector3 terrainSize3D = landscape.GetLandscapeTerrainSize(); lbTemplate.heightmapResolution = landscape.GetLandscapeTerrainHeightmapResolution(); lbTemplate.terrainWidth = terrainSize3D.x; lbTemplate.terrainHeight = terrainSize3D.y; lbTemplate.pixelError = landscape.GetLandscapeTerrainPixelError(); lbTemplate.baseMapDistance = landscape.GetLandscapeTerrainBaseMapDist(); lbTemplate.alphaMapResolution = landscape.GetLandscapeTerrainAlphaMapResolution(); lbTemplate.baseTextureResolution = landscape.GetLandscapeTerrainBaseTextureResolution(); lbTemplate.treeDistance = landscape.GetLandscapeTerrainTreeDistance(); lbTemplate.treeBillboardDistance = landscape.GetLandscapeTerrainTreeBillboardStart(); lbTemplate.detailDistance = landscape.GetLandscapeTerrainDetailDistance(); lbTemplate.detailDensity = landscape.GetLandscapeTerrainDetailDensity(); lbTemplate.detailResolution = landscape.GetLandscapeTerrainDetailResolution(); lbTemplate.treeFadeDistance = landscape.GetLandscapeTerrainTreeFadeLength(); lbTemplate.grassWindSpeed = landscape.GetLandscapeTerrainGrassWindSpeed(); lbTemplate.grassWindRippleSize = landscape.GetLandscapeTerrainGrassWindRippleSize(); lbTemplate.grassWindBending = landscape.GetLandscapeTerrainGrassWindBending(); lbTemplate.grassWindTint = landscape.GetLandscapeTerrainGrassWindTint(); lbTemplate.terrainLegacySpecular = landscape.GetLandscapeTerrainLegacySpecular(); lbTemplate.terrainLegacyShininess = landscape.GetLandscapeTerrainLegacyShininess(); lbTemplate.useTerrainDrawInstanced = landscape.GetLandscapeTerrainDrawInstanced(); lbTemplate.useTerrainPerPixelNormals = GetTerrainPerPixelNormals(landscape); lbTemplate.terrainGroupingID = landscape.GetLandscapeTerrainGroupingID(); lbTemplate.terrainAutoConnect = landscape.GetLandscapeTerrainAutoConnect(); // Synchronize with a duplicate enum in lbTemplate lbTemplate.terrainMaterialType = (LBTemplate.TerrainMaterialType)landscape.GetTerrainMaterialType(); // Check if any lists are null if (landscape.topographyLayersList == null) { landscape.topographyLayersList = new List <LBLayer>(); } if (landscape.terrainTexturesList == null) { landscape.terrainTexturesList = new List <LBTerrainTexture>(); } if (landscape.terrainTreesList == null) { landscape.terrainTreesList = new List <LBTerrainTree>(); } if (landscape.terrainGrassList == null) { landscape.terrainGrassList = new List <LBTerrainGrass>(); } if (landscape.lbGroupList == null) { landscape.lbGroupList = new List <LBGroup>(); } if (landscape.landscapeMeshList == null) { landscape.landscapeMeshList = new List <LBLandscapeMesh>(); } if (landscape.landscapeWaterList == null) { landscape.landscapeWaterList = new List <LBWater>(); } // Update texture names to help detect missing textures when importing templates into another project for (int txIdx = 0; txIdx < landscape.terrainTexturesList.Count; txIdx++) { // Only attempt to update the textureName if it is null or an empty string. // This avoids loosing details about an already missing texture if (string.IsNullOrEmpty(landscape.terrainTexturesList[txIdx].textureName)) { if (landscape.terrainTexturesList[txIdx].texture != null) { landscape.terrainTexturesList[txIdx].textureName = landscape.terrainTexturesList[txIdx].texture.name; isSceneSaveRequired = true; } } // Only attempt to update the normalMapName if it is null or an empty string. // This avoids loosing details about an already missing normalMap if (string.IsNullOrEmpty(landscape.terrainTexturesList[txIdx].normalMapName)) { if (landscape.terrainTexturesList[txIdx].normalMap != null) { landscape.terrainTexturesList[txIdx].normalMapName = landscape.terrainTexturesList[txIdx].normalMap.name; isSceneSaveRequired = true; } } } // Update Grass texture names to help detect missing textures when importing templates into another project for (int grIdx = 0; grIdx < landscape.terrainGrassList.Count; grIdx++) { // Only attempt to update the grass textureName if it is null or an empty string. // This avoids loosing details about an already missing grass texture if (string.IsNullOrEmpty(landscape.terrainGrassList[grIdx].textureName)) { if (landscape.terrainGrassList[grIdx].texture != null) { landscape.terrainGrassList[grIdx].textureName = landscape.terrainGrassList[grIdx].texture.name; isSceneSaveRequired = true; } } // Only attempt to update the grass meshPrefName if it is null or an empty string. // This avoids loosing details about an already missing grass mesh prefab if (string.IsNullOrEmpty(landscape.terrainGrassList[grIdx].meshPrefabName)) { if (landscape.terrainGrassList[grIdx].meshPrefab != null) { landscape.terrainGrassList[grIdx].meshPrefabName = landscape.terrainGrassList[grIdx].meshPrefab.name; isSceneSaveRequired = true; } } } // Update Tree prefab names to help detect missing prefabs when importing templates into another project for (int trIdx = 0; trIdx < landscape.terrainTreesList.Count; trIdx++) { // Only attempt to update the tree prefabName if it is null or an empty string. // This avoids loosing details about an already missing tree prefab if (string.IsNullOrEmpty(landscape.terrainTreesList[trIdx].prefabName)) { if (landscape.terrainTreesList[trIdx].prefab != null) { landscape.terrainTreesList[trIdx].prefabName = landscape.terrainTreesList[trIdx].prefab.name; isSceneSaveRequired = true; } } } // Update Mesh prefab names to help detect missing prefabs when importing templates into another project for (int meshIdx = 0; meshIdx < landscape.landscapeMeshList.Count; meshIdx++) { // Only attempt to update the mesh prefabName if it is null or an empty string. // This avoids loosing details about an already missing mesh prefab if (string.IsNullOrEmpty(landscape.landscapeMeshList[meshIdx].prefabName)) { if (landscape.landscapeMeshList[meshIdx].prefab != null) { landscape.landscapeMeshList[meshIdx].prefabName = landscape.landscapeMeshList[meshIdx].prefab.name; isSceneSaveRequired = true; } } } int numGroups = landscape.lbGroupList == null ? 0 : landscape.lbGroupList.Count; // Update Group Member prefab names to help detect missing prefabs when importing templates into another project for (int grpIdx = 0; grpIdx < numGroups; grpIdx++) { if (landscape.lbGroupList[grpIdx].groupMemberList != null) { List <LBGroupMember> groupMemberList = landscape.lbGroupList[grpIdx].groupMemberList; for (int grpMbrIdx = 0; grpMbrIdx < groupMemberList.Count; grpMbrIdx++) { // Only attempt to update the prefab prefabName if it is null or an empty string. // This avoids loosing details about an already missing prefab if (string.IsNullOrEmpty(groupMemberList[grpMbrIdx].prefabName)) { if (groupMemberList[grpMbrIdx].prefab != null) { groupMemberList[grpMbrIdx].prefabName = groupMemberList[grpMbrIdx].prefab.name; isSceneSaveRequired = true; } } } } } // Landscape class lists - perform deep copy (#SMS 2.0.6 Beta 6f) // Attempts to avoid issue where a template prefab is created (and later deleted) which could delete data // from the landscape meta-data in the scene. lbTemplate.topographyLayersList = landscape.topographyLayersList.ConvertAll(lyr => new LBLayer(lyr)); lbTemplate.terrainTexturesList = landscape.terrainTexturesList.ConvertAll(tt => new LBTerrainTexture(tt)); lbTemplate.terrainTreesList = landscape.terrainTreesList.ConvertAll(tt => new LBTerrainTree(tt)); lbTemplate.terrainGrassList = landscape.terrainGrassList.ConvertAll(tg => new LBTerrainGrass(tg)); lbTemplate.lbGroupList = landscape.lbGroupList.ConvertAll(grp => new LBGroup(grp)); lbTemplate.landscapeMeshList = landscape.landscapeMeshList.ConvertAll(msh => new LBLandscapeMesh(msh)); lbTemplate.landscapeWaterList = landscape.landscapeWaterList.ConvertAll(wtr => new LBWater(wtr, false)); // Check for surface and/or base mesh materials in Group Object Paths for (int grpIdx = 0; grpIdx < numGroups; grpIdx++) { int numGrpMembers = landscape.lbGroupList[grpIdx].groupMemberList == null ? 0 : landscape.lbGroupList[grpIdx].groupMemberList.Count; for (int grpMbrIdx = 0; grpMbrIdx < numGrpMembers; grpMbrIdx++) { LBGroupMember _lbGroupMember = landscape.lbGroupList[grpIdx].groupMemberList[grpMbrIdx]; // A deep copy will attempt create a new instance of the material using our LBGroupMember clone constructor // In this case we need to reference the actual material in the project folder. // If the Object Path was a duplicate of an existing Object Path, then this may also fail. if (_lbGroupMember != null && _lbGroupMember.lbMemberType == LBGroupMember.LBMemberType.ObjPath && _lbGroupMember.lbObjPath != null) { lbTemplate.lbGroupList[grpIdx].groupMemberList[grpMbrIdx].lbObjPath.surfaceMeshMaterial = _lbGroupMember.lbObjPath.surfaceMeshMaterial; lbTemplate.lbGroupList[grpIdx].groupMemberList[grpMbrIdx].lbObjPath.baseMeshMaterial = _lbGroupMember.lbObjPath.baseMeshMaterial; } } } // Final Pass varibles lbTemplate.useFinalPassSmoothing = landscape.useFinalPassSmoothing; lbTemplate.finalPassSmoothingIterations = landscape.finalPassSmoothingIterations; lbTemplate.finalPassPixelRange = landscape.finalPassPixelRange; lbTemplate.fPassSmoothStencilGUID = landscape.fPassSmoothStencilGUID; lbTemplate.fPassSmoothStencilLayerGUID = landscape.fPassSmoothStencilLayerGUID; lbTemplate.fPassSmoothFilterMode = landscape.fPassSmoothFilterMode; lbTemplate.thermalErosionPreset = landscape.thermalErosionPreset; lbTemplate.useThermalErosion = landscape.useThermalErosion; lbTemplate.thermalErosionIterations = landscape.thermalErosionIterations; lbTemplate.thermalErosionTalusAngle = landscape.thermalErosionTalusAngle; lbTemplate.thermalErosionStrength = landscape.thermalErosionStrength; lbTemplate.fPassThErosionStencilGUID = landscape.fPassThErosionStencilGUID; lbTemplate.fPassThErosionStencilLayerGUID = landscape.fPassThErosionStencilLayerGUID; lbTemplate.fPassThErosionFilterMode = landscape.fPassThErosionFilterMode; // Group Settings lbTemplate.autoRefreshGroupDesigner = landscape.autoRefreshGroupDesigner; // Vegetation Integration variables lbTemplate.useVegetationSystem = landscape.useVegetationSystem; lbTemplate.useVegetationSystemTextures = landscape.useVegetationSystemTextures; // Landscape Extension lbTemplate.useLandscapeExtension = landscape.useLandscapeExtension; if (landscape.lbLandscapeExtension != null) { lbTemplate.lbLandscapeExtension = new LBLandscapeExtension(landscape.lbLandscapeExtension); } else { lbTemplate.lbLandscapeExtension = new LBLandscapeExtension(); } // GPU acceleration lbTemplate.useGPUTexturing = landscape.useGPUTexturing; lbTemplate.useGPUTopography = landscape.useGPUTopography; lbTemplate.useGPUGrass = landscape.useGPUGrass; lbTemplate.useGPUPath = landscape.useGPUPath; // Undo override lbTemplate.isUndoTopographyDisabled = landscape.isUndoTopographyDisabled; // Topography Mask - there is one per landscape lbTemplate.topographyMaskMode = (LBTemplate.MaskMode)landscape.topographyMaskMode; lbTemplate.distanceToCentreMask = landscape.distanceToCentreMask; lbTemplate.maskWarpAmount = landscape.maskWarpAmount; lbTemplate.maskNoiseTileSize = landscape.maskNoiseTileSize; lbTemplate.maskNoiseOffsetX = landscape.maskNoiseOffsetX; lbTemplate.maskNoiseOffsetY = landscape.maskNoiseOffsetY; lbTemplate.maskNoiseCurveModifier = landscape.maskNoiseCurveModifier; // Does user wish to include LBLighting? if (addLBLightingToTemplate) { // Only include LBLighting if it is in the scene LBLighting lbLighting = GameObject.FindObjectOfType <LBLighting>(); if (lbLighting == null) { lbTemplate.isLBLightingIncluded = false; Debug.LogWarning("Landscape Builder - Export Template - No LBLighting found in the scene"); } else { lbTemplate.isLBLightingIncluded = true; lbTemplate.AddLBLightingSettings(lbLighting); } } else { lbTemplate.isLBLightingIncluded = false; } // Create an empty list of Asset Paths for the mesh materials List <string> lbMapPathMaterialAssetPathList = new List <string>(); if (addPathsToTemplate) { // Find any Camera Paths in this landscape (changed from all in scene in 1.3.2 Beta 9b) List <LBCameraPath> lbCameraPathList = LBCameraPath.GetCameraPathsInLandscape(landscape); if (lbCameraPathList != null) { // Get the LBPath from each LBCameraPath and add it to the LBTemplate instance foreach (LBCameraPath lbCameraPath in lbCameraPathList) { if (lbCameraPath.lbPath != null) { // Update the path name before adding to the template if (lbCameraPath.gameObject != null) { lbCameraPath.lbPath.pathName = lbCameraPath.gameObject.name; isSceneSaveRequired = true; } lbTemplate.lbPathList.Add(lbCameraPath.lbPath); } } } // Find all MapPaths in the this landscape List <LBMapPath> lbMapPathList = LBMapPath.GetMapPathsInLandscape(landscape); if (lbMapPathList != null) { // Get the LBPath from each LBMapPath and add it to the LBTemplate instance foreach (LBMapPath lbMapPath in lbMapPathList) { if (lbMapPath.lbPath != null) { // Update the path name before adding to the template if (lbMapPath.gameObject != null) { lbMapPath.lbPath.pathName = lbMapPath.gameObject.name; // Check for a mesh if (lbMapPath.lbPath.lbMesh != null && addPathMeshMaterialsToTemplate) { lbMapPath.lbPath.meshTempMaterial = lbMapPath.meshMaterial; // If also creating a package, remember the asset path for this mesh material if (createTemplatePackage) { string mapPathMatAssetPath = UnityEditor.AssetDatabase.GetAssetPath(lbMapPath.meshMaterial); if (!string.IsNullOrEmpty(mapPathMatAssetPath)) { lbMapPathMaterialAssetPathList.Add(mapPathMatAssetPath); } } } else { lbMapPath.lbPath.meshTempMaterial = null; } isSceneSaveRequired = true; } lbTemplate.lbPathList.Add(lbMapPath.lbPath); } } } } if (addStencilsToTemplate) { List <LBStencil> lbStencilList = LBStencil.GetStencilsInLandscape(landscape, true); if (lbTemplate.lbTemplateStencilList == null) { lbTemplate.lbTemplateStencilList = new List <LBTemplateStencil>(); } if (lbTemplate.lbTemplateStencilList != null && lbStencilList != null) { // Create a LBTemplateStencil for each Stencil in the landscape, and add it to the Template. // NOTE Does not copy the USHORT layerArray or render textures in the Stencil Layers as we want to keep // the Template as small as possible. foreach (LBStencil lbStencil in lbStencilList) { if (lbStencil != null) { LBTemplateStencil lbTemplateStencil = new LBTemplateStencil(lbStencil); if (lbTemplateStencil != null) { lbTemplate.lbTemplateStencilList.Add(lbTemplateStencil); } } } } } // Create template folders if they don't already exist LBEditorHelper.CheckFolder("Assets/LandscapeBuilder/Templates"); if (!Directory.Exists("LandscapeBuilder/TemplatePackages")) { Directory.CreateDirectory("LandscapeBuilder/TemplatePackages"); } // Create a prefab bool continueToSave = false; string templateFullPath = Application.dataPath + "/LandscapeBuilder/Templates/" + landscapeTemplateName + ".prefab"; string templateAssetPath = "Assets/LandscapeBuilder/Templates/" + landscapeTemplateName + ".prefab"; if (File.Exists(templateFullPath)) { if (EditorUtility.DisplayDialog("Template Already Exists", "Are you sure you want to save the template? The currently existing" + " template will be lost.", "Overwrite", "Cancel")) { if (!AssetDatabase.DeleteAsset(templateAssetPath)) { Debug.LogWarning("Landscape Builder - could not overwrite Assets/LandscapeBuilder/Templates/" + landscapeTemplateName + " for " + landscapeName + " template"); } else { continueToSave = true; } } } else { continueToSave = true; } if (continueToSave) { #if UNITY_2018_3_OR_NEWER GameObject templatePrefabGO = PrefabUtility.SaveAsPrefabAsset(newTemplateObj, templateAssetPath); #else GameObject templatePrefabGO = PrefabUtility.CreatePrefab(templateAssetPath, newTemplateObj); #endif if (templatePrefabGO != null && createTemplatePackage) { // Always include the template prefab (this is meta-data only) List <string> templateAssetPaths = new List <string>(); templateAssetPaths.Add(templateAssetPath); // Although technically users could include 3rd party textures in a LBMap texture, they are MUCH more likely to use // map textures generated from within Landscape Builder. if (addMapTexturesToTemplatePackage) { List <string> uniqueMapTexPaths = LBLandscapeOperations.GetMapTextureAssetPathsFromLandscape(landscape, true); if (uniqueMapTexPaths != null) { if (uniqueMapTexPaths.Count > 0) { templateAssetPaths.AddRange(uniqueMapTexPaths); } } } if (addLayerHeightmapTexturesToTemplatePackage) { // Get a list of the image-based topography layers with a heightmap texture List <LBLayer> layerList = landscape.topographyLayersList.FindAll(lyr => lyr.heightmapImage != null && (lyr.type == LBLayer.LayerType.ImageBase || lyr.type == LBLayer.LayerType.ImageAdditive || lyr.type == LBLayer.LayerType.ImageSubtractive || lyr.type == LBLayer.LayerType.ImageDetail)); if (layerList != null) { //Debug.Log("Save Template found " + layerList.Count + " image layers with a heightmap"); for (int lyrIdx = 0; lyrIdx < layerList.Count; lyrIdx++) { // Get the path in the asset db to the image-based layer heightmap texture string heightmapPath = UnityEditor.AssetDatabase.GetAssetPath(layerList[lyrIdx].heightmapImage); if (!string.IsNullOrEmpty(heightmapPath)) { templateAssetPaths.Add(heightmapPath); } } } } // Add the list of map path mesh materials we add earlier. if (addPathMeshMaterialsToTemplate && lbMapPathMaterialAssetPathList.Count > 0) { templateAssetPaths.AddRange(lbMapPathMaterialAssetPathList); } AssetDatabase.ExportPackage(templateAssetPaths.ToArray(), "LandscapeBuilder/TemplatePackages/" + landscapeTemplateName + ".unitypackage", ExportPackageOptions.Interactive); } LBEditorHelper.HighlightItemInProjectWindow(templateAssetPath); } // Cleanup scene hierarchy GameObject.DestroyImmediate(newTemplateObj); } } return(isSuccessful); }
// Use this for initialization void Awake() { #region Initialise // This line just gets the starting time of the generation so that the total generation time // can be recorded and displayed float generationStartTime = Time.realtimeSinceStartup; RuntimeSampleHelper.RemoveDefaultCamera(); RuntimeSampleHelper.RemoveDefaultLight(); // We're using some old trees in this demo, which don't like anti-aliasing QualitySettings.antiAliasing = 0; // Get a link to the LBLandscape script landscape = this.GetComponent <LBLandscape>(); if (landscape == null) { Debug.Log("Cannot find LBLandscape script attached to Runtime gameobject"); return; } // Update the size landscape.size = landscapeSize; // Create the terrains int terrainNumber = 0; #endregion #region Create Terrains for (float tx = 0f; tx < landscapeSize.x - 1f; tx += terrainWidth) { for (float ty = 0f; ty < landscapeSize.y - 1f; ty += terrainWidth) { // Create a new gameobject GameObject terrainObj = new GameObject("RuntimeTerrain" + (terrainNumber++).ToString("000")); // Create a new gameobject // Correctly parent and position the terrain terrainObj.transform.parent = this.transform; terrainObj.transform.localPosition = new Vector3(tx, 0f, ty); // Add a terrain component Terrain newTerrain = terrainObj.AddComponent <Terrain>(); // Set terrain settings (depending on your situtation, you may need to set more or less than I have in this example) newTerrain.heightmapPixelError = 5f; newTerrain.basemapDistance = 1000f; newTerrain.treeDistance = 750f; newTerrain.treeBillboardDistance = 100f; newTerrain.detailObjectDistance = 200f; newTerrain.treeCrossFadeLength = 5f; // Set terrain data settings (same as above comment) TerrainData newTerrainData = new TerrainData(); newTerrainData.heightmapResolution = 513; newTerrainData.size = new Vector3(terrainWidth, terrainHeight, terrainWidth); newTerrainData.SetDetailResolution(1024, 16); newTerrain.terrainData = newTerrainData; // Set up the terrain collider TerrainCollider newTerrainCol = terrainObj.AddComponent <TerrainCollider>(); newTerrainCol.terrainData = newTerrainData; } } landscape.SetLandscapeTerrains(true); landscape.SetDefaultTerrainMaterial(); #endregion #region Create a Stencil // Add a new Stencil to the (empty) landscape LBStencil lbStencil = LBStencil.CreateStencilInScene(landscape, landscape.gameObject); if (lbStencil != null) { lbStencil.name += "01"; /// Import PNG files into stencil layers (at runtime) and add as filters. lbStencil.layerImportMethod = LBStencil.LayerImportMethod.Grayscale; if (lbStencil.ImportTexture("Hills Layer 1", stencilLayerTex1, true)) { // Remove the default first layer if (lbStencil.stencilLayerList.Count > 1) { lbStencil.stencilLayerList.RemoveAt(0); } } } #endregion #region Define the Topography // NOTE: This sample uses a topography mask. This is not a requirement // Create the distance to centre mask using an animation curve AnimationCurve distanceToCentreMask = new AnimationCurve(); distanceToCentreMask.AddKey(0.00f, 0.04f); distanceToCentreMask.AddKey(0.30f, 0.03f); distanceToCentreMask.AddKey(0.78f, 1.00f); distanceToCentreMask.AddKey(1.00f, 1.00f); Keyframe[] distanceToCentreMaskKeys = distanceToCentreMask.keys; distanceToCentreMaskKeys[0].inTangent = 0.00f; distanceToCentreMaskKeys[0].outTangent = 0.00f; distanceToCentreMaskKeys[1].inTangent = -0.02f; distanceToCentreMaskKeys[1].outTangent = -0.02f; distanceToCentreMaskKeys[2].inTangent = 0.01f; distanceToCentreMaskKeys[2].outTangent = 0.01f; distanceToCentreMaskKeys[3].inTangent = 0.00f; distanceToCentreMaskKeys[3].outTangent = 0.00f; distanceToCentreMask = new AnimationCurve(distanceToCentreMaskKeys); // Assign the topography mask to the LBLandscape instance landscape.distanceToCentreMask = distanceToCentreMask; landscape.topographyMaskMode = LBLandscape.MaskMode.DistanceToCentre; // Create the Topography Layers // You can mix and match Perlin and Image layers landscape.topographyLayersList = new List <LBLayer>(); if (landscape.topographyLayersList != null) { // NOTE // If you have used the LB Editor to first build a test landscape, the Topography layer // can be scripted out and pasted into your runtime script here. // Layer Code generated from Landscape Builder at 7:59 AM on .... AnimationCurve additiveCurve = new AnimationCurve(); AnimationCurve subtractiveCurve = new AnimationCurve(); List <LBLayerFilter> filters = new List <LBLayerFilter>(); // Add LayerFilter code here List <AnimationCurve> imageCurveModifiers = new List <AnimationCurve>(); List <AnimationCurve> outputCurveModifiers = new List <AnimationCurve>(); AnimationCurve OutputCurve1 = new AnimationCurve(); OutputCurve1.AddKey(0.00f, 0.00f); OutputCurve1.AddKey(0.50f, 0.06f); OutputCurve1.AddKey(1.00f, 1.00f); Keyframe[] OutputCurve1Keys = OutputCurve1.keys; OutputCurve1Keys[0].inTangent = 0.00f; OutputCurve1Keys[0].outTangent = 0.00f; OutputCurve1Keys[1].inTangent = 0.50f; OutputCurve1Keys[1].outTangent = 0.50f; OutputCurve1Keys[2].inTangent = 4.00f; OutputCurve1Keys[2].outTangent = 4.00f; OutputCurve1 = new AnimationCurve(OutputCurve1Keys); outputCurveModifiers.Add(OutputCurve1); List <AnimationCurve> perOctaveCurveModifiers = new List <AnimationCurve>(); AnimationCurve PerOctaveCurve1 = new AnimationCurve(); PerOctaveCurve1.AddKey(0.00f, 0.00f); PerOctaveCurve1.AddKey(0.05f, 0.10f); PerOctaveCurve1.AddKey(0.45f, 0.90f); PerOctaveCurve1.AddKey(0.50f, 1.00f); PerOctaveCurve1.AddKey(0.55f, 0.90f); PerOctaveCurve1.AddKey(0.95f, 0.10f); PerOctaveCurve1.AddKey(1.00f, 0.00f); Keyframe[] PerOctaveCurve1Keys = PerOctaveCurve1.keys; PerOctaveCurve1Keys[0].inTangent = 0.00f; PerOctaveCurve1Keys[0].outTangent = 0.00f; PerOctaveCurve1Keys[1].inTangent = 2.00f; PerOctaveCurve1Keys[1].outTangent = 2.00f; PerOctaveCurve1Keys[2].inTangent = 2.00f; PerOctaveCurve1Keys[2].outTangent = 2.00f; PerOctaveCurve1Keys[3].inTangent = 0.00f; PerOctaveCurve1Keys[3].outTangent = 0.00f; PerOctaveCurve1Keys[4].inTangent = -2.00f; PerOctaveCurve1Keys[4].outTangent = -2.00f; PerOctaveCurve1Keys[5].inTangent = -2.00f; PerOctaveCurve1Keys[5].outTangent = -2.00f; PerOctaveCurve1Keys[6].inTangent = 0.00f; PerOctaveCurve1Keys[6].outTangent = 0.00f; PerOctaveCurve1 = new AnimationCurve(PerOctaveCurve1Keys); perOctaveCurveModifiers.Add(PerOctaveCurve1); AnimationCurve mapPathBlendCurve = new AnimationCurve(); mapPathBlendCurve.AddKey(0.00f, 0.00f); mapPathBlendCurve.AddKey(1.00f, 1.00f); Keyframe[] mapPathBlendCurveKeys = mapPathBlendCurve.keys; mapPathBlendCurveKeys[0].inTangent = 0.00f; mapPathBlendCurveKeys[0].outTangent = 0.00f; mapPathBlendCurveKeys[1].inTangent = 0.00f; mapPathBlendCurveKeys[1].outTangent = 0.00f; mapPathBlendCurve = new AnimationCurve(mapPathBlendCurveKeys); AnimationCurve mapPathHeightCurve = new AnimationCurve(); mapPathHeightCurve.AddKey(0.00f, 1.00f); mapPathHeightCurve.AddKey(1.00f, 1.00f); Keyframe[] mapPathHeightCurveKeys = mapPathHeightCurve.keys; mapPathHeightCurveKeys[0].inTangent = 0.00f; mapPathHeightCurveKeys[0].outTangent = 0.00f; mapPathHeightCurveKeys[1].inTangent = 0.00f; mapPathHeightCurveKeys[1].outTangent = 0.00f; mapPathHeightCurve = new AnimationCurve(mapPathHeightCurveKeys); LBLayer lbBaseLayer01 = new LBLayer(); if (lbBaseLayer01 != null) { lbBaseLayer01.type = LBLayer.LayerType.PerlinBase; lbBaseLayer01.preset = LBLayer.LayerPreset.MountainPeaksBase; lbBaseLayer01.layerTypeMode = LBLayer.LayerTypeMode.Add; lbBaseLayer01.noiseTileSize = 1000; lbBaseLayer01.noiseOffsetX = 0; lbBaseLayer01.noiseOffsetZ = 0; lbBaseLayer01.octaves = 7; lbBaseLayer01.downscaling = 1; lbBaseLayer01.lacunarity = 1.75f; lbBaseLayer01.gain = 0.475f; lbBaseLayer01.additiveAmount = 0.5f; lbBaseLayer01.subtractiveAmount = 0.2f; lbBaseLayer01.additiveCurve = additiveCurve; lbBaseLayer01.subtractiveCurve = subtractiveCurve; lbBaseLayer01.removeBaseNoise = true; lbBaseLayer01.addMinHeight = false; lbBaseLayer01.addHeight = 0f; lbBaseLayer01.restrictArea = false; lbBaseLayer01.areaRect = new Rect(0, 0, 1000, 1000); lbBaseLayer01.interpolationSmoothing = 0; //lbBaseLayer01.heightmapImage = heightmapImage; lbBaseLayer01.imageHeightScale = 1f; lbBaseLayer01.imageCurveModifiers = imageCurveModifiers; lbBaseLayer01.filters = filters; lbBaseLayer01.isDisabled = false; lbBaseLayer01.showLayer = false; lbBaseLayer01.showAdvancedSettings = false; lbBaseLayer01.showCurvesAndFilters = true; lbBaseLayer01.showAreaHighlighter = false; lbBaseLayer01.detailSmoothRate = 0f; lbBaseLayer01.areaBlendRate = 0.5f; lbBaseLayer01.downscaling = 1; lbBaseLayer01.warpAmount = 0f; lbBaseLayer01.warpOctaves = 1; lbBaseLayer01.outputCurveModifiers = outputCurveModifiers; lbBaseLayer01.perOctaveCurveModifiers = perOctaveCurveModifiers; lbBaseLayer01.heightScale = 0.75f; lbBaseLayer01.minHeight = 0f; lbBaseLayer01.imageSource = LBLayer.LayerImageSource.Default; lbBaseLayer01.imageRepairHoles = false; lbBaseLayer01.threshholdRepairHoles = 0f; lbBaseLayer01.mapPathBlendCurve = mapPathBlendCurve; lbBaseLayer01.mapPathHeightCurve = mapPathHeightCurve; lbBaseLayer01.mapPathAddInvert = false; lbBaseLayer01.floorOffsetY = 0f; // Add LBMapPath code here // lbBaseLayer01.lbPath = lbPath; // lbBaseLayer01.lbMapPath = lbMapPath; // NOTE Add the new layer to the landscape meta-data landscape.topographyLayersList.Add(lbBaseLayer01); } } #endregion // Create the terrain topographies landscape.ApplyTopography(false, true); // NOTE // If you have used the LB Editor to first build a test path in a landscape, the path points can be scripted // out and pasted into your runtime script #region LBMapPath Map Path // LBMapPath generated from Landscape Builder at 3:10 PM on Sunday, October 01, 2017 LBMapPath lbMapPath = LBMapPath.CreateMapPath(landscape, landscape.gameObject); if (lbMapPath != null) { lbMapPath.name = "Map Path"; if (lbMapPath.lbPath != null) { lbMapPath.lbPath.pathName = "Map Path"; lbMapPath.mapResolution = 1; lbMapPath.lbPath.blendStart = true; lbMapPath.lbPath.blendEnd = true; lbMapPath.lbPath.pathResolution = 2f; lbMapPath.lbPath.closedCircuit = false; lbMapPath.lbPath.edgeBlendWidth = 0f; lbMapPath.lbPath.removeCentre = false; lbMapPath.lbPath.leftBorderWidth = 0f; lbMapPath.lbPath.rightBorderWidth = 0f; lbMapPath.lbPath.snapToTerrain = true; lbMapPath.lbPath.heightAboveTerrain = 0f; lbMapPath.lbPath.zoomOnFind = true; lbMapPath.lbPath.findZoomDistance = 50f; // Mesh options lbMapPath.lbPath.isMeshLandscapeUV = false; lbMapPath.lbPath.meshUVTileScale = new Vector2(1, 1); lbMapPath.lbPath.meshYOffset = 0.08f; lbMapPath.lbPath.meshEdgeSnapToTerrain = true; lbMapPath.lbPath.meshSnapType = LBPath.MeshSnapType.BothEdges; lbMapPath.lbPath.meshIsDoubleSided = false; lbMapPath.lbPath.meshIncludeEdges = false; lbMapPath.lbPath.meshIncludeWater = false; lbMapPath.lbPath.meshSaveToProjectFolder = false; lbMapPath.meshMaterial = path1meshMaterial; // Path Points lbMapPath.lbPath.positionList.Add(new Vector3(631.6624f, 23.52699f, 825.2574f)); lbMapPath.lbPath.positionList.Add(new Vector3(615.8184f, 9.507171f, 763.9471f)); lbMapPath.lbPath.positionList.Add(new Vector3(592.5421f, 4.510101f, 721.7316f)); lbMapPath.lbPath.positionList.Add(new Vector3(600.6003f, 2.589149f, 679.3673f)); lbMapPath.lbPath.positionList.Add(new Vector3(620.8919f, 2.475228f, 658.526f)); lbMapPath.lbPath.positionList.Add(new Vector3(599.6022f, 2.838308f, 605.2884f)); lbMapPath.lbPath.positionList.Add(new Vector3(575.0403f, 2.714737f, 555.6046f)); lbMapPath.lbPath.positionList.Add(new Vector3(560.4745f, 2.838308f, 472.1874f)); lbMapPath.lbPath.positionList.Add(new Vector3(570.2177f, 3.09073f, 444.6886f)); lbMapPath.lbPath.positionList.Add(new Vector3(570.2177f, 3.299063f, 387.1046f)); lbMapPath.lbPath.positionList.Add(new Vector3(600.3734f, 4.613719f, 311.1418f)); lbMapPath.lbPath.positionList.Add(new Vector3(610.5876f, 6.345493f, 293.1662f)); lbMapPath.lbPath.widthList.Add(14f); lbMapPath.lbPath.widthList.Add(14f); lbMapPath.lbPath.widthList.Add(14f); lbMapPath.lbPath.widthList.Add(14f); lbMapPath.lbPath.widthList.Add(14f); lbMapPath.lbPath.widthList.Add(11.32066f); lbMapPath.lbPath.widthList.Add(14f); lbMapPath.lbPath.widthList.Add(14f); lbMapPath.lbPath.widthList.Add(14f); lbMapPath.lbPath.widthList.Add(14f); lbMapPath.lbPath.widthList.Add(14f); lbMapPath.lbPath.widthList.Add(14f); lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(638.2852f, 23.52699f, 823.5834f)); lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(622.2536f, 9.507171f, 761.4589f)); lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(599.409f, 4.510101f, 720.4888f)); lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(606.8383f, 2.589149f, 682.5374f)); lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(627.8883f, 2.475228f, 658.7487f)); lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(604.7557f, 2.838308f, 602.9471f)); lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(581.7473f, 2.714737f, 553.6004f)); lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(567.473f, 2.838308f, 472.0406f)); lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(577.1524f, 3.09073f, 445.6413f)); lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(577.0537f, 3.299063f, 388.6086f)); lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(606.7752f, 4.613719f, 313.9633f)); lbMapPath.lbPath.positionListLeftEdge.Add(new Vector3(616.454f, 6.345493f, 296.91f)); lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(625.0396f, 23.52699f, 826.9315f)); lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(609.3831f, 9.507171f, 766.4353f)); lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(585.6751f, 4.510101f, 722.9744f)); lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(594.3624f, 2.589149f, 676.1973f)); lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(613.8955f, 2.475228f, 658.3033f)); lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(594.4488f, 2.838308f, 607.6296f)); lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(568.3334f, 2.714737f, 557.6088f)); lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(553.4761f, 2.838308f, 472.3342f)); lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(563.2829f, 3.09073f, 443.736f)); lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(563.3816f, 3.299063f, 385.6005f)); lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(593.9716f, 4.613719f, 308.3203f)); lbMapPath.lbPath.positionListRightEdge.Add(new Vector3(604.7213f, 6.345493f, 289.4224f)); lbMapPath.minPathWidth = lbMapPath.lbPath.GetMinWidth(); lbMapPath.lbPath.RefreshPathHeights(landscape); // Create Mesh for Path if (lbMapPath.lbPath.CreateMeshFromPath(landscape)) { Vector3 meshPosition = new Vector3(0f, lbMapPath.lbPath.meshYOffset, 0f); Transform meshTransform = LBMeshOperations.AddMeshToScene(lbMapPath.lbPath.lbMesh, meshPosition, lbMapPath.lbPath.pathName + " Mesh", lbMapPath.transform, lbMapPath.meshMaterial, true, true); if (meshTransform != null) { } } } } #endregion // Create a list of LBTerrainTexture objects // These contain the textures and normal maps but also the rules for applying them to the terrain landscape.terrainTexturesList = new List <LBTerrainTexture>(); // Populate the list by creating temporary LBTerrainTexture objects and adjusting their settings, // then adding each one into the list // Update the textures LBTerrainTexture tempTerrainTexture = new LBTerrainTexture(); if (tempTerrainTexture != null) { // Forest Floor tempTerrainTexture.texture = texture1; tempTerrainTexture.normalMap = texture1NM; tempTerrainTexture.tileSize = Vector2.one * 15f; tempTerrainTexture.useNoise = false; tempTerrainTexture.texturingMode = LBTerrainTexture.TexturingMode.ConstantInfluence; tempTerrainTexture.strength = 0.04f; landscape.terrainTexturesList.Add(tempTerrainTexture); // Rock Layered tempTerrainTexture = new LBTerrainTexture(); tempTerrainTexture.texture = texture2; tempTerrainTexture.normalMap = texture2NM; tempTerrainTexture.tileSize = Vector2.one * 100f; tempTerrainTexture.texturingMode = LBTerrainTexture.TexturingMode.HeightAndInclination; tempTerrainTexture.minHeight = 400f / terrainHeight; tempTerrainTexture.maxHeight = 1000f / terrainHeight; tempTerrainTexture.minInclination = 30f; tempTerrainTexture.maxInclination = 90f; tempTerrainTexture.useNoise = true; tempTerrainTexture.noiseTileSize = 100f; tempTerrainTexture.strength = 1f; landscape.terrainTexturesList.Add(tempTerrainTexture); // Rock1 tempTerrainTexture = new LBTerrainTexture(); tempTerrainTexture.texture = texture3; tempTerrainTexture.normalMap = texture3NM; tempTerrainTexture.tileSize = Vector2.one * 100f; tempTerrainTexture.texturingMode = LBTerrainTexture.TexturingMode.HeightAndInclination; tempTerrainTexture.minHeight = 10f / terrainHeight; tempTerrainTexture.maxHeight = 1000f / terrainHeight; tempTerrainTexture.minInclination = 30f; tempTerrainTexture.maxInclination = 60f; tempTerrainTexture.useNoise = true; tempTerrainTexture.noiseTileSize = 100f; tempTerrainTexture.strength = 1f; landscape.terrainTexturesList.Add(tempTerrainTexture); // CliffBlue tempTerrainTexture = new LBTerrainTexture(); tempTerrainTexture.texture = texture4; tempTerrainTexture.normalMap = texture4NM; tempTerrainTexture.tileSize = Vector2.one * 100f; tempTerrainTexture.texturingMode = LBTerrainTexture.TexturingMode.Height; tempTerrainTexture.minHeight = 100f / terrainHeight; tempTerrainTexture.maxHeight = 1000f / terrainHeight; tempTerrainTexture.useNoise = true; tempTerrainTexture.noiseTileSize = 10f; tempTerrainTexture.strength = 0.5f; landscape.terrainTexturesList.Add(tempTerrainTexture); // Good Dirt - FUTURE generate Map at runtime from slightly wider path and texture edges //tempTerrainTexture = new LBTerrainTexture(); //tempTerrainTexture.texture = texture5; //tempTerrainTexture.normalMap = texture5NM; //tempTerrainTexture.tileSize = Vector2.one * 10f; //tempTerrainTexture.texturingMode = LBTerrainTexture.TexturingMode.Map; //tempTerrainTexture.map = .... //tempTerrainTexture.mapIsPath = true; //tempTerrainTexture.useAdvancedMapTolerance = false; //tempTerrainTexture.mapInverse = false; //tempTerrainTexture.useNoise = false; //tempTerrainTexture.strength = 1f; //landscape.terrainTexturesList.Add(tempTerrainTexture); // Texture the terrains landscape.ApplyTextures(true, true); } // Add a tree type LBTerrainTree terrainTree1 = new LBTerrainTree(); if (terrainTree1 != null && treePrefab1 != null) { // Set tree type options as required. See LBTerrainTree class constructor for default settings terrainTree1.prefab = treePrefab1.gameObject; terrainTree1.maxTreesPerSqrKm = 140; terrainTree1.minScale = 2f; terrainTree1.maxScale = 3f; terrainTree1.treeScalingMode = LBTerrainTree.TreeScalingMode.RandomScaling; terrainTree1.lockWidthToHeight = true; terrainTree1.treePlacingMode = LBTerrainTree.TreePlacingMode.HeightAndInclination; terrainTree1.minInclination = 0f; terrainTree1.maxInclination = 30f; terrainTree1.minHeight = 0f; terrainTree1.maxHeight = 200f / terrainHeight; terrainTree1.useNoise = false; //// Create a new filter, which will be used for the Stencil Layer //// This demonstrates how to apply a stencil layer to the placement of trees //LBFilter lbFilterTree = LBFilter.CreateFilter(lbStencil, "Hills Layer 1", true); //if (lbFilterTree != null) //{ // // If the list of filters isn't defined, create an empty list // if (terrainTree1.filterList == null) { terrainTree1.filterList = new List<LBFilter>(); } // // Add the Stencil Layer to the list of Tree Filters // terrainTree1.filterList.Add(lbFilterTree); //} // Add the tree type configuration to the landscape landscape.terrainTreesList.Add(terrainTree1); } LBTerrainTree terrainTree2 = new LBTerrainTree(); if (terrainTree2 != null && treePrefab1 != null) { // Set tree type options as required. See LBTerrainTree class constructor for default settings terrainTree2.prefab = treePrefab2.gameObject; terrainTree2.maxTreesPerSqrKm = 140; terrainTree2.minScale = 2f; terrainTree2.maxScale = 3f; terrainTree2.treeScalingMode = LBTerrainTree.TreeScalingMode.RandomScaling; terrainTree2.lockWidthToHeight = true; terrainTree2.treePlacingMode = LBTerrainTree.TreePlacingMode.HeightAndInclination; terrainTree2.minInclination = 0f; terrainTree2.maxInclination = 30f; terrainTree2.minHeight = 0f; terrainTree2.maxHeight = 200f / terrainHeight; terrainTree2.useNoise = false; // Add the tree type configuration to the landscape landscape.terrainTreesList.Add(terrainTree2); } // Populate the landscape with the trees landscape.treesHaveColliders = true; landscape.treePlacementSpeed = LBTerrainTree.TreePlacementSpeed.FastPlacement; landscape.ApplyTrees(true, true); // Add some rock prefabs to the landscape LBLandscapeMesh lbLandscapeMesh = new LBLandscapeMesh(); if (lbLandscapeMesh != null && rockPrefab != null) { lbLandscapeMesh.usePrefab = true; lbLandscapeMesh.prefab = rockPrefab; // Set mesh options as required. See LBLandscapeMesh class constructor for default settings lbLandscapeMesh.maxMeshes = 50; lbLandscapeMesh.meshPlacingMode = LBLandscapeMesh.MeshPlacingMode.ConstantInfluence; // Sink the rocks into the ground by 0.5m lbLandscapeMesh.offset = new Vector3(0f, -0.5f, 0f); // Group the rocks together //lbLandscapeMesh.isClustered = true; //lbLandscapeMesh.clusterDensity = 0.1f; //lbLandscapeMesh.clusterDistance = 10f; landscape.landscapeMeshList.Add(lbLandscapeMesh); landscape.meshPlacementSpeed = LBLandscapeMesh.MeshPlacementSpeed.FastPlacement; //landscape.ApplyMeshes(true, true); } // Get the first Camera Animator in the scene, snap the camera path to the new terrain, // and start moving the camera along the camera path. LBCameraAnimator lbCameraAnimator = LBCameraAnimator.GetFirstCameraAnimatorInLandscape(landscape); if (lbCameraAnimator == null) { Debug.LogWarning("GetFirstCameraAnimatorInLandscape returned null"); } else { if (lbMapPath != null) { if (!lbCameraAnimator.cameraPath.ImportMapPathPoints(lbMapPath)) { Debug.LogWarning("Could not make camera animator travel along new Map Path."); } } // Get the LBPath instance which contains the points along the camera path LBPath lbPath = lbCameraAnimator.cameraPath.lbPath; if (lbPath == null) { Debug.LogWarning("Could not find the camera path instance for the animator"); } else { // Optionally update the path points to match the terrain lbPath.heightAboveTerrain = 5f; lbPath.snapToTerrain = true; lbPath.RefreshPathHeights(landscape); // Start the camera moving from the start of the path. lbCameraAnimator.BeginAnimation(true, 0f); } } // Display the total time taken to generate the landscape (usually for debugging purposes) Debug.Log("Time taken to generate landscape: " + (Time.realtimeSinceStartup - generationStartTime).ToString("00.00") + " seconds."); }