Unity3D:同步更新网格

问题描述 投票:0回答:1

我面临着一个关于更新几个meshes材质的问题。我正在开发一个投影贴图应用,目前我的表面上有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: 对不起,我写了这么多文字

unity3d mesh
1个回答
0
投票

刚刚用解决了。

yield return new WaitForSeconds(.25f);

在LoadScenario()函数里面。貌似For循环比更新函数快,所以只有For循环的最后一个成员是真正更新的。

© www.soinside.com 2019 - 2024. All rights reserved.