public void SetDirection(World.Direction d) { direction = (int)d; if (d == World.Direction.UP) { colli = colliUp; climbArea = climbAreaUp; } else if (d == World.Direction.DOWN) { colli = colliDown; climbArea = climbAreaDown; } }
// default public ClimbAction(Character owner) : base(owner) { //this(owner, Type.Attack, 1f, 1f, false, false, true, "Character_Attack"); this.timeout = 0f; this.type = Type.Climb; this.isCancelable = true; this.isRepeatable = true; this.isSpeedChangable = true; this.animationName = owner.GetClassName() + "_Walk"; //===== new attribute here ======= colliUp = owner.transform.Find("ClimbAreaUp").GetComponent <Collider2D> (); climbAreaUp = colliUp.GetComponent <ClimbArea> (); colliDown = owner.transform.Find("ClimbAreaDown").GetComponent <Collider2D>(); climbAreaDown = colliDown.GetComponent <ClimbArea>(); colli = colliUp; climbArea = climbAreaUp; Init(); }
static void ExportClimbArea(int method, int imgwidth, int imgheight) { float fimgwidth = imgwidth; float fimgheight = imgheight; Rectangle rc = new Rectangle(0, 0, imgwidth, imgheight); System.Drawing.Bitmap img = new System.Drawing.Bitmap(imgwidth, imgheight); System.Drawing.Graphics gdi = System.Drawing.Graphics.FromImage(img); gdi.Clear(System.Drawing.Color.Black); //--------------------------------------------------------- // find renderers //--------------------------------------------------------- List <Renderer> renderers = new List <Renderer>(); GameObject[] groupgos = Selection.gameObjects; foreach (GameObject groupgo in groupgos) { Renderer[] mrs = groupgo.GetComponentsInChildren <Renderer>(); if (mrs == null) { continue; } renderers.AddRange(mrs); } //--------------------------------------------------------- // calc max bound and min bound of whole grass map //--------------------------------------------------------- Vector3 worldmin = new Vector3(9999999.0f, 9999999.0f, 9999999.0f); Vector3 worldmax = new Vector3(-9999999.0f, -9999999.0f, -9999999.0f); foreach (Renderer mr in renderers) { Bounds bound = mr.bounds; Vector3 min = bound.min; Vector3 max = bound.max; if (min.x < worldmin.x) { worldmin.x = min.x; } if (min.y < worldmin.y) { worldmin.y = min.y; } if (min.z < worldmin.z) { worldmin.z = min.z; } if (max.x > worldmax.x) { worldmax.x = max.x; } if (max.y > worldmax.y) { worldmax.y = max.y; } if (max.z > worldmax.z) { worldmax.z = max.z; } } Vector3 worldsize = worldmax - worldmin; Vector3 worldcenter = (worldmax + worldmin) * 0.5f; worldsize *= 1.1f; worldmax = worldcenter + worldsize * 0.5f; worldmin = worldcenter - worldsize * 0.5f; //--------------------------------------------------------- // generate sub area //--------------------------------------------------------- System.Drawing.Brush whitebrush = new System.Drawing.SolidBrush(System.Drawing.Color.White); List <ClimbArea> areas = new List <ClimbArea>(); for (int k = 0; k < renderers.Count; k++) { Mesh mesh = null; Renderer mr = renderers[k] as Renderer; if (null == mr) { continue; } if (mr.GetType() == typeof(MeshRenderer)) { MeshFilter mf = mr.GetComponent <MeshFilter>(); if (mf == null) { continue; } mesh = Application.isPlaying ? mf.mesh : mf.sharedMesh; } else { SkinnedMeshRenderer skin = mr as SkinnedMeshRenderer; mesh = skin.sharedMesh; } if (mesh == null) { continue; } Transform tran = renderers[k].transform; List <PointF> nodes = new List <PointF>(); List <PointF> vertexs = new List <PointF>(); for (int i = 0; i < mesh.vertexCount; i++) { Vector3 vertex = mesh.vertices[i]; Vector3 pos = tran.TransformPoint(vertex); PointF point = new PointF(); point.X = (pos.x - worldmin.x) / worldsize.x * fimgwidth; point.Y = fimgheight - 1.0f - (pos.z - worldmin.z) / worldsize.z * fimgheight; nodes.Add(point); PointF vert = new PointF(); vert.X = pos.x; vert.Y = pos.z; vertexs.Add(vert); } ConvexAogrithm ca = new ConvexAogrithm(nodes); Stack <PointF> p_nodes = ca.GetResult(); PointF[] convex = p_nodes.ToArray(); ConvexAogrithm cv = new ConvexAogrithm(vertexs); Stack <PointF> p_verts = cv.GetResult(); gdi.Clear(System.Drawing.Color.Black); gdi.FillPolygon(whitebrush, convex); gdi.Flush(); System.Drawing.Imaging.BitmapData bmp = img.LockBits(rc, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); int stride = imgwidth * 4; byte[] data = new byte[imgwidth * imgheight * 4]; Marshal.Copy(bmp.Scan0, data, 0, imgwidth * imgheight * 4); img.UnlockBits(bmp); Hashtable bits = new Hashtable(); for (int y = 0; y < imgheight; y++) { for (int x = 0; x < imgwidth; x++) { int g = data[y * stride + x * 4 + 1]; if (g != 0) { bits[y * imgwidth + x] = g; } } } //区域点输出规则: //飞檐走壁为一个cube,所以区域点为4个顶点的矩形 //取最短的边开始,顺时针或逆时针方向输出 //因此,AB CD为短边,BC为长边 int minEdgeIndex = 0; float minEdgeLength = -1.0f; PointF[] e_verts = p_verts.ToArray(); int e_vertsLen = e_verts.Length; for (int i = 0; i < e_vertsLen; i++) { int j = (i + 1) % e_vertsLen; Vector2 pa = new Vector2(e_verts[i].X, e_verts[i].Y); Vector2 pb = new Vector2(e_verts[j].X, e_verts[j].Y); float edgeLength = (pa - pb).magnitude; if (minEdgeLength < 0 || minEdgeLength > edgeLength) { minEdgeIndex = i; minEdgeLength = edgeLength; } } PointF[] o_verts = new PointF[e_vertsLen]; for (int i = 0; i < e_vertsLen; i++) { int j = (i + minEdgeIndex) % e_vertsLen; o_verts[i] = e_verts[j]; } ClimbArea newArea = new ClimbArea(); newArea.mr = renderers[k]; newArea.convex = convex; newArea.bits = bits; newArea.vertex = o_verts; areas.Add(newArea); float fProgress = (float)k / (float)renderers.Count; EditorUtility.DisplayProgressBar("Export Climb Map", "Generate Area...", fProgress); } whitebrush.Dispose(); whitebrush = null; EditorUtility.ClearProgressBar(); //--------------------------------------------------------- // export //--------------------------------------------------------- string imgpath = EditorUtility.SaveFilePanel("climbArea map", Application.dataPath, "climbAreaMap", "jpg"); string csvpath = ""; if (imgpath.Length > 3) { csvpath = imgpath.Substring(0, imgpath.Length - 3) + "csv"; } StreamWriter sw = null; if (csvpath.Length > 3) { sw = new StreamWriter(csvpath, false); } if (sw != null) { // sw.WriteLine("?,undefied,undefied,undefied,undefied,undefied,undefied,undefied,undefied,undefied,undefied"); // sw.WriteLine("?,undefied,undefied,undefied,undefied,undefied,undefied,undefied,undefied,undefied,undefied"); // sw.WriteLine("#,minx,minz,maxx,maxz"); // sw.WriteLine("world" + "," + worldmin.x.ToString() + "," + worldmin.z.ToString() + "," + worldmax.x.ToString() + "," + worldmax.z.ToString()); // sw.WriteLine("#,area,subarea,colorr,colorg,colorb,minx,minz,maxx,maxz,convex"); { sw.WriteLine("area,subarea,colorr,colorg,colorb,bmp_minx,bmp_minz,bmp_maxx,bmp_maxz,minx,minz,maxx,maxz,convex"); sw.WriteLine("int,int,int,int,int,float,float,float,float,float,float,float,float,string"); } } gdi.Clear(System.Drawing.Color.Black); int areacount = 0; foreach (ClimbArea area in areas) { int colorindex = areacount + 1; int b = colorindex % 4; int g = (colorindex / 4) % 4; int r = colorindex / (4 * 4); r *= 64; g *= 64; b *= 64; if (r > 255) { r = 255; } if (g > 255) { g = 255; } if (b > 255) { b = 255; } System.Drawing.Color c = System.Drawing.Color.FromArgb(r, g, b); System.Drawing.Brush brush = new System.Drawing.SolidBrush(c); if (method == 1) { gdi.FillPolygon(brush, area.convex); } else if (method == 2) { MeshFilter mf = area.mr.GetComponent <MeshFilter>(); if (mf == null) { continue; } Mesh mesh = Application.isPlaying ? mf.mesh : mf.sharedMesh; if (mesh == null) { continue; } Transform tran = mf.transform; for (int j = 0; j < mesh.triangles.Length / 3; j++) { int[] indices = new int[3]; for (int i = 0; i < 3; i++) { indices[i] = mesh.triangles[j * 3 + i]; } Vector3[] vertices = new Vector3[3]; for (int i = 0; i < 3; i++) { vertices[i] = mesh.vertices[indices[i]]; } Vector3[] positions = new Vector3[3]; for (int i = 0; i < 3; i++) { positions[i] = tran.TransformPoint(vertices[i]); } System.Drawing.PointF[] points = new System.Drawing.PointF[3]; for (int i = 0; i < 3; i++) { points[i].X = (positions[i].x - worldmin.x) / worldsize.x * fimgwidth; points[i].Y = fimgheight - 1.0f - (positions[i].z - worldmin.z) / worldsize.z * fimgheight; } gdi.FillPolygon(brush, points); } } else { Bounds bound = area.mr.bounds; Vector3 min = bound.min; Vector3 max = bound.max; float px = (min.x - worldmin.x) / worldsize.x * (float)imgwidth; float py = 511.0f - (min.z - worldmin.z) / worldsize.z * (float)imgheight; float pw = (max.x - min.x) / worldsize.x * (float)imgwidth; float ph = (max.z - min.z) / worldsize.z * (float)imgheight; py -= ph; gdi.FillRectangle(brush, px, py, pw, ph); } if (sw != null) { string convexstr = ""; foreach (PointF pt in area.vertex) { convexstr += "{" + pt.X.ToString() + "|" + pt.Y.ToString() + "};"; } // sw.WriteLine("area" + "," // + areacount.ToString() + "," // + k.ToString() + "," // + r.ToString() + "," // + g.ToString() + "," // + b.ToString() + "," // + subarea.mr.bounds.min.x.ToString() + "," // + subarea.mr.bounds.min.z.ToString() + "," // + subarea.mr.bounds.max.x.ToString() + "," // + subarea.mr.bounds.max.z.ToString() + "," // + convexstr // ); { sw.WriteLine(areacount.ToString() + "," + areacount.ToString() + "," + r.ToString() + "," + g.ToString() + "," + b.ToString() + "," + worldmin.x.ToString() + "," + worldmin.z.ToString() + "," + worldmax.x.ToString() + "," + worldmax.z.ToString() + "," + area.mr.bounds.min.x.ToString() + "," + area.mr.bounds.min.z.ToString() + "," + area.mr.bounds.max.x.ToString() + "," + area.mr.bounds.max.z.ToString() + "," + convexstr ); } } brush.Dispose(); brush = null; areacount++; } gdi.Flush(); if (imgpath.Length > 3) { img.Save(imgpath); } if (sw != null) { sw.Close(); sw.Dispose(); sw = null; } gdi.Dispose(); gdi = null; img.Dispose(); img = null; if (imgpath.Length > 3) { Debug.Log("generate climb map ok:" + imgpath); System.Diagnostics.Process.Start(imgpath, ""); } if (csvpath.Length > 3) { Debug.Log("generate climb list ok:" + csvpath); //System.Diagnostics.Process.Start(csvpath, ""); } }