CultivationOfBrewing-2/Assets/Scripts/HQB/SorghumFieldController.cs

182 lines
6.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SorghumFieldController : MonoBehaviour
{
// 原有字段保持不变
public MeshRenderer fieldArea;
public bool randomRotate = false;
public float rowDistance = 1;
public float strainDistance = 1;
public float diseasedRate = 0;
// 新增动态渲染相关字段
[Header("Dynamic Rendering")]
public int chunksPerAxis = 10; // 每轴区块数量
private Dictionary<Vector2Int, List<GameObject>> chunkMap = new Dictionary<Vector2Int, List<GameObject>>();
private float chunkSize;
private Bounds fieldBounds;
public void InitSorghum(float rowDistance, float strainDistance, float diseasedRate, bool randomRotate = false)
{
GameObject sorghumPrefab = Resources.Load<GameObject>("Prefabs/高粱预制体");
if (sorghumPrefab == null || fieldArea == null)
{
Debug.LogError("预制体或农田区域未分配!");
return;
}
BoxCollider fieldCollider = fieldArea.GetComponent<BoxCollider>();
if (fieldCollider == null)
{
Debug.LogError("农田区域缺少BoxCollider组件");
return;
}
// 初始化农田参数
fieldBounds = fieldCollider.bounds;
chunkSize = Mathf.Max(fieldBounds.size.x, fieldBounds.size.z) / chunksPerAxis;
// 预生成所有高粱并分配到区块
GenerateSorghumGrid(sorghumPrefab, rowDistance, strainDistance);
ProcessDiseasedPlants(diseasedRate, randomRotate);
// 初始隐藏所有高粱
SetAllChunksVisibility(false);
}
void GenerateSorghumGrid(GameObject prefab, float rowDist, float strainDist)
{
for (float x = fieldBounds.min.x; x <= fieldBounds.max.x; x += rowDist)
{
for (float z = fieldBounds.min.z; z <= fieldBounds.max.z; z += strainDist)
{
Vector3 spawnPos = new Vector3(x, fieldBounds.min.y, z);
GameObject obj = Instantiate(prefab, spawnPos, Quaternion.identity, fieldArea.transform);
AddToChunk(obj);
}
}
}
void AddToChunk(GameObject sorghum)
{
Vector2Int chunkCoord = new Vector2Int(
Mathf.FloorToInt((sorghum.transform.position.x - fieldBounds.min.x) / chunkSize),
Mathf.FloorToInt((sorghum.transform.position.z - fieldBounds.min.z) / chunkSize)
);
if (!chunkMap.ContainsKey(chunkCoord))
{
chunkMap[chunkCoord] = new List<GameObject>();
}
chunkMap[chunkCoord].Add(sorghum);
}
void ProcessDiseasedPlants(float diseasedRate, bool randomRotate)
{
SorghumController[] sorghumControllers = FindObjectsOfType<SorghumController>();
int DisCount = (int)(sorghumControllers.Length * diseasedRate);
for (int i = 0; i < DisCount; i++)
{
int iter = (int)(sorghumControllers.Length * UnityEngine.Random.value);
if (iter >= sorghumControllers.Length) iter = sorghumControllers.Length - 1;
if (iter < 0) iter = 0;
sorghumControllers[iter].Init(SorghumState.Diseased, randomRotate);
sorghumControllers[iter] = sorghumControllers[sorghumControllers.Length - 1];
SorghumController[] newArry = new SorghumController[sorghumControllers.Length - 1];
Array.Copy(sorghumControllers, newArry, sorghumControllers.Length - 1);
}
foreach (var item in sorghumControllers)
{
item.Init(SorghumState.Healthy, randomRotate);
SetRenderersEnabled(false, item.gameObject);
//item.gameObject.GetComponentInChildren<Renderer>().enabled = false; // 初始隐藏
}
}
void SetAllChunksVisibility(bool visible)
{
foreach (var chunk in chunkMap.Values)
{
foreach (GameObject plant in chunk)
{
SetRenderersEnabled(visible, plant);
}
}
}
void Start()
{
InitSorghum(rowDistance, strainDistance, diseasedRate, randomRotate);
StartCoroutine(VisibilityUpdateRoutine());
}
IEnumerator VisibilityUpdateRoutine()
{
WaitForSeconds wait = new WaitForSeconds(0.1f); // 每0.1秒更新一次
Plane[] frustumPlanes = new Plane[6];
Camera mainCam = Camera.main;
while (true)
{
if (mainCam != null)
{
frustumPlanes = GeometryUtility.CalculateFrustumPlanes(mainCam);
foreach (var chunk in chunkMap)
{
Bounds chunkBounds = CalculateChunkBounds(chunk.Key);
bool shouldVisible = GeometryUtility.TestPlanesAABB(frustumPlanes, chunkBounds);
SetChunkVisibility(chunk.Key, shouldVisible);
}
}
yield return wait;
}
}
Bounds CalculateChunkBounds(Vector2Int coord)
{
Vector3 min = new Vector3(
fieldBounds.min.x + coord.x * chunkSize,
fieldBounds.min.y,
fieldBounds.min.z + coord.y * chunkSize
);
return new Bounds(
min + new Vector3(chunkSize / 2, 0, chunkSize / 2),
new Vector3(chunkSize, fieldBounds.size.y, chunkSize)
);
}
void SetChunkVisibility(Vector2Int coord, bool visible)
{
if (chunkMap.TryGetValue(coord, out List<GameObject> plants))
{
foreach (GameObject plant in plants)
{
SetRenderersEnabled(visible, plant);
//plant.GetComponentInChildren<Renderer>().enabled = visible;
}
}
}
private void SetRenderersEnabled(bool enabled, GameObject go)
{
GameObject obj = go;
if (obj == null) obj = this.gameObject;
Renderer[] renderers = go.GetComponentsInChildren<Renderer>();
foreach (Renderer r in renderers)
{
r.enabled = enabled;
}
LODGroup lg = go.GetComponent<LODGroup>();
Debug.Log("LOD组数" + lg.GetLODs().Length);
//Renderer[] rd = lg.GetLODs();
}
}