Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by ArsDiaboli · Nov 15, 2014 at 11:42 PM · 2dpolygon collider 2dhitbox

Can't delete random vertices from a PolygonCollider

This has me tearing my hair off.

This webm illustrates the problem. I've been trying to make melee combat hitboxes with placeholder sprites. This link started me out. As you can see in the example webm, I'm trying to make the arm the hitbox, and this same technique will be applied to other animations. The method itself works. I've successfully generated trigger collisions. BUT there is one problem here that leads to another:

alt text

I can't delete those extra vertices. Ever. I've tried deleting in a different order, but I always have the same vertices left, and you can see them in the webm as triangles in the legs and pelvis of the character. And no matter what I do, they can't be deleted.

Why does it matter? Because of this line:

              localCollider.SetPath(0, colliders[(int)val].GetPath(0));

The path (polygon) I will get from GetPath will be 0. This would be perfectly fine... if I could delete those triangles. But since I can't, GetPath(0) has a high chance of returning one of those triangles, instead of the polygon I want (the box in arm in this case). I have no way to know which index is the correct one so I can use it, instead of hard coding GetPath(0), nor can I delete the extra paths (triangles) to just leave GetPath as it is now.

I don't know what to do with this problem. I've tried other methods for the hitboxes, but none were to my liking, so I'm not sure what to do anymore. Suggestions?

triangles.jpg (180.4 kB)
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by ArsDiaboli · Nov 22, 2014 at 07:02 PM

Another coder helped me with this problem. This is the solution that we ended up with.

Since the polygon collider behaved the way I mentioned above, the other coder made 2 script to let me add points to the current gameobject, using this as a replacement for the polygon collider.

This is the script for the custom inspector:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 
 using UnityEngine;
 using UnityEditor;
 
 [CustomEditor(typeof(PolygonHitboxShape))]
 public class PolygonHitboxShapeEditor : Editor
 {
     public override void OnInspectorGUI()
     {
         var phs = target as PolygonHitboxShape;
 
         this.DrawDefaultInspector();
 
         if (GUILayout.Button("Add new point"))
         {
             Undo.RecordObject(target, "Added PolygonHitboxShape point");
 
             // put new point in position that's an average of all of them
             float ax = phs.points.Count > 0 ? phs.points.Average((px) => px.x) : 0f;
             float ay = phs.points.Count > 0 ? phs.points.Average((py) => py.y) : 0f;
             phs.points.Add(new Vector2(ax, ay));
 
             EditorUtility.SetDirty(phs);
         }
 
         for (int i = 0; i < phs.points.Count; i++)
         {
             if (GUILayout.Button("Delete point #" + i))
             {
                 Undo.RecordObject(target, "Deleted PolygonHitboxShape point " + i);
                 phs.points.RemoveAt(i);
                 EditorUtility.SetDirty(phs);
             }
         }
     }
 
     void OnSceneGUI()
     {
         var phs = target as PolygonHitboxShape;
 
         if (!phs.enabled)
             return;
 
         // unity only adds to the undo list if GUI.changed happens during this func
         Undo.RecordObject(target, "Changed PolygonHitboxShape points");
 
         // fudge factor for moving numbers out of the way of handles
         var fudgeFactor = HandleUtility.GetHandleSize(phs.transform.position) / 8f;
 
 
         // list of points transformed into absolute scene space. this is what we draw!
         var tps = phs.GetTransformedPoints().ToList();
 
 
         // let user move any points we have
         if (tps.Count > 0)
         {
             for (int i = 0; i < tps.Count; i++)
             {
                 var p = tps[i];
                 var pAfter = Handles.PositionHandle(p, Quaternion.identity);
 
                 // put little numbers next to them
                 Handles.Label(new Vector3(p.x, p.y - fudgeFactor, 0f), i.ToString());
 
                 if (GUI.changed)
                 {
                     phs.points[i] = phs.UntransformPoint(new Vector2(pAfter.x, pAfter.y));
                     EditorUtility.SetDirty(phs);
                 }
             }
         }
 
         // draw big polygon to show the bounds (in case drawDebugGizmo is off)
         if (tps.Count > 0)
         {
             Handles.color = phs.gizmoColor ?? phs.defaultGizmoColor;
 
             Handles.DrawPolyLine(tps.Union(new Vector2[] { new Vector2(tps[0].x, tps[0].y + 0.000001f) })
                 .Select((v2) => new Vector3(v2.x, v2.y, 0f)).ToArray());
         }
     }
 }
 

The above code is dropped in the Editor folder, and you can see the PolygonHitboxShape class. That's the script used to create the polygon points, and is the next script:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 
 using UnityEngine;
 using UnityEditor;
 
 [ExecuteInEditMode]
 public class PolygonHitboxShape : MonoBehaviour
 {
     // delete this field if you don't want it
     // (can use this to have multiple PolygonHitboxShapes on the same gameobject)
     public int number = 0;
 
     // i like generic lists. so sue me.
     // (List<T> is the one generic type Unity will serialize)
     public List<Vector2> points = new List<Vector2>();
 
     public Vector2 UntransformPoint(Vector2 v)
     {
         var v3 = this.transform.InverseTransformPoint(v);
         return new Vector2(v3.x, v3.y);
     }
 
     public IEnumerable<Vector2> GetTransformedPoints()
     {
         // transform point (implicit cast Vector2->Vector3) then turn back into Vector2
         return points.Select((v) => this.transform.TransformPoint(v)).Select((v3) => new Vector2(v3.x, v3.y));
     }
 
     // 
     // DEBUG VISUALIZATION STUFF FOLLOWS
     // 
     // (Note that the PolygonHitboxShapeEditor also has code for drawing the shape!)
 
     // DrawDebugGizmo could be set by the user, or you could set it at runtime so it's only visible
     //  when this hitbox is 'active'.
     public bool drawDebugGizmo = false;
     public Color defaultGizmoColor = Color.green;
 
     /// <summary>
     /// Overrides gizmo color. (Make me red on enter collision, for example, and set back to null on exit!)
     /// </summary>
     [HideInInspector]
     public Color? gizmoColor = null;
 
     void OnDrawGizmos()
     {
         if (drawDebugGizmo)
         {
             var tps = GetTransformedPoints().ToList();
 
             if (tps.Count == 0)
                 return;
 
             Gizmos.color = gizmoColor ?? defaultGizmoColor;
 
             // 0->1, 1->2, .., n-1 -> n
             for (int i = 1; i < tps.Count; i++)
                 Gizmos.DrawLine(tps[i - 1], tps[i]);
 
             // n->0
             Gizmos.DrawLine(tps[tps.Count - 1], tps[0]);
         }
     }
 
     // so that you can tick/untick the PHS in the Inspector window
     void Update() { }
 }
 

The above script is your replacement for the PolygonCollider. Instead of having the PolyCollider like the reference I used, you use this script and add points to whatever GameObject has the script attached.

Finally, this required me to edit the initial code.

 using UnityEngine;
 using System.Collections;
 using System.IO;
 using UnityEditor;
 
 //Based on http://answers.unity3d.com/questions/372252/how-can-i-do-frame-by-frame-hitbox-control-for-a-2.html
 public class HitboxManagerScript : MonoBehaviour {
 
     public GameObject hitbox;
 
     public PolygonHitboxShape[] polyColliders;
     // Collider on this game object
     private PolygonCollider2D localCollider;
 
     void Start()
     {
         // Create a polygon collider
         localCollider = hitbox.gameObject.AddComponent<PolygonCollider2D>();
         localCollider.isTrigger = true; // Set as a trigger so it doesn't collide with our environment
         localCollider.pathCount = 0; // Clear auto-generated polygons
     }
     
     public void setHitBox(animationEnum.hitBoxes val)
     {
         if (val != animationEnum.hitBoxes.clear) {
             Vector2[] points = new Vector2[polyColliders [(int)val].points.Count];
             for (int i = 0; i < points.Length; i++) {
                     points [i] = polyColliders [(int)val].points [i];
             }
             localCollider.SetPath (0, points);
             return;
         }
         localCollider.pathCount = 0;
     }
 
     void OnValidate(){
         //It's ugly as sin, but it works. Generates the enum to use.
          string copyPath = "Assets/Scripts/Autogenerated/AnimationEnumAutogenScript.cs";
          using (StreamWriter outfile = new StreamWriter(copyPath)) {
             outfile.WriteLine("using UnityEngine;");
             outfile.WriteLine("using System.Collections;");
             outfile.WriteLine("");
             outfile.WriteLine("public class animationEnum : MonoBehaviour {");
             outfile.WriteLine("public enum hitBoxes {");
             for (int i = 0; i < polyColliders.Length; i++) {
                 outfile.Write(polyColliders[i].name);
                 outfile.WriteLine(",");
             }
             outfile.WriteLine("clear");
             outfile.WriteLine("}");
             outfile.WriteLine(" ");
             outfile.WriteLine("}");
          }
          AssetDatabase.Refresh();
     }
 }
 

Since I wanted to use a dropdown in the Animator editor, I needed that enum. This creates an enum after you add a new hitbox to your manager. The hitbox manager itself is just added to the GameObject that you want to have the animations and hitboxes, like the link I referred to did.

It's rough around the edges and chances are that there are better ways to do this, but as it is, it's working just fine for us now.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

2 People are following this question.

avatar image avatar image

Related Questions

Polygon Collider 2D Problem. 1 Answer

"Double transform" on 2D hitboxes when root motion is enabled 0 Answers

2D polygon collider support? 1 Answer

collider y radius freeze 0 Answers

[2D] Enable colliders around the player based on the direction of the mouse click 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges