Unity3D:同步网格更新

时间:2014-03-21 13:29:23

标签: unity3d mesh material

我遇到了关于更新几种网格物质的问题。 我正在开发一个投影映射应用程序,目前我的表面上有3个平面,每个平面有4个点定义它们在空间中的位置(每个点,名为DestinationPoint位于代表网格的平面角的边缘)。通过移动(手动,使用OnMouseDown()和OnMouseDrag()函数)每个点,网格会相应更新,以便每个角跟随每个点(目标与真实世界表面匹配。)

因此我不必每次都进行此校准,我将这12个点(3个平面* 4个点)的值(本地位置属性)保存在XML文件中。 XML文件的保存/加载过程工作得很好,所有点都自动移动到以前保存在XML文件中的位置。 Unity更新每个网格材质时会出现问题,它只更新一个网格。

例如,这是保存的场景,保存到XML文件中,有3个平面,每个平面有4个点由白色球体表示。

Scene as saved in XML

这是从XML文件加载的场景。点移动到正确的位置,但网格不会更新。

Scene as loaded from 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:对文字墙感到抱歉!

1 个答案:

答案 0 :(得分:0)

刚刚解决了它:

yield返回新的WaitForSeconds(.25f);

LoadScenario()函数内部。似乎对于循环比更新函数更快,因此只有For循环的最后一个成员才真正更新。