Debuggery

I was having a terrible time finding if a sword slash hit a barrel or not… which, it clearly did not because the barrel did not trigger a collision. After numerous attempts to figure out what was going on, I started on a path to debug … well … the path the collider was on! So I wrote a script.

I’m using box colliders since everything I’m doing does not require precision. This makes it easy to script up something to highlight the path my colliders have been on.

The code is below. I tossed an MIT license on it so you can use it however you like. You can add it to any game object that has a box collider or add it to an empty object in your scene and reference a box collider. You could even adapt the script to use some other collider if you like.

/**
 * MIT License
 *
 * Copyright (c) 2021 Josiah Olivieri
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

/**
 *
 * this is used to debug the path a box collider proceeds on as the game is played. i am hoping it 
 * proves useful in debugging whether a target is hit or not in combat.
 */
public class DebugColliderPath : MonoBehaviour {

    public bool debugTrail = false;

    public BoxCollider boxCollider;
    public float captureRate = 0.5f;
    public int maxPoints = 10;
    public bool connected = false;
    public Color trailColor = new Color( 1.0f, 0.75f, 0.0f );

    private List<List<Vector3>> debugPath = new List<List<Vector3>>();
    private float lastTimeDebugTrail;

    void Start() {
        if (debugTrail && boxCollider == null) {
            boxCollider = GetComponent<BoxCollider>();
        }
    }

    void FixedUpdate() {
        if (debugTrail) {
            if ( boxCollider == null || boxCollider.gameObject == null ) {
                debugTrail = false;
                return;
            }

            if (Time.time - lastTimeDebugTrail < captureRate)
                return;

            lastTimeDebugTrail = Time.time;

            Vector3 center = boxCollider.center;
            Vector3 boxSize = boxCollider.size / 2.0f;

            List<Vector3> points = new List<Vector3>();
            for (int i = 0; i < 8; i++) {
                Vector3 extents = boxSize;

                extents.Scale( new Vector3( ( i & 1 ) == 0 ? 1 : -1, ( i & 2 ) == 0 ? 1 : -1, ( i & 4 ) == 0 ? 1 : -1 ) );

                Vector3 localPos = center + extents;
                Vector3 globalPos = boxCollider.transform.TransformPoint( localPos );

                points.Add( globalPos );
            }

            debugPath.Add( points );

            if (debugPath.Count > maxPoints)
                debugPath.RemoveAt( 0 );
        }
    }

#if UNITY_EDITOR
    void OnDrawGizmos() {

        if ( debugTrail ) {
            if (boxCollider == null || boxCollider.gameObject == null) {
                debugTrail = false;
                return;
            }

            GUIStyle style = new GUIStyle();
            style.richText = true;
            style.fontSize = 12;

            Color trails = new Color(trailColor.r, trailColor.g, trailColor.b, 0.0f );
            
            float alpha = 0.0f;
            float inc = 1.0f / (float)maxPoints;
            int n = 0;
            if ( debugPath.Count < 1 )
                return;

            var lastPoints = debugPath[0];
            foreach (var points in debugPath) {
                Gizmos.color = trails;

                for ( int i=0; i<7; i++ ) {
                    for ( int j=i+1; j<8; j++ ) {
                        Gizmos.DrawLine( points[i], points[j] );
                    }
                }

                if ( connected ) {
                    Gizmos.color = new Color( trails.b, trails.r, trails.g, alpha );
                    for ( int i=0; i<7; i++ ) {
                        Gizmos.DrawLine( points[i], lastPoints[i] );
                    }
                }
                
                UnityEditor.Handles.Label( points[0], "<color=white>p" + n + "</color>", style );
                n++;

                alpha = alpha + inc; 
                if ( alpha > 1.0f ) alpha = 1.0f;
                trails.a = alpha;
                lastPoints = points;
            }
        }
    }
#endif
}

That’s all for this week. This little example was fun to work on but it also proved useful. (I found that the animation was key-framed to the side of the barrel and past the barrel… so I turned on animate physics and it seems like things… barrels… are breaking correctly now!)