所以我最近发现了Unity中上下文菜单的使用。我有一个带有一堆三角形的网格,每个三角形有 3 个顶点。
我有一个可编写脚本的对象,
LevelData
[CreateAssetMenu(fileName = "LevelData", menuName = "Tactics/LevelData", order = 0)]
public class LevelData : ScriptableObject {
public List<Tri> AllTris = new List<Tri>();
public List<Vertex> AllVerts = new List<Vertex>();
public Vertex GetVertexFromVector3(Vector3 position)
{
foreach (Vertex v in AllVerts)
{
if (v.pos == position)
{
return v;
}
}
return null;
}
}
我设置了 AllTris 和 AllVerts:
[ContextMenu("Find All Vertices")]
void GetAllVerts(){
mesh = GetComponent<MeshFilter>().sharedMesh;
levelData.AllVerts = new List<Vertex>();
for (int t = 0; t < mesh.vertices.Length; t++)
{
levelData.AllVerts.Add(new Vertex(t, mesh.vertices[t]));
}
}
[ContextMenu("Find All Triangles")]
void GetAllTris(){
mesh = GetComponent<MeshFilter>().sharedMesh;
levelData.AllTris = new List<Tri>();
List<Vertex> verts = levelData.AllVerts;
for (int t = 0; t < mesh.triangles.Length; t+=3)
{
Vertex v1 = verts[mesh.triangles[t+0]];
Vertex v2 = verts[mesh.triangles[t+1]];
Vertex v3 = verts[mesh.triangles[t+2]];
levelData.AllTris.Add(new Tri( (t+3)/3 - 1, v1, v2, v3 ));
}
}
我希望的是,当我移动 AllVerts 中的顶点时,这会影响 AllTris 中的该顶点
我创建这个是为了测试它:
[ContextMenu("Test relationship between AllVerts and AllTris")]
void MoveVertexAndLogTriangle(){
Debug.Log(levelData.AllTris.First().First.pos);
Vertex v1 = levelData.GetVertexFromVector3(levelData.AllTris.First().First.pos);
v1.pos += Vector3.up;
Debug.Log(levelData.AllTris.First().First.pos);
}
这在我按下播放之前就起作用了。它记录向下移动的顶点。
但是在运行时,它不起作用。我的猜测是 AllVerts 和 AllTris 中的顶点之间的链接丢失了。但我真的不知道。
我将 GetAllTris 和 GetAllVerts 都放在 start 方法中,它按预期工作,如下所示:
private void Start() {
mesh = GetComponent<MeshFilter>().mesh;
levelData.AllVerts = new List<Vertex>();
for (int t = 0; t < mesh.vertices.Length; t++)
{
//do we need an id?
levelData.AllVerts.Add(new Vertex(t, mesh.vertices[t]));
}
levelData.AllTris = new List<Tri>();
for (int t = 0; t < mesh.triangles.Length; t+=3)
{
Vertex v1 = levelData.AllVerts[mesh.triangles[t+0]];
Vertex v2 = levelData.AllVerts[mesh.triangles[t+1]];
Vertex v3 = levelData.AllVerts[mesh.triangles[t+2]];
levelData.AllTris.Add(new Tri( (t+3)/3 - 1, v1, v2, v3 ));
}
MoveVertexAndLogTriangle();
}
但我希望能够预先计算所有这些以节省性能。
有谁知道为什么从可编写脚本的对象加载 tris 和 verts 列表不起作用?有办法解决这个问题吗?预先感谢!
我想知道带有 Id 的东西是否可以工作?
我看不到您对
Vertex
或 Tri
的实现。
但一般来说:当您在 Unity 中序列化某些不是
UnityEngine.Object
类型而只是“正常”[Serializable]
类型的内容时,它始终会按 BY VALUE 进行序列化。
请记住,
ScriptableObject
(与场景和预制件等大多数其他资产一样)基本上只是一个包含文本的 YAML 文件。
现在,当从该 YAML 文件加载
ScriptableObject
时,解析器无法判断 AllTris
中的最初条目与 c#
中元素的相同 AllVerts
实例。
它只会将两者单独反序列化为两个单独的实例,没有任何连接。
它适用于
UnityEngine.Object
引用,因为 Unity 序列化器专门通过存储在 .meta
文件中的 GUID 来处理这些引用(这就是为什么如果丢失 .meta
文件,所有引用都会丢失)。
那么现在该怎么办呢?
说实话,我还不太清楚你到底想做什么。但您必须确保使用不同的方式以独特的方式引用/识别顶点。
=> 为什么不简单地坚持 Unity 的做法:不是将实际的
Vertex
实例存储到 Triangle
中,而是将顶点的 index 存储在整个 vertices
数组中。
您可以执行相同的操作,并在您的
Tri
中仅将三个索引传递到 Vertex
中的 AllVerts
实例。
这可能也会回答
//我们需要一个id吗?
如果您只是按索引进行操作 - 不,不是真的。