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*;*
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 = 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 is the one generic type Unity will serialize)
public List points = new List();
public Vector2 UntransformPoint(Vector2 v)
{
var v3 = this.transform.InverseTransformPoint(v);
return new Vector2(v3.x, v3.y);
}
public IEnumerable 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;
///
/// Overrides gizmo color. (Make me red on enter collision, for example, and set back to null on exit!)
///
[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*);*
// 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();*
* 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 = polyColliders [(int)val].points ;
* }*
* 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*.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.