我面临着一个关于更新几个meshes材质的问题。我正在开发一个投影贴图应用,目前我的表面上有3个平面,每个平面有4个点,定义了它们在空间中的位置(每个点,命名为DestinationPoint位于代表网格的平面角的边缘)。通过移动(手动,使用OnMouseDown()和OnMouseDrag()函数)每个点,网格会相应地更新,使每个角跟随每个点(目标是与真实世界的表面相匹配)。
为了避免每次都要做这样的校准,我将这12个点(3个平面*4个点)的值(局部位置属性)保存在一个XML文件中。XML文件的保存加载过程运行得很好,所有的点都会自动移动到之前保存在XML文件中的位置。问题出现在Unity更新每个网格材质的时候,它只更新一个网格。
例如,这是保存的场景,保存到XML文件中,有3个平面,每个平面有4个点,用白色球体表示。
这是从XML文件中加载的场景。这些点被移动到了正确的位置,但网格却没有更新。
加载XML文件的函数如下。
void LoadScenario(){
filePath = Application.dataPath + "/XmlData/"+scenario+".xml";
XmlReader reader = XmlReader.Create(filePath);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(reader);
XmlNodeList Surfaces = xmlDoc.GetElementsByTagName("Surfaces");
/* XML file structure
*
* <Surfaces>
<ProjectionSurface1>
<DestinationPoints>
<DP0>
<Position>-8.28037,18.33852,10.06745</Position>
</DP0>
<DP1>
<Position>-31.55436,-3.485761,3.270439</Position>
</DP1>
<DP2>
<Position>38.00045,-1.380948,4.482903</Position>
</DP2>
<DP3>
<Position>30.65092,19.90506,10.96985</Position>
</DP3>
</DestinationPoints>
</ProjectionSurface1>
</Surfaces>
*/
for(int surface = 0; surface < Surfaces.Count; surface++){
// There is only 1 type of Surface, so only 1 node for now...
XmlNode NodeSurface = Surfaces.Item(surface);
// Get List of Projection Surfaces
XmlNodeList allProjSurfaces = NodeSurface.ChildNodes;
//Debug.Log("Number of Proj Surfaces = " + allProjSurfaces.Count);
for(int projSurf = 0 ; projSurf < allProjSurfaces.Count; projSurf++){
XmlNode nodeProjSurface = allProjSurfaces.Item(projSurf);
string activeProjSurfStr = nodeProjSurface.Name;
//Debug.Log("Projection Surface: " + nodeProjSurface.Name);
// Get the DestinationPoints node
XmlNode nodeDestPoints = nodeProjSurface.FirstChild;
// Get all DPs node list
XmlNodeList allDPs = nodeDestPoints.ChildNodes;
for(int dp = 0; dp < allDPs.Count; dp++){
XmlNode nodeDP = allDPs.Item(dp);
XmlNode nodePos = nodeDP.FirstChild;
string dpStr = nodeDP.Name;
Debug.Log("dpStr: " + dpStr);
string[] split_position = nodePos.InnerText.Split(',');
/*Debug.Log("ProjectionSurface : " + nodeProjSurface.Name +
" with " + nodeDP.Name +
" ,with PosX: " + float.Parse(split_position[0]) +
" ,with PosY: " + float.Parse(split_position[1]) +
" ,with PosZ: " + float.Parse(split_position[2]));*/
float xmlXPos = float.Parse(split_position[0]);
float xmlYPos = float.Parse(split_position[1]);
float xmlZPos = float.Parse(split_position[2]);
Vector3 xmlPosVec = new Vector3(xmlXPos, xmlYPos, xmlZPos);
List <GameObject> dpList = sleManager.listOfDestPoints;
int multiplier = destControl.ReturnModifier(projSurf+1);
dpList[dp+multiplier].transform.localPosition = xmlPosVec;
GameObject dpActiveObj = dpList[dp+multiplier].gameObject;
}
}
}
reader.Close();
// Test to force an update to all 3 projection surfaces meshes
GameObject dp0 = sleManager.listOfDestPoints[0];
GameObject dp4 = sleManager.listOfDestPoints[4];
GameObject dp8 = sleManager.listOfDestPoints[8];
destControl.Run(dp0);
Debug.Log("0");
destControl.Run(dp4);
destControl.Run(dp8);
}
}
我最后使用的函数Run(GameObj obj)的主要目的是更新参数中obj的材质属性,如下所示。
public void Run(GameObject dpObj){
Debug.Log("Run com arg obj name: " + dpObj.gameObject.name);
manager.indexChanged = true;
string activeDPStr = dpObj.name;
string activeProjSurfStr = dpObj.transform.root.ToString();
manager.activeProjSurfObj = ReturnActiveProjSurf(dpObj);
manager.activePlaneObj = ReturnActivePlaneObj(manager.activeProjSurfObj);
string activePlaneStr = manager.activePlaneObj.name;
manager.activeProjSurf = int.Parse(activeProjSurfStr[17].ToString());
manager.modifier = ReturnModifier(manager.activeProjSurf);
manager.activeIndex = int.Parse(activeDPStr[2].ToString()) + manager.modifier;
manager.meshMaterial = manager.activePlaneObj.renderer.material;
}
列表 "listOfDestPoints "包含了所有现有的目标点。请记住每个平面有4个点,所以列表中每4个成员,目标平面就会发生变化.现在,如果我尝试运行do。
destControl.Run(dp0); // Updates Plane 1, works just fine.
但如果我试着去做:
destControl.Run(dp0);
destControl.Run(dp4); // Does not update Plane 1, only Plane 2.
p. s: 对不起,我写了这么多文字
刚刚用解决了。
yield return new WaitForSeconds(.25f);
在LoadScenario()函数里面。貌似For循环比更新函数快,所以只有For循环的最后一个成员是真正更新的。