我有一个生成自定义复合网格的脚本。但是当用户编辑生成复合网格的脚本的属性时,我想删除先前创建的网格。我必须按照脚本来完成这个:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class BasicVoidVisualizationProperties : MonoBehaviour {
public Vector3 Dimensions;
public float Thickness;
public float Spacing;
private GameObject[] Corners = new GameObject[8];
private EdgeBuilder[] Edges = new EdgeBuilder[12];
// Use this for initialization
void Start () {
for (int i = 0; i < Corners.Length; i++)
{
Corners[i] = Instantiate(Resources.Load("cube") as GameObject);
Corners[i].transform.SetParent(this.transform);
}
RebuildCorners(Corners, Dimensions, Thickness);
for (int i = 0; i < Edges.Length; i++)
{
Edges[i] = new EdgeBuilder(this.transform);
}
RebuildEdges(Edges, Corners);
}
// Update is called once per frame
void Update () {
}
private void RebuildCorners(GameObject[] Corners, Vector3 Dimensions, float Thickness)
{
Corners[0].transform.localScale = new Vector3(Thickness, Thickness, Thickness);
Corners[0].transform.position = this.transform.position + new Vector3(Thickness/2, Thickness /2, Thickness/2);
Corners[1].transform.localScale = new Vector3(Thickness, Thickness, Thickness);
Corners[1].transform.position = this.transform.position + new Vector3(Dimensions.x - Thickness /2, Thickness /2, Thickness/2);
Corners[2].transform.localScale = new Vector3(Thickness, Thickness, Thickness);
Corners[2].transform.position = this.transform.position + new Vector3(Dimensions.x - Thickness /2, Thickness/2, Dimensions.z - Thickness /2);
Corners[3].transform.localScale = new Vector3(Thickness, Thickness, Thickness);
Corners[3].transform.position = this.transform.position + new Vector3(Thickness/2, Thickness/2, Dimensions.z - Thickness /2);
Corners[4].transform.localScale = new Vector3(Thickness, Thickness, Thickness);
Corners[4].transform.position = this.transform.position + new Vector3(Thickness/2, Dimensions.y - Thickness/2, Thickness/2);
Corners[5].transform.localScale = new Vector3(Thickness, Thickness, Thickness);
Corners[5].transform.position = this.transform.position + new Vector3(Dimensions.x - Thickness /2, Dimensions.y - Thickness/2, Thickness/2);
Corners[6].transform.localScale = new Vector3(Thickness, Thickness, Thickness);
Corners[6].transform.position = this.transform.position + new Vector3(Dimensions.x - Thickness /2, Dimensions.y - Thickness/2, Dimensions.z - Thickness /2);
Corners[7].transform.localScale = new Vector3(Thickness, Thickness, Thickness);
Corners[7].transform.position = this.transform.position + new Vector3(Thickness/2, Dimensions.y - Thickness/2, Dimensions.z - Thickness /2);
}
private void RebuildEdges(EdgeBuilder[] Edges, GameObject[] Corners)
{
Edges[0].RebuildEdge(Corners[0].transform.position, Corners[1].transform.position, Thickness, Spacing, Direction.right);
Edges[1].RebuildEdge(Corners[3].transform.position, Corners[2].transform.position, Thickness, Spacing, Direction.right);
Edges[2].RebuildEdge(Corners[4].transform.position, Corners[5].transform.position, Thickness, Spacing, Direction.right);
Edges[3].RebuildEdge(Corners[7].transform.position, Corners[6].transform.position, Thickness, Spacing, Direction.right);
Edges[4].RebuildEdge(Corners[0].transform.position, Corners[4].transform.position, Thickness, Spacing, Direction.up);
Edges[5].RebuildEdge(Corners[1].transform.position, Corners[5].transform.position, Thickness, Spacing, Direction.up);
Edges[6].RebuildEdge(Corners[2].transform.position, Corners[6].transform.position, Thickness, Spacing, Direction.up);
Edges[7].RebuildEdge(Corners[3].transform.position, Corners[7].transform.position, Thickness, Spacing, Direction.up);
Edges[8].RebuildEdge(Corners[0].transform.position, Corners[3].transform.position, Thickness, Spacing, Direction.forward);
Edges[9].RebuildEdge(Corners[1].transform.position, Corners[2].transform.position, Thickness, Spacing, Direction.forward);
Edges[10].RebuildEdge(Corners[4].transform.position, Corners[7].transform.position, Thickness, Spacing, Direction.forward);
Edges[11].RebuildEdge(Corners[5].transform.position, Corners[6].transform.position, Thickness, Spacing, Direction.forward);
}
void OnValidate()
{
if(Corners[0] != null) RebuildCorners(Corners, Dimensions, Thickness);
if(Corners[0] != null && Edges[0] != null)
{
foreach (var edge in Edges)
{
foreach (var eb in edge.EdgeBlocks)
{
StartCoroutine(DestroyEdgeElement(eb));
}
}
RebuildEdges(Edges, Corners);
}
}
private IEnumerator DestroyEdgeElement(GameObject go)
{
yield return new WaitForEndOfFrame();
Debug.Log("DESTROYED"); // IS NEVER CALLED (never logs to console)
DestroyImmediate(go);
}
private class EdgeBuilder
{
private Transform Parent;
public List<GameObject> EdgeBlocks = new List<GameObject>();
public EdgeBuilder(Transform parent)
{
Parent = parent;
}
private List<GameObject> CalculateEdgeBlocks(Vector3 origin, Vector3 end, float thickness, float spacing)
{
List<GameObject> elements = new List<GameObject>();
var dist = Vector3.Distance(origin, end) - thickness;
var blocks = (int)Mathf.Round((dist - (thickness + spacing * 2)) / (thickness + spacing));
for (int i = 0; i < blocks; i++)
{
var el = Instantiate(Resources.Load("cube") as GameObject);
el.transform.localScale = new Vector3(thickness, thickness, thickness);
el.transform.SetParent(Parent);
elements.Add(el);
}
return elements;
}
public void RebuildEdge(Vector3 origin, Vector3 end, float thickness, float spacing, Direction dir)
{
// if(EdgeBlocks.Count > 0) ClearEdge();
EdgeBlocks = CalculateEdgeBlocks(origin, end, thickness, spacing);
if (dir == Direction.up)
{
var firstEl = new Vector3(origin.x, origin.y + thickness + spacing, origin.z);
foreach (var el in EdgeBlocks)
{
el.transform.position = firstEl;
firstEl += new Vector3(0, thickness + spacing, 0);
}
}
else if(dir == Direction.right)
{
var firstEl = new Vector3(origin.x + thickness + spacing, origin.y, origin.z);
foreach (var el in EdgeBlocks)
{
el.transform.position = firstEl;
firstEl += new Vector3(thickness + spacing, 0, 0);
}
}
else if(dir == Direction.forward)
{
var firstEl = new Vector3(origin.x, origin.y, origin.z + thickness + spacing);
foreach (var el in EdgeBlocks)
{
el.transform.position = firstEl;
firstEl += new Vector3(0, 0, thickness + spacing);
}
}
}
// private void ClearEdge()
// {
// foreach (var eb in EdgeBlocks)
// {
// DestroyImmediate(eb, true);
// }
// EdgeBlocks.Clear();
// }
}
private enum Direction
{
up,
right,
forward
}
}
我一直存在的问题是从未调用过Debug.log("Destroyed");
(我没看到Debug.log执行)。为什么会这样?
为什么使用你可能会问的协程,请参阅下面的链接,了解我使用协程的原因:Coroutine to destroy object from editor event
如果需要更多信息,请告诉我,以便我澄清!
问题来自WaitForEndOfFrame
。对于原因并不完全有信心,但似乎在编辑器模式下此操作不会返回,而不是处于播放模式。
如果你改用yield return null
,它应该达到同样的效果。
答案可能对执行顺序图表中的其他人显而易见:https://docs.unity3d.com/uploads/Main/monobehaviour_flowchart.svg