void SaveTowerPositions(WG_TerrainBuilder builderComponent)
        {
            NumberFormatInfo nfi = new NumberFormatInfo();

            nfi.NumberDecimalSeparator = ".";

            WG_Tower[] positions = WG_Helper.FindObjectsOfTypeAll <WG_Tower>().ToArray();// FindObjectsOfType<WG_Tower>();
            string     path      = serverPath + "Towers.txt";

            using (StreamWriter sw = File.CreateText(path))
            {
                for (int i = 0; i < positions.Length; i++)
                {
                    Vector3 p   = positions[i].transform.position;
                    IntPair loc = WG_Helper.GetLocationCoordinates(p, builderComponent.segmentSize);
                    if (loc.u >= builderComponent.segmentsMinX && loc.u <= builderComponent.segmenstMaxX && loc.v >= builderComponent.segmentsMinY && loc.v <= builderComponent.segmenstMaxY)
                    {
                        sw.Write(positions[i].towerType);
                        sw.Write(",");
                        sw.Write(p.x.ToString("0.000", nfi));
                        sw.Write(",");
                        sw.Write(p.z.ToString("0.000", nfi));
                        sw.Write(",");
                        sw.Write(positions[i].towerName);
                        if (i < positions.Length - 1)
                        {
                            sw.Write("|");
                        }
                    }
                }
            }
        }
示例#2
0
        string SaveTextureAsset(Texture2D texture, bool isHdr)
        {
#if UNITY_EDITOR
            string dataPath = WG_Helper.RemoveFirstFolderFromPath(textureAssetFolder) + "lightmap_" + texture.GetInstanceID().ToString() + (isHdr ? ".exr" : ".png");
            string filePath = Application.dataPath + "/" + dataPath;
            if (isHdr)
            {
                //Debug.Log("Save exr " + filePath);
                //Debug.Log("center pixel: " + texture.GetPixel(texture.width / 2, texture.height / 2).ToString());
                byte[] _bytes = texture.EncodeToEXR();
                File.WriteAllBytes(filePath, _bytes);
                AssetDatabase.ImportAsset("Assets/" + dataPath, ImportAssetOptions.ForceUpdate);
                return("Assets/" + dataPath);
            }
            else
            {
                byte[] _bytes = texture.EncodeToPNG();
                File.WriteAllBytes(filePath, _bytes);
                AssetDatabase.ImportAsset("Assets/" + dataPath, ImportAssetOptions.ForceUpdate);
                return("Assets/" + dataPath);
            }
            #else
            return("");
            #endif
        }
示例#3
0
        public int ExportMesh(Mesh mesh, GameObject obj)
        {
            int meshId = mesh.GetInstanceID();

            #if UNITY_EDITOR
            if (!meshLinks.ContainsKey(meshId))
            {
                string meshName = "mesh_" + meshId.ToString() + "_" + WG_Helper.NormalizeName(mesh.name);
                string meshLink = "meshes/" + meshName;
                string meshPath = AssetDatabase.GetAssetPath(mesh);
                if (meshPath.Length > 0)
                {
                    AssetImporter.GetAtPath(meshPath).SetAssetBundleNameAndVariant(meshLink, "");

                    meshLinks.Add(meshId, new NameLinkPath()
                    {
                        link = meshLink, name = mesh.name, path = meshPath
                    });
                }
                else
                {
                    Debug.Log("Mesh component of the object " + obj.name + " not saved as asset. Save it before exorting scene.");
                }
            }
            #endif
            return(meshId);
        }
示例#4
0
 void ClearGeneratedAssets()
 {
     //Application.dataPath = .../Assets
     WG_Helper.ClearFolder(Application.dataPath + assetMaterialPath);
     WG_Helper.ClearFolder(Application.dataPath + assetLocationPath);
     WG_Helper.ClearFolder(Application.dataPath + assetMeshPath);
     WG_Helper.ClearFolder(Application.dataPath + assetTexturePath);
     WG_Helper.ClearFolder(Application.dataPath + assetNavmeshPath);
     WG_Helper.ClearFolder(Application.dataPath + assetMinimapPath);
 }
示例#5
0
 string SaveMinimapAsset(Texture2D texture)
 {
     #if UNITY_EDITOR
     byte[] _bytes   = texture.EncodeToPNG();
     string dataPath = WG_Helper.RemoveFirstFolderFromPath(minimapAssetFolder) + texture.name + ".png";
     string filePath = Application.dataPath + "/" + dataPath;
     File.WriteAllBytes(filePath, _bytes);
     string assetPath = "Assets/" + dataPath;
     AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate);
     return(assetPath);
     #else
     return("");
     #endif
 }
 public static Color ConvertColorToLightmap(Color color, bool applyGamma = false)
 {
     if (applyGamma)
     {
         return(new Color(WG_Helper.ApplyGammaCorrection(color.r, 0.4545f),
                          WG_Helper.ApplyGammaCorrection(color.g, 0.4545f),
                          WG_Helper.ApplyGammaCorrection(color.b, 0.4545f),
                          color.a));
     }
     else
     {
         return(color);
     }
 }
示例#7
0
        public int ExportMaterial(Material material)
        {
            int materialId = material.GetInstanceID();
            int shaderId   = material.shader.GetInstanceID();

            #if UNITY_EDITOR
            //should we add the shader to the asset bundle
            if (!shaderLinks.ContainsKey(shaderId))
            {
                Shader shader     = material.shader;
                string shaderName = "shader_" + shaderId.ToString();
                string shaderLink = "shaders/" + shaderName;
                string assetPath  = AssetDatabase.GetAssetPath(shader);
                AssetImporter.GetAtPath(assetPath).SetAssetBundleNameAndVariant(shaderLink, "");

                shaderLinks.Add(shaderId, new NameLinkPath()
                {
                    link = shaderLink, name = shaderName, path = assetPath
                });
            }
            if (!materialLinks.ContainsKey(materialId))
            {
                string matName   = "material_" + materialId.ToString() + "_" + WG_Helper.NormalizeName(material.name);
                string matLink   = "materials/" + matName;
                string assetPath = AssetDatabase.GetAssetPath(material);

                //iterate throw parameters of the material and try to find all textures
                Shader shader     = material.shader;
                int    propsCount = ShaderUtil.GetPropertyCount(shader);
                for (int i = 0; i < propsCount; i++)
                {
                    if (ShaderUtil.GetPropertyType(shader, i) == ShaderUtil.ShaderPropertyType.TexEnv)
                    {
                        string  texPropName = ShaderUtil.GetPropertyName(shader, i);
                        Texture tex         = material.GetTexture(texPropName);
                        ExportTexture(tex);
                    }
                }
                AssetImporter.GetAtPath(assetPath).SetAssetBundleNameAndVariant(matLink, "");

                materialLinks.Add(materialId, new NameLinkPath()
                {
                    link = matLink, name = material.name, path = assetPath
                });
            }
            #endif
            return(materialId);
        }
示例#8
0
        public static Color[] ConverPixelsToLightMap(Color[] array, bool debug = false)
        {
            Color[] toReturn    = new Color[array.Length];
            Color   randomColor = Random.ColorHSV();

            for (int i = 0; i < toReturn.Length; i++)
            {
                if (debug)
                {
                    toReturn[i] = randomColor;
                }
                else
                {
                    toReturn[i] = WG_Helper.ConvertColorToLightmap(array[i]);
                }
            }

            return(toReturn);
        }
示例#9
0
        //void SaveCollisionMap(NavMeshData data)
        public void SaveCollisionMap(string serverPath)
        {
            List <BoundaryEdge> boundary = WG_Helper.GetNavmeshBoundary();

            if (serverPath != null)
            {
                using (StreamWriter outputFile = new StreamWriter(serverPath + @"CollisionMap.txt"))
                {
                    for (int i = 0; i < boundary.Count; i++)
                    {
                        BoundaryEdge edge = boundary[i];
                        outputFile.Write(WG_Helper.Vectro3ToString(edge.start) + "|" + WG_Helper.Vectro3ToString(edge.end) + (i == boundary.Count - 1 ? "" : "|"));
                        //IntIntClass edge = edgesList[boundaryEdges[i]].GetEdgeVertices();

                        //outputFile.Write(WG_Helper.Vectro3ToString(vertexList[edge.value1].position) + "|" + WG_Helper.Vectro3ToString(vertexList[edge.value2].position) + (i == boundaryEdges.Count - 1 ? "" : "|"));
                    }
                }
            }
        }
        public float GetHeight(Vector2 point)
        {
            int  maxIndex = -1;
            bool isHeight = false;

            for (int i = 0; i < points.Count; i++)
            {
                Disc d = points[i];
                if (WG_Helper.IsInside(point, d))
                {
                    if (d.level > maxIndex)
                    {
                        maxIndex = d.level;
                        isHeight = !d.isNegative;
                    }
                }
            }

            return(isHeight ? 1.0f : 0.0f);
        }
示例#11
0
        public void ExportTexture(Texture tex)
        {
            #if UNITY_EDITOR
            if (tex != null)
            {
                int texId = tex.GetInstanceID();
                if (!textureLinks.ContainsKey(texId))
                {
                    string texName = "texture_" + texId.ToString() + "_" +
                                     WG_Helper.NormalizeName(tex.name);
                    string texPath = AssetDatabase.GetAssetPath(tex);
                    string texLink = "textures/" + texName;
                    AssetImporter.GetAtPath(texPath).SetAssetBundleNameAndVariant(texLink, "");

                    textureLinks.Add(texId, new NameLinkPath()
                    {
                        link = texLink, name = texName, path = texPath
                    });
                }
            }
            #endif
        }
示例#12
0
        void CreateMinimap(int minimapSize, Camera minimapCamera, float minimapCameraHeight)
        {
            RenderTexture renderTexture = new RenderTexture(minimapSize, minimapSize, 16, DefaultFormat.LDR);

            renderTexture.Create();
            minimapCamera.targetTexture = renderTexture;
            Rect rectReadPicture = new Rect(0, 0, minimapSize, minimapSize);

            Vector3 locPosition = gameObject.transform.position;

            minimapCamera.transform.position = new Vector3(locPosition.x, minimapCameraHeight, locPosition.z);
            minimapCamera.Render();

            RenderTexture.active = renderTexture;

            //Create texture
            locationMinimap      = new Texture2D(minimapSize, minimapSize);
            locationMinimap.name = "minimap_" + u.ToString() + "_" + v.ToString();

            // Read pixels
            locationMinimap.ReadPixels(rectReadPicture, 0, 0);
            Color[] rawPixels     = locationMinimap.GetPixels();
            Color[] processPixels = new Color[rawPixels.Length];
            for (int pi = 0; pi < rawPixels.Length; pi++)
            {
                float a = rawPixels[pi].a;
                processPixels[pi] = new Color(a, a, a, a);
            }
            locationMinimap.SetPixels(processPixels);

            // Clean up
            RenderTexture.active = null;
            renderTexture.Release();

            minimapAssetPath = SaveMinimapAsset(locationMinimap);
            WG_Helper.SetTextureSprite(minimapAssetPath);
        }
示例#13
0
 public override string ToString()
 {
     return("(" + vertex01.ToString() + ", " + vertex02.ToString() + "), triangles: " +
            WG_Helper.ListToString(triangles) + ", isBoundary: " + isBoundary.ToString());
 }
示例#14
0
        public void BuildMesh()
        {
#if UNITY_EDITOR
            //clear generated segments
            navmeshExist = false;
            //create helper object for all sub-generated objects
            GameObject store = new GameObject()
            {
                name = "Temp Store"
            };
            Transform[] allTransforms = gameObject.GetComponentsInChildren <Transform>();
            for (int trIndex = allTransforms.Length - 1; trIndex >= 0; trIndex--)
            {
                GameObject go = allTransforms[trIndex].gameObject;
                //try to get noise primitive component
                //if this component is null, then delete game object
                WG_Primitive_PerlinNoise noiseComponent = go.GetComponent <WG_Primitive_PerlinNoise>();
                WG_Primitive_Paint       paintComponent = go.GetComponent <WG_Primitive_Paint>();
                WG_Painter      painterComponent        = go.GetComponent <WG_Painter>();
                WG_VisualCenter visCenterComponent      = go.GetComponent <WG_VisualCenter>();
                if (go != gameObject && noiseComponent == null && paintComponent == null && painterComponent == null && visCenterComponent == null)
                {
                    if (clearAll)
                    {
                        DestroyImmediate(go);
                    }
                    else
                    {
                        //check is this object contains location controller
                        WG_LocationController locController = go.GetComponent <WG_LocationController>();
                        if (locController != null)
                        {//this is location root object, destoy it
                            DestroyImmediate(go);
                        }
                        else
                        {     //this is not location root, may be walls or ground object
                            if (go.name == groundName || go.name == wallsName || go.name == meshRootName)
                            { //this is generated ground or wall object, destoy it
                                DestroyImmediate(go);
                            }
                            else
                            {//this is sub-placed object, store it
                                if (PrefabUtility.GetOutermostPrefabInstanceRoot(go) == null || PrefabUtility.GetOutermostPrefabInstanceRoot(go) == go)
                                {
                                    go.transform.SetParent(store.transform, true);
                                }
                            }
                        }
                    }
                }
            }
            //fill map for all location segments
            bool[,] map = new bool[(segmenstMaxX - segmentsMinX + 1) * meshSquaresCount + 1, (segmenstMaxY - segmentsMinY + 1) * meshSquaresCount + 1];
            WG_Primitive_BaseNoise[] noises = gameObject.GetComponentsInChildren <WG_Primitive_BaseNoise>();
            float   meshSquareSize          = segmentSize / meshSquaresCount;
            Vector2 bottomLeftCorner        = new Vector2((segmentsMinX - 0.5f) * segmentSize, (segmentsMinY - 0.5f) * segmentSize);
            for (int x = 0; x < map.GetLength(0); x++)
            {
                for (int y = 0; y < map.GetLength(1); y++)
                {
                    Vector2 pos = new Vector2(x * meshSquareSize, y * meshSquareSize) + bottomLeftCorner;
                    map[x, y] = IsPointMountains(pos, noises);
                }
            }

            //next create root for location segments
            GameObject locationsRoot = new GameObject {
                name = meshRootName
            };
            locationsRoot.transform.SetParent(gameObject.transform);
            //create location generator
            WG_SegmentsGenerator         generator = new WG_SegmentsGenerator();
            List <WG_LocationController> locations = generator.GenerateLocationSegments(this, segmentSize, meshSquareSize, meshSquaresCount, segmentsMinX, segmenstMaxX, segmentsMinY, segmenstMaxY, locationsRoot, groundMaterial, mountainsMaterial, wallsMaterial, map, mountainsHeight, !(forceUpdate && buildMesh), navMeshCutVolume, uv2Padding);
#endif

#if UNITY_EDITOR
            //after generation we should place back all stored objects, we will place it inside location root object
            Transform[] storedObjects = store.GetComponentsInChildren <Transform>();
            for (int tfmIndex = 0; tfmIndex < storedObjects.Length; tfmIndex++)
            {
                Transform tfm = storedObjects[tfmIndex];
                if (tfm.gameObject != store)
                {
                    Vector3 position          = tfm.position;
                    IntPair locCoords         = WG_Helper.GetLocationCoordinates(position, segmentSize);
                    WG_LocationController loc = GetLocationByCoordinates(locCoords, locations);
                    if (loc != null)
                    {
                        //rever prefab properties (mesh and material)
                        GameObject prefabMaster  = PrefabUtility.GetOutermostPrefabInstanceRoot(tfm.gameObject);
                        MeshFilter meshComponent = tfm.GetComponent <MeshFilter>();
                        if ((prefabMaster == null && meshComponent != null) || prefabMaster == tfm.gameObject)
                        {
                            Vector3    scale  = tfm.localScale;
                            GameObject source = PrefabUtility.GetCorrespondingObjectFromSource(tfm.gameObject);
                            if (source != null)
                            {
                                PrefabUtility.RevertPrefabInstance(tfm.gameObject, InteractionMode.UserAction);
                            }

                            tfm.localScale = scale;

                            //move object inside location
                            tfm.SetParent(loc.gameObject.transform, true);
                            tfm.position += loc.gameObject.transform.position;
                        }
                    }
                    else
                    {
                        Debug.Log("There is no locations with coordinates " + locCoords.ToString() + ", so skip the object " + tfm.gameObject.name);
                    }
                }
            }
            //delete temp store
            DestroyImmediate(store);
            #endif

            BuildNavmeshOnly();
        }
示例#15
0
        void CalculateMeshOutlines()
        {
            //WG_Helper.PrintArray(vertices.ToArray());
            for (int vertexIndex = 0; vertexIndex < vertices.Count; vertexIndex++)
            {
                if (!checkedVertices.Contains(vertexIndex))
                {
                    int newOulineVertex = GetConnectedOutlineVertex(vertexIndex);
                    if (newOulineVertex != -1)
                    {
                        //if both vertexIndex and newOulineVertex are on boundary, skip the process
                        Vector3 startPoint      = vertices[vertexIndex];
                        Vector3 nextPoint       = vertices[newOulineVertex];
                        bool    isStartBoundary = IsNearBoundary(startPoint);
                        bool    isNextBoundary  = IsNearBoundary(nextPoint);
                        //Debug.Log(startPoint.ToString() + " " + nextPoint.ToString() + " " + isStartBoundary.ToString() + " " + isNextBoundary.ToString() + " " + IsDifferentBoundarySides(startPoint, nextPoint).ToString());
                        if (!isStartBoundary || !isNextBoundary || IsDifferentBoundarySides(startPoint, nextPoint))
                        {
                            checkedVertices.Add(vertexIndex);

                            List <int> newOutline = new List <int> {
                                vertexIndex
                            };
                            outlines.Add(newOutline);
                            FollowOutline(newOulineVertex, outlines.Count - 1);

                            //check if we break the outline new zone boundary
                            //in this case we should revert the process from the last point (in zone boundary) to the other direction
                            int lastIndex = newOutline[newOutline.Count - 1];
                            //Debug.Log("Last index: " + lastIndex.ToString());
                            if (IsNearBoundary(vertices[lastIndex]))
                            {
                                //Debug.Log("point " + lastIndex.ToString() + " near boundary");
                                //remove vertices from the checked set
                                //WG_Helper.PrintArray(checkedVertices);
                                for (int i = newOutline.Count - 1; i >= 0; i--)
                                {
                                    checkedVertices.Remove(newOutline[i]);
                                }
                                //WG_Helper.PrintArray(checkedVertices);
                                //remove outline
                                outlines.RemoveAt(outlines.Count - 1);

                                //start the process again
                                checkedVertices.Add(lastIndex);
                                List <int> newOtherOutline = new List <int> {
                                    lastIndex
                                };
                                outlines.Add(newOtherOutline);
                                newOulineVertex = GetConnectedOutlineVertex(lastIndex);
                                FollowOutline(newOulineVertex, outlines.Count - 1);
                            }
                            else
                            {
                                outlines[outlines.Count - 1].Add(vertexIndex);
                            }

                            //check if we should revert outline array
                            //get triangles incident to the start vertex
                            int             startVertex    = outlines[outlines.Count - 1][0];
                            List <Triangle> startTriangles = triangleDictionary[startVertex];
                            //find in a triangle the next point in the outline
                            int  nextVertex   = outlines[outlines.Count - 1][1];
                            bool shouldRevert = true;
                            foreach (Triangle startTriangle in startTriangles)
                            {
                                if ((startTriangle.vertexIndexA == startVertex && startTriangle.vertexIndexB == nextVertex) ||
                                    (startTriangle.vertexIndexB == startVertex && startTriangle.vertexIndexC == nextVertex) ||
                                    (startTriangle.vertexIndexC == startVertex && startTriangle.vertexIndexA == nextVertex))
                                {
                                    shouldRevert = false;
                                    break;
                                }
                            }

                            if (shouldRevert)
                            {
                                outlines[outlines.Count - 1] = WG_Helper.Revert(outlines[outlines.Count - 1]);
                            }


                            //WG_Helper.PrintArray(outlines[outlines.Count - 1].ToArray());
                        }
                    }
                }
            }
        }
示例#16
0
        void OnDrawGizmos()
        {
            #if UNITY_EDITOR
            if (visualMap != null && visualizeMap)
            {
                for (int x = 0; x < visualMap.GetLength(0); x++)
                {
                    for (int y = 0; y < visualMap.GetLength(1); y++)
                    {
                        Gizmos.color = (visualMap[x, y]) ? new Color(0, 0, 0, gizmoAlpha) : new Color(1, 1, 1, gizmoAlpha);
                        Vector3 pos = new Vector3(-visualAreaSize / 2 + (x + 0.5f) * visualSquareSize + visualAreaCenter.position.x, 0, -visualAreaSize / 2 + (y + 0.5f) * visualSquareSize + visualAreaCenter.position.z);
                        Gizmos.DrawCube(pos, new Vector3(visualSquareSize * 0.75f, 0.0f, visualSquareSize * 0.75f));
                    }
                }

                Vector2 minCorner = new Vector2(visualAreaCenter.position.x - visualAreaSize / 2, visualAreaCenter.position.z - visualAreaSize / 2);
                Vector2 maxCorner = new Vector2(visualAreaCenter.position.x + visualAreaSize / 2, visualAreaCenter.position.z + visualAreaSize / 2);

                int minX = (int)(minCorner.x / (segmentSize / 2)) + (minCorner.x > 0 ? 1 : 0);
                int maxX = (int)(maxCorner.x / (segmentSize / 2)) + (maxCorner.x > 0 ? 1 : 0);

                int minY = (int)(minCorner.y / (segmentSize / 2)) + (minCorner.y > 0 ? 1 : 0);
                int maxY = (int)(maxCorner.y / (segmentSize / 2)) + (maxCorner.y > 0 ? 1 : 0);

                Gizmos.color = visualZoneLine;
                for (int x = minX - 1; x < maxX + 1; x++)
                {
                    for (int y = minY - 1; y < maxY + 1; y++)
                    {
                        if (x % 2 == 0 && y % 2 == 0)
                        {
                            Gizmos.DrawLine(GetPositionOfSegmetnCorner(x - 1, y - 1), GetPositionOfSegmetnCorner(x + 1, y - 1));
                            Gizmos.DrawLine(GetPositionOfSegmetnCorner(x + 1, y - 1), GetPositionOfSegmetnCorner(x + 1, y + 1));
                            Gizmos.DrawLine(GetPositionOfSegmetnCorner(x + 1, y + 1), GetPositionOfSegmetnCorner(x - 1, y + 1));
                            Gizmos.DrawLine(GetPositionOfSegmetnCorner(x - 1, y + 1), GetPositionOfSegmetnCorner(x - 1, y - 1));

                            string  labelString = "(" + (x / 2).ToString() + ", " + (y / 2).ToString() + ")";
                            Vector3 labelPos    = new Vector3(x * segmentSize / 2, 2.0f, y * segmentSize / 2);
                            Handles.Label(labelPos, labelString);
                        }
                    }
                }
            }

            if (visualizeBoundaryEdges)
            {
                List <BoundaryEdge> boundary = WG_Helper.GetNavmeshBoundary();

                Gizmos.color = boundaryLine;
                for (int i = 0; i < boundary.Count; i++)
                {
                    BoundaryEdge edge = boundary[i];
                    if (true)
                    {
                        Gizmos.DrawLine(edge.start, edge.end);
                        //Handles.DrawSolidDisc(edge.start, Vector3.up, 0.03f);
                        //Handles.Label(edge.start, edge.startVertex.ToString());
                        //Handles.DrawSolidDisc(edge.end, Vector3.up, 0.03f);
                        //Handles.Label(edge.end, edge.endVertes.ToString());
                        //Handles.Label((edge.start + edge.end) / 2.0f, edge.index.ToString());
                    }
                }
            }
            #endif
        }
示例#17
0
        void PrepareMaterial(GameObject go)
        {
            //for material of the geometry we should get lightmap, save it, reassign material with all textures plus lightmap
            #if UNITY_EDITOR
            MeshRenderer meshRenderer = go.GetComponent <MeshRenderer>();
            if (meshRenderer != null)
            {
                //get material
                Material originalMaterial = meshRenderer.sharedMaterial;
                //if material use lightMap texture, then does not save new texture and reassign material
                bool lmSlotExist       = IsMaterialContainsMap(originalMaterial, "_LightMap");
                bool bumpSlotExist     = IsMaterialContainsMap(originalMaterial, "_BumpMap");
                bool emissionSlotExist = IsMaterialContainsMap(originalMaterial, "_EmissionMap");
                bool diffuseSlotExist  = IsMaterialContainsMap(originalMaterial, "_MainTex");
                if (lmSlotExist)
                {
                    Texture t = originalMaterial.GetTexture("_LightMap");
                    if (t == null)
                    {
                        lmSlotExist = false;
                    }
                }
                if (!lmSlotExist)
                {//material does not contains slot for lightmap, so, we should save it and re-assign material
                    //get lightmap
                    string lmTextureAssetPath = "";
                    int    lmIndex            = meshRenderer.lightmapIndex;
                    bool   reAssignMaterial   = false;
                    if (lmIndex > -1 && lmIndex < LightmapSettings.lightmaps.Length)
                    {
                        LightmapData data      = LightmapSettings.lightmaps[lmIndex];
                        Texture2D    lmTexture = data.lightmapColor;
                        WG_Helper.SetTextureReadable(lmTexture, true);
                        //int width = (int)(lmTexture.width * Mathf.Min(1.0f, meshRenderer.lightmapScaleOffset.x));
                        //int height = (int)(lmTexture.height * Mathf.Min(1.0f, meshRenderer.lightmapScaleOffset.y));
                        int width  = (int)(lmTexture.width * meshRenderer.lightmapScaleOffset.x);
                        int height = (int)(lmTexture.height * meshRenderer.lightmapScaleOffset.y);

                        //int startX = Mathf.Max(0, (int)(lmTexture.width * meshRenderer.lightmapScaleOffset.z));
                        //int startY = Mathf.Max(0, (int)(lmTexture.height * meshRenderer.lightmapScaleOffset.w));
                        int startX = (int)(lmTexture.width * meshRenderer.lightmapScaleOffset.z);
                        int startY = (int)(lmTexture.height * meshRenderer.lightmapScaleOffset.w);

                        Texture2D newTexture = new Texture2D(width, height, isLightmapHDR ? DefaultFormat.HDR : DefaultFormat.LDR, TextureCreationFlags.MipChain);

                        int mapStartX = Mathf.Max(0, startX);
                        int mapStartY = Mathf.Max(0, startY);
                        int mapEndX   = Mathf.Min(lmTexture.width, startX + width);
                        int mapEndY   = Mathf.Min(lmTexture.height, startY + height);
                        int mapWidth  = mapEndX - mapStartX;
                        int mapHeight = mapEndY - mapStartY;

                        //fill the main rect
                        Color[] lmColorsRaw = lmTexture.GetPixels(mapStartX, mapStartY, mapWidth, mapHeight);
                        //WG_Helper.PrintMinMaxPixels(lmColorsRaw);

                        Color[] lmColors = WG_Helper.ConverPixelsToLightMap(lmColorsRaw);
                        //WG_Helper.PrintMinMaxPixels(lmColors);
                        //Debug.Log("main rect: " + (mapStartX - startX).ToString() + " " + (mapStartY - startY).ToString() + " " + mapWidth.ToString() + " " + mapHeight.ToString());
                        newTexture.SetPixels(mapStartX - startX, mapStartY - startY, mapWidth, mapHeight, isLightmapHDR ? lmColors : lmColorsRaw);

                        //next fill left area (if we need it)
                        Color[] leftColorsRaw = lmTexture.GetPixels(mapStartX, mapStartY, 1, mapHeight);
                        Color[] leftColors    = WG_Helper.ConverPixelsToLightMap(leftColorsRaw);
                        for (int column = 0; column < mapStartX - startX; column++)
                        {
                            newTexture.SetPixels(column, mapStartY - startY, 1, mapHeight, isLightmapHDR ? leftColors : leftColorsRaw);
                        }

                        //next right area
                        Color[] rightColorsRaw = lmTexture.GetPixels(mapEndX - 1, mapStartY, 1, mapHeight);
                        Color[] rightColors    = WG_Helper.ConverPixelsToLightMap(rightColorsRaw);
                        for (int column = 0; column < width + startX - mapEndX; column++)
                        {
                            newTexture.SetPixels(mapEndX - startX + column, mapStartY - startY, 1, mapHeight, isLightmapHDR ? rightColors: rightColorsRaw);
                        }

                        //bottom and top
                        Color[] bottomColorsRaw = lmTexture.GetPixels(mapStartX, mapStartY, mapWidth, 1);
                        Color[] bottomColors    = WG_Helper.ConverPixelsToLightMap(bottomColorsRaw);
                        for (int row = 0; row < mapStartY - startY; row++)
                        {
                            newTexture.SetPixels(mapStartX - startX, row, mapWidth, 1, isLightmapHDR ? bottomColors : bottomColorsRaw);
                        }
                        Color[] topColorsRaw = lmTexture.GetPixels(mapStartX, mapEndY - 1, mapWidth, 1);
                        Color[] topColors    = WG_Helper.ConverPixelsToLightMap(topColorsRaw);
                        for (int row = 0; row < height + startY - mapEndY; row++)
                        {
                            newTexture.SetPixels(mapStartX - startX, mapEndY - startY + row, mapWidth, 1, isLightmapHDR ? topColors : topColorsRaw);
                        }

                        //regions on corners
                        Color leftBootm  = isLightmapHDR ? WG_Helper.ConvertColorToLightmap(lmTexture.GetPixel(mapStartX, mapStartY)) : lmTexture.GetPixel(mapStartX, mapStartY);
                        Color leftTop    = isLightmapHDR ? WG_Helper.ConvertColorToLightmap(lmTexture.GetPixel(mapStartX, mapEndY - 1)) : lmTexture.GetPixel(mapStartX, mapEndY - 1);
                        Color rightBootm = isLightmapHDR ? WG_Helper.ConvertColorToLightmap(lmTexture.GetPixel(mapEndX - 1, mapStartY)) : lmTexture.GetPixel(mapEndX - 1, mapStartY);
                        Color rightTop   = isLightmapHDR ? WG_Helper.ConvertColorToLightmap(lmTexture.GetPixel(mapEndX - 1, mapEndY - 1)) : lmTexture.GetPixel(mapEndX - 1, mapEndY - 1);

                        Color[] leftBottomColors  = WG_Helper.CreateArray(leftBootm, (mapStartX - startX) * (mapStartY - startY));
                        Color[] leftTopColors     = WG_Helper.CreateArray(leftTop, (mapStartX - startX) * (startY + height - mapEndY));
                        Color[] rightBottomColors = WG_Helper.CreateArray(rightBootm, (startX + width - mapEndX) * (mapStartY - startY));
                        Color[] rightTopColors    = WG_Helper.CreateArray(rightTop, (startX + width - mapEndX) * (startY + height - mapEndY));

                        newTexture.SetPixels(0, 0, mapStartX - startX, mapStartY - startY, leftBottomColors);
                        newTexture.SetPixels(0, mapEndY, mapStartX - startX, startY + height - mapEndY, leftTopColors);
                        //Debug.Log(rightBottomColors.Length.ToString() + " " + (startX + width - mapEndX).ToString() + " " + (mapStartY - startY).ToString());
                        try
                        {
                            newTexture.SetPixels(mapEndX, 0, startX + width - mapEndX, mapStartY - startY, rightBottomColors);
                        }
                        catch
                        {
                            Debug.Log(rightBottomColors.Length.ToString() + " " + (startX + width - mapEndX).ToString() + " " + (mapStartY - startY).ToString());
                        }
                        newTexture.SetPixels(mapEndX, mapEndY, startX + width - mapEndX, startY + height - mapEndY, rightTopColors);

                        newTexture.Apply();

                        //Debug.Log("isLightmapHDR=" + isLightmapHDR.ToString());
                        //Debug.Log("original pixel: " + lmTexture.GetPixel(mapStartX + width / 3, mapStartY + height / 3).ToString() + " "
                        //+ lmTexture.GetPixel(mapStartX + 2*width / 3, mapStartY + 2*height / 3).ToString());
                        //Debug.Log("saved pixel: " + newTexture.GetPixel(width / 3, height / 3).ToString() + " " + newTexture.GetPixel(2*width / 3, 2*height / 3).ToString());

                        lmTextureAssetPath = SaveTextureAsset(newTexture, isLightmapHDR);
                        WG_Helper.SetTextureLightmap(lmTextureAssetPath, isLightmapHDR);
                        reAssignMaterial = true;
                    }
                    else
                    {
                        Debug.Log("Object " + go.name + " does not have lightmaps or this data is invalid.");
                    }

                    //reassign material if we need it
                    if (reAssignMaterial)
                    {
                        if (true)
                        {
                            Material newMaterial = lmMode == LMShaderMode.LWRP ? new Material(lwrpShader) : new Material(GetStdShader(diffuseSlotExist, bumpSlotExist, emissionSlotExist));
                            //Material newMaterial = (lmMode == LMShaderMode.LWRP || (lmMode == LMShaderMode.Std && bumpSlotExist == false)) ? new Material(lmShader) : new Material(lmSecondShader);
                            //for LWRP we use only one uber-shader, for std shaders each different once from array
                            //assign all parameters from original material to the new one
                            Shader        originalShader   = originalMaterial.shader;
                            List <string> newMaterialNames = WG_Helper.GetShaderParameterNames(newMaterial.shader);
                            int           propsCount       = ShaderUtil.GetPropertyCount(originalShader);
                            for (int i = 0; i < propsCount; i++)
                            {
                                string propName = ShaderUtil.GetPropertyName(originalShader, i);
                                if (newMaterialNames.Contains(propName))
                                {
                                    ShaderUtil.ShaderPropertyType type = ShaderUtil.GetPropertyType(originalShader, i);
                                    if (type == ShaderUtil.ShaderPropertyType.Color)
                                    {
                                        newMaterial.SetColor(propName, originalMaterial.GetColor(propName));
                                    }
                                    else if (type == ShaderUtil.ShaderPropertyType.Float)
                                    {
                                        newMaterial.SetFloat(propName, originalMaterial.GetFloat(propName));
                                    }
                                    else if (type == ShaderUtil.ShaderPropertyType.Range)
                                    {
                                        newMaterial.SetFloat(propName, originalMaterial.GetFloat(propName));
                                    }
                                    else if (type == ShaderUtil.ShaderPropertyType.TexEnv)
                                    {
                                        newMaterial.SetTexture(propName, originalMaterial.GetTexture(propName));
                                        newMaterial.SetTextureOffset(propName, originalMaterial.GetTextureOffset(propName));
                                        newMaterial.SetTextureScale(propName, originalMaterial.GetTextureScale(propName));
                                    }
                                    else if (type == ShaderUtil.ShaderPropertyType.Vector)
                                    {
                                        newMaterial.SetVector(propName, originalMaterial.GetVector(propName));
                                    }
                                }
                                else
                                {
                                    Debug.Log("New material (" + newMaterial.shader.name + ") for the object " + go.name + " does not contains property " + propName + ". Skip it.");
                                }
                            }
                            //set gpu instancing
                            newMaterial.enableInstancing = originalMaterial.enableInstancing;
                            //finally assign lightMap texture
                            newMaterial.SetTexture("_LightMap", AssetDatabase.LoadAssetAtPath <Texture2D>(lmTextureAssetPath));
                            //set amibient, if we need it
                            if (!isLightmapHDR)
                            {
                                //--newMaterial.SetColor("_Ambient", ldrAmbient);  // <-- does not used in WebGL mode
                                newMaterial.SetFloat("_Multiplier", ldrLightmapMultiplier);
                            }
                            //enable all kewords
                            string[] originalKeyWords = originalMaterial.shaderKeywords;
                            for (int s = 0; s < originalKeyWords.Length; s++)
                            {
                                newMaterial.EnableKeyword(originalKeyWords[s]);
                            }
                            //CoreUtils.SetKeyword(newMaterial, "_EMISSION", originalMaterial.IsKeywordEnabled("_EMISSION"));
                            //assign material to the object
                            meshRenderer.sharedMaterial = newMaterial;
                            SaveMaterialAsset(newMaterial);
                        }
                        else
                        {
                        }
                    }
                    else
                    {
                        //string matAssetPath = SaveMaterialAsset(originalMaterial);
                        //Debug.Log("Create material asset " + matAssetPath);
                    }
                }
                else
                {
                    SaveMaterialAsset(originalMaterial);
                }
            }
            #endif
        }
示例#18
0
        public static List <BoundaryEdge> GetNavmeshBoundary()
        {
            //copy algorithm
            NavMeshTriangulation triangulatedNavMesh = NavMesh.CalculateTriangulation();

            Vector3[]         originalVertices = triangulatedNavMesh.vertices;
            int[]             originalIndexes  = triangulatedNavMesh.indices;
            float             weldValue        = 0.01f;
            List <VertexData> vertexList       = new List <VertexData>();

            for (int i = 0; i < originalVertices.Length; i++)
            {
                Vector3 vPos  = originalVertices[i];
                bool    isNew = true;
                //Try to find this vertex on vertexList
                for (int vIndex = 0; vIndex < vertexList.Count; vIndex++)
                {
                    VertexData v = vertexList[vIndex];
                    if (Vector3.Distance(vPos, v.position) < weldValue)
                    {//i-th vertex placed in the same position as vIndex in the list. Add it index
                        v.indexes.Add(i);
                        vIndex = vertexList.Count;
                        isNew  = false;
                    }
                }
                if (isNew)
                {
                    VertexData newVertex = new VertexData();
                    newVertex.position = vPos;
                    newVertex.indexes  = new List <int>();
                    newVertex.indexes.Add(i);
                    vertexList.Add(newVertex);
                }
            }
            List <EdgeData> edgesList = new List <EdgeData>();
            int             originalTrianglesCount = originalIndexes.Length / 3;

            for (int i = 0; i < originalTrianglesCount; i++)
            {
                int  i1        = WG_Helper.GetVertexIndex(originalIndexes[3 * i], vertexList);
                int  i2        = WG_Helper.GetVertexIndex(originalIndexes[3 * i + 1], vertexList);
                int  i3        = WG_Helper.GetVertexIndex(originalIndexes[3 * i + 2], vertexList);
                bool isFindI12 = false;
                bool isFindI23 = false;
                bool isFindI31 = false;
                for (int eIndex = 0; eIndex < edgesList.Count; eIndex++)
                {
                    isFindI12 = edgesList[eIndex].TryToAdd(i1, i2) || isFindI12;
                    isFindI23 = edgesList[eIndex].TryToAdd(i2, i3) || isFindI23;
                    isFindI31 = edgesList[eIndex].TryToAdd(i3, i1) || isFindI31;
                }
                if (!isFindI12)
                {
                    EdgeData newEdge = new EdgeData(i1, i2);
                    edgesList.Add(newEdge);
                }
                if (!isFindI23)
                {
                    EdgeData newEdge = new EdgeData(i2, i3);
                    edgesList.Add(newEdge);
                }
                if (!isFindI31)
                {
                    EdgeData newEdge = new EdgeData(i3, i1);
                    edgesList.Add(newEdge);
                }
            }

            //filter boundary edges, if it contains vertex of the other boundary edge inside it
            List <int> boundaryIndexes = new List <int>();

            for (int i = 0; i < edgesList.Count; i++)
            {
                if (edgesList[i].IsBoundary())
                {
                    boundaryIndexes.Add(i);
                }
            }

            bool isUpdate = true;

            while (isUpdate)
            {
                isUpdate = false;
                int i = 0;
                while (i < boundaryIndexes.Count)
                {
                    IntInt currentEdge;
                    currentEdge.value01 = edgesList[boundaryIndexes[i]].GetEdgeVertices().value1;
                    currentEdge.value02 = edgesList[boundaryIndexes[i]].GetEdgeVertices().value2;
                    //IntIntClass currentEdge = edgesList[boundaryIndexes[i]].GetEdgeVertices();
                    Vector3 currentStart = vertexList[currentEdge.value01].position;
                    Vector3 currentEnd   = vertexList[currentEdge.value02].position;
                    if (Vector3.Distance(currentStart, currentEnd) < 0.01f)
                    {
                        boundaryIndexes.RemoveAt(i);
                        i        = boundaryIndexes.Count + 1;
                        isUpdate = true;
                    }
                    else
                    {
                        int j = 0;
                        while (j < boundaryIndexes.Count)
                        {
                            IntInt testEdge;
                            testEdge.value01 = edgesList[boundaryIndexes[j]].GetEdgeVertices().value1;
                            testEdge.value02 = edgesList[boundaryIndexes[j]].GetEdgeVertices().value2;
                            //IntIntClass testEdge = edgesList[boundaryIndexes[j]].GetEdgeVertices();
                            Vector3 testStart = vertexList[testEdge.value01].position;
                            Vector3 testEnd   = vertexList[testEdge.value02].position;
                            if (Vector3.Distance(testStart, testEnd) < 0.01f)
                            {
                                boundaryIndexes.RemoveAt(j);
                                j        = boundaryIndexes.Count + 1;
                                i        = boundaryIndexes.Count + 1;
                                isUpdate = true;
                            }
                            else if (i != j && boundaryIndexes[i] < boundaryIndexes[j])
                            {
                                if (IsEdgesCollinear(currentStart, currentEnd, testStart, testEnd))
                                {
                                    if (IsPointsClose(currentStart, testEnd) && IsPointOnTheEdge(testStart, currentStart, currentEnd))
                                    {
                                        EdgeData ith = new EdgeData(testEdge.value01, currentEdge.value02);
                                        EdgeData jth = new EdgeData(currentEdge.value01, testEdge.value02);
                                        edgesList[boundaryIndexes[i]] = ith;
                                        edgesList[boundaryIndexes[j]] = jth;
                                        i        = boundaryIndexes.Count + 1;
                                        j        = boundaryIndexes.Count + 1;
                                        isUpdate = true;
                                    }
                                    else if (IsPointsClose(currentEnd, testStart) && IsPointOnTheEdge(testEnd, currentStart, currentEnd))
                                    {
                                        EdgeData ith = new EdgeData(currentEdge.value01, testEdge.value02);
                                        EdgeData jth = new EdgeData(testEdge.value01, currentEdge.value02);
                                        edgesList[boundaryIndexes[i]] = ith;
                                        edgesList[boundaryIndexes[j]] = jth;
                                        i        = boundaryIndexes.Count + 1;
                                        j        = boundaryIndexes.Count + 1;
                                        isUpdate = true;
                                    }
                                    else if (IsPointsClose(currentStart, testEnd) && IsPointOnTheEdge(currentEnd, testStart, testEnd))
                                    {
                                        EdgeData ith = new EdgeData(currentEdge.value01, testEdge.value02);
                                        EdgeData jth = new EdgeData(testEdge.value01, currentEdge.value02);
                                        edgesList[boundaryIndexes[i]] = ith;
                                        edgesList[boundaryIndexes[j]] = jth;
                                        i        = boundaryIndexes.Count + 1;
                                        j        = boundaryIndexes.Count + 1;
                                        isUpdate = true;
                                    }
                                    else if (IsPointsClose(currentEnd, testStart) && IsPointOnTheEdge(currentStart, testStart, testEnd))
                                    {
                                        EdgeData ith = new EdgeData(testEdge.value01, currentEdge.value02);
                                        EdgeData jth = new EdgeData(currentEdge.value01, testEdge.value02);
                                        edgesList[boundaryIndexes[i]] = ith;
                                        edgesList[boundaryIndexes[j]] = jth;
                                        i        = boundaryIndexes.Count + 1;
                                        j        = boundaryIndexes.Count + 1;
                                        isUpdate = true;
                                    }
                                    else if (IsPointsClose(currentEnd, testStart) && IsPointsClose(currentStart, testEnd))
                                    {
                                        EdgeData ith = new EdgeData(currentEdge.value01, currentEdge.value01);
                                        EdgeData jth = new EdgeData(testEdge.value01, testEdge.value01);
                                        edgesList[boundaryIndexes[i]] = ith;
                                        edgesList[boundaryIndexes[j]] = jth;
                                        i        = boundaryIndexes.Count + 1;
                                        j        = boundaryIndexes.Count + 1;
                                        isUpdate = true;
                                    }
                                }
                            }

                            j++;
                        }
                    }
                    i++;
                }
            }

            //copy to the output
            List <BoundaryEdge> toReturn = new List <BoundaryEdge>();

            for (int i = 0; i < boundaryIndexes.Count; i++)
            {
                int          index   = boundaryIndexes[i];
                IntIntClass  edge    = edgesList[index].GetEdgeVertices();
                BoundaryEdge newEdge = new BoundaryEdge();
                newEdge.index       = index;
                newEdge.start       = vertexList[edge.value1].position;
                newEdge.end         = vertexList[edge.value2].position;
                newEdge.startVertex = edge.value1;
                newEdge.endVertes   = edge.value2;
                toReturn.Add(newEdge);
            }
            return(toReturn);
        }
        void ExportScene(Transform locationRoot)
        {
            WG_Helper.ClearFolder(Application.dataPath + assetLocationSOPath);

            for (int i = 0; i < locationRoot.childCount; i++)
            {
                Transform             loc           = locationRoot.GetChild(i);
                WG_LocationController locController = loc.GetComponent <WG_LocationController>();

                if (locController != null)
                {
                    locController.ExportLocation("Assets" + assetLocationXMLPath, "Assets" + assetLocationSOPath, minimapSize, minimapCamera, minimapCameraHeight, "Assets" + assetMinimapPath);
                }
            }

#if UNITY_EDITOR
            //export navmesh
            WG_TerrainBuilder builderComponent = builder.gameObject.GetComponent <WG_TerrainBuilder>();
            NavMeshData       data             = builderComponent.GetNavmeshData();
            string            navmeshAssetPath = "";
            if (data != null)
            {
                navmeshAssetPath = "navmeshes/" + data.name;
                AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(data)).SetAssetBundleNameAndVariant(navmeshAssetPath, "");
            }
            else
            {
                if (localNavMesh == null)
                {
                    Debug.Log("Navmesh data is null, can't export it.");
                }
                else
                {
                    Debug.Log("Use local version of the navmesh data object.");
                    data             = localNavMesh;
                    navmeshAssetPath = "navmeshes/" + localNavMesh.name;
                    AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(localNavMesh)).SetAssetBundleNameAndVariant(navmeshAssetPath, "");
                }
            }

            //create xml with navmeshlink and starting points
            GlobalLocation globalLocation = new GlobalLocation();
            if (navmeshAssetPath.Length > 0 && data != null)
            {
                globalLocation.navmeshData = new NavmeshData()
                {
                    link = navmeshAssetPath, name = data.name
                };
                if (exportPlayerPositionsInLocations)
                {
                    globalLocation.positions = new List <PositionData>();
                    WG_Position[] positions = WG_Helper.FindObjectsOfTypeAll <WG_Position>().ToArray();// FindObjectsOfType<WG_Position>();
                    for (int i = 0; i < positions.Length; i++)
                    {
                        Vector3 pos = positions[i].gameObject.transform.position;
                        IntPair loc = WG_Helper.GetLocationCoordinates(pos, builderComponent.segmentSize);
                        if (loc.u >= builderComponent.segmentsMinX && loc.u <= builderComponent.segmenstMaxX && loc.v >= builderComponent.segmentsMinY && loc.v <= builderComponent.segmenstMaxY)
                        {
                            globalLocation.positions.Add(new PositionData()
                            {
                                positionX = pos.x, positionY = pos.y, positionZ = pos.z
                            });
                        }
                    }

                    if (globalLocation.positions.Count == 0)
                    {
                        Debug.Log("No start positions on the scene. Add default position (0, 0, 0).");
                        globalLocation.positions.Add(new PositionData()
                        {
                            positionX = 0.0f, positionY = 0.0f, positionZ = 0.0f
                        });
                    }
                }


                globalLocation.bounds = new LocationsBounds()
                {
                    minU = builderComponent.segmentsMinX,
                    maxU = builderComponent.segmenstMaxX,
                    minV = builderComponent.segmentsMinY,
                    maxV = builderComponent.segmenstMaxY
                };

                globalLocation.locationSize = new LocationSize()
                {
                    value = builderComponent.segmentSize
                };

                string globalLocationName      = "global_location";
                string globalLocationAssetPath = "Assets" + assetLocationXMLPath + globalLocationName + ".xml";
                globalLocation.Save(globalLocationAssetPath);
                AssetDatabase.ImportAsset(globalLocationAssetPath, ImportAssetOptions.ForceUpdate);
                AssetImporter.GetAtPath(globalLocationAssetPath).SetAssetBundleNameAndVariant("locations/" + globalLocationName, "");

                //export server data
                SavePlayerPositions(builderComponent);
                SaveCollisionMap(serverPath);
                SaveTowerPositions(builderComponent);

                //also export locations data to SO
                GlobalLocationDataSO globalSO = ScriptableObjectUtility.CreateAsset <GlobalLocationDataSO>("Assets" + assetLocationSOPath, globalLocationName);
                globalSO.minU = builderComponent.segmentsMinX;
                globalSO.maxU = builderComponent.segmenstMaxX;
                globalSO.minV = builderComponent.segmentsMinY;
                globalSO.maxV = builderComponent.segmenstMaxY;

                globalSO.size = builderComponent.segmentSize;

                globalSO.navmeshName = data.name;
                globalSO.navmeshLink = navmeshAssetPath;

                if (exportPlayerPositionsInLocations)
                {
                    globalSO.startPositions = new List <Vector3>();
                    for (int pi = 0; pi < globalLocation.positions.Count; pi++)
                    {
                        globalSO.startPositions.Add(new Vector3(globalLocation.positions[pi].positionX, globalLocation.positions[pi].positionY, globalLocation.positions[pi].positionZ));
                    }
                }

                EditorUtility.SetDirty(globalSO);
                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();
                AssetImporter.GetAtPath("Assets" + assetLocationSOPath + globalLocationName + ".asset").SetAssetBundleNameAndVariant("locations_so/" + globalLocationName, "");
            }
#endif
        }