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
        }
        public void AddDisturbance(Vector3 pos, float radius, float force)
        {
            int minX = GetGridIndex(pos.x - radius);
            int maxX = GetGridIndex(pos.x + radius);
            int minY = GetGridIndex(pos.z - radius);
            int maxY = GetGridIndex(pos.z + radius);

            for (int x = minX; x <= maxX; x++)
            {
                for (int y = minY; y <= maxY; y++)
                {
                    TerrainGrassTile tile = rollMap.Get(x, y);
                    if (tile)
                    {
                        tile.AddDisturbance(pos, radius, force);
                    }
                }
            }
        }
        //新滚动出来的格子
        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 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);
            }
        }