void Update() { Vector3 centerPos = Vector3.zero; bool bPosValid = false; if (Camera.main) { centerPos = Camera.main.transform.position; bPosValid = true; } #if QINSHI if (CameraManager.Instance.controller.GetFollowTargetObject() != null) { centerPos = CameraManager.Instance.controller.GetFollowTargetObject().transform.position; bPosValid = true; } #endif if (bPosValid) { int currentX = GetGridStartIndex(centerPos.x); int currentY = GetGridStartIndex(centerPos.z);//摄像机当前所处的格子 rollMap.RollTo(currentX, currentY); if (taskList.Count > 0) { int nearestIndex = GetNearestTaskIndex(centerPos, taskList); TerrainGrassTile tile = taskList[nearestIndex]; taskList.RemoveAt(nearestIndex); float top = 0; float bottom = 10000; tile.gameObject.SetActive(true); for (int i = 0; i < tile.grassList.Count; i++) { TerrainGrass grass = tile.grassList[i]; bool hasMesh = grass.CreateMesh(); if (hasMesh) { grass.gameObject.SetActive(true); top = Mathf.Max(grass.top, top); bottom = Mathf.Min(grass.bottom, bottom); } } tile.UpdateBox(top, bottom); //正在生成时,慢慢的修改可视距离,减小跳动 for (int i = 0; i < materials.Length; i++) { materials[i].SetFloat("_ViewDistance", (tile.Center - centerPos).magnitude - PatchSize / 2.0f); } } } Shader.SetGlobalFloat("_GrassTime", Time.time); #if UNITY_EDITOR UpdateGrassShaderParams(); #endif }
//新滚动出来的格子 TerrainGrassTile CreateNode(int x, int y) { if (x >= 0 && y >= 0 && x < PatchNumX && y < PatchNumX) { bool anyLayer = false; for (int l = 0; l < details.Length; l++) { if (patchVisible[x, y, l]) { anyLayer = true; } } if (anyLayer) { TerrainGrassTile tile = tilePool.New();//从池子里申请一个 tile.transform.SetParent(transform, false); tile.rect = new Rect(x * PatchSize, y * PatchSize, PatchSize, PatchSize); tile.grassList.Clear(); for (int l = 0; l < details.Length; l++) { if (patchVisible[x, y, l]) { TerrainGrass grass = meshPool.New(); grass.transform.SetParent(tile.transform, false); grass.transform.localPosition = Vector3.zero; grass.Reset(materials[l], l); grass.rect = tile.rect; grass.patchX = x * resolutionPerPatch; grass.patchY = y * resolutionPerPatch; grass.resolutionPerPatch = resolutionPerPatch; grass.detailDensity = detailDensity; tile.AddGrass(grass); } } taskList.Add(tile); return(tile); } } return(null); }
public void AddGrass(TerrainGrass grass) { grassList.Add(grass); }
public void OnEnable() { m_instance = this; #if QINSHI subscribes.Add(Utility.EventSystem.Subscribe <Vector3, float, float>("add_disturbance", "grass", AddDisturbance)); #endif terrain = GetComponent <Terrain>(); terrainData = terrain.terrainData; terrain.detailObjectDistance = 0; UpdatePatchVisible(); recyle = new GameObject("recyle").transform; recyle.SetParent(transform, false); details = terrain.terrainData.detailPrototypes; materials = new Material[details.Length]; for (int i = 0; i < details.Length; i++) { materials[i] = new Material(material);// new Material(shader); materials[i].mainTexture = details[i].prototypeTexture; materials[i].SetFloat("_GrassMinWidth", details[i].minWidth); materials[i].SetFloat("_GrassMaxWidth", details[i].maxWidth); materials[i].SetFloat("_GrassMinHeight", details[i].minHeight); materials[i].SetFloat("_GrassMaxHeight", details[i].maxHeight); materials[i].SetColor("_WavingTint", terrain.terrainData.wavingGrassTint); materials[i].SetColor("_GrassColor", (details[i].dryColor + details[i].healthyColor) * 0.5f); materials[i].SetFloat("_ViewDistance", grassViewDistance); materials[i].SetVector("_TerrainOffsetSize", new Vector4(terrain.transform.position.x, terrain.transform.position.z, terrainData.size.x, terrainData.size.z)); if (terrain.lightmapIndex >= 0 && terrain.lightmapIndex < LightmapSettings.lightmaps.Length) { materials[i].SetTexture("_Lightmap", LightmapSettings.lightmaps[terrain.lightmapIndex].lightmapColor); } int[,] density = terrain.terrainData.GetDetailLayer(0, 0, terrain.terrainData.detailResolution, terrain.terrainData.detailResolution, i); short[,] sDensity = new short[density.GetLength(0), density.GetLength(1)]; for (int x = 0; x < density.GetLength(0); x++) { for (int y = 0; y < density.GetLength(1); y++) { sDensity[x, y] = (short)density[x, y]; } } detailDensity.Add(sDensity); } UpdateGrassShaderParams(); meshPool = new Pool <TerrainGrass>(); meshPool.funNew = () => { GameObject obj = new GameObject("grass"); obj.transform.SetParent(transform); //obj.layer = terrain.gameObject.layer; TerrainGrass grass = obj.AddComponent <TerrainGrass>(); grass.Init(terrain, soft); return(grass); }; tilePool = new Pool <TerrainGrassTile>(); tilePool.funNew = () => { GameObject obj = new GameObject("tile"); obj.transform.SetParent(transform); TerrainGrassTile tile = obj.AddComponent <TerrainGrassTile>(); return(tile); }; rollNum = (int)((grassViewDistance * 2 - 0.1f) / PatchSize) + 1; rollMap = new RollMap <TerrainGrassTile>(rollNum, rollNum, -10000, -10000); rollMap.funDelete = (TerrainGrassTile tile) => { if (tile) { tile.gameObject.SetActive(false); tile.transform.SetParent(recyle, false); tilePool.Recycle(tile); for (int i = 0; i < tile.grassList.Count; i++) { meshPool.Recycle(tile.grassList[i]); tile.transform.SetParent(recyle, false); } taskList.RemoveAll((TerrainGrassTile item) => item == tile); } }; rollMap.funNew = CreateNode; if (terrain.lightmapIndex >= 0 && terrain.lightmapIndex < LightmapSettings.lightmaps.Length) { Shader.SetGlobalTexture("_GrassLightmap", LightmapSettings.lightmaps[terrain.lightmapIndex].lightmapColor); } }