我有一个建筑放置项目,不适用于 3D 房屋对象。这些对象都具有刚体和盒子碰撞器组件,而只有房屋预制对象具有子对象。 我的脚本是这样的:
BuildingManager 脚本:
public class BuildingManager : MonoBehaviour
{
private GameObject pendingObject;
[SerializeField] private Material[] materials;
public bool canPlace;
void Update()
{
if (pendingObject != null)
{
UpDateMaterials();
pendingObject.transform.position = pos;
if (Input.GetMouseButtonDown(0) && canPlace)
{
PlaceObject();
}
}
}
public void PlaceObject()
{
pendingObject.GetComponent<MeshRenderer>().material = materials[2];
pendingObject = null;
}
public void UpDateMaterials()
{
if (canPlace)
{
pendingObject.GetComponent<MeshRenderer>().material = materials[0];
}
if (!canPlace)
{
pendingObject.GetComponent<MeshRenderer>().material = materials[1];
}
}
}
检查放置脚本:
public class CheckPlacement : MonoBehaviour
{
BuildingManager buildingManager;
void Start()
{
buildingManager = GameObject.Find("BuildingManager").GetComponent<BuildingManager>();
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Building"))
{
Debug.Log("Can't Place Building");
buildingManager.canPlace = false;
}
}
private void OnTriggerExit(Collider other)
{
if (other.gameObject.CompareTag("Building"))
{
Debug.Log("Can Place Building");
buildingManager.canPlace = true;
}
}
}
这些脚本可以很好地与 Unity 的默认 3D 对象配合使用,例如 3D 胶囊、球体、盒子对象。例如,我尝试将胶囊对象与已经在地面(平面)上的房屋对象重叠。当胶囊对象与房屋对象碰撞时,它会变成透明的红色,当我将它拖到地面时,它会变成透明的绿色。
欢迎任何建议...
由于房屋对象有多个子对象,因此您需要更新所有网格渲染器。为此,请使用 GetComponentsInChildren 获取所有网格渲染器,并在更改材质时循环遍历这些渲染器。如果对象没有改变,您可以缓存网格渲染器以避免多次调用 GetComponents。您还可以添加待处理状态,这样就可以避免每帧更新材质,即使它们没有更改状态。我将排除该部分,因为它需要一些解释,并且可能会使这个答案变得复杂。
private MeshRenderer[] meshRenderers;
private void Awake()
{
meshRenderers = pendingObject.GetComponentsInChildren<MeshRenderer>();
}
...
private void UpdateMaterials()
{
if (canPlace)
{
UpdateMeshRenderersMaterial(materials[0]);
}
else
{
UpdateMeshRenderersMaterial(materials[1]);
}
}
private void PlaceObject()
{
UpdateMeshRenderersMaterial(materials[2]);
}
private void UpdateMeshRenderersMaterial(Material material)
{
foreach (var meshRenderer in meshRenderers)
{
meshRenderer.material = material;
}
}