Monday, April 21, 2014

Raycasting in Unity and the Pursuit for more OOP


 Something that I think most developers find when they start getting in to doing complex character animations in Unity using the 2D libraries is that the built in collision leaves something to be desired.  The go to solution for getting better collision is using raycasting and essentially building your own collision detection from scratch.

Recently I've been reworking all my scripts in to solid object oriented classes.  I should have done it from the start, but with all the code examples out there being condensed into single scripts it was bothersome to do it on the fly.  Anywho, here's the class I recently made to handle raycasting for my collision detection, I thought I'd share it today. I'd also like to go over my process for improving the script and making it more useful, saving loads of effort in the long run.


using UnityEngine;
using System.Collections;



public class RaycastDetect : MonoBehaviour {
   
    public bool rayDetected = false; //set detection false by default

    bool RaycastDetection(Transform rayStartingPoint, Transform rayEndPoint, string rayLayerToDetect, bool debug) {   
   if  (debug) {
        Debug.DrawLine(rayStartingPoint.position,rayEndPoint.position, Color.green);
        }
        rayDetected = Physics2D.Linecast(rayStartingPoint.position, rayEndPoint.position, 1<< LayerMask.NameToLayer(rayLayerToDetect));

        return rayDetected;
    }
    }

So as it stands, it takes two transforms and a layer to detect and draws the line, with an option for a debug mode so you can see the lines during development.  The issues here are that for proper collision detection you have to repeat this method a lot just for one direction, and that the debug often isn't needed or desired after the first test.    We can easily overload the RaycastDetection method so that the developer can pass in arrays of transforms, and then iterate through them.  This would be much faster on the development side, and as long as arrays don't get too large the execution shouldn't slow down.  Also, we can provide an option where you don't have to put anything about the debug in.


The first overloaded class would look like this:

    bool RaycastDetection(Transform[] rayStartingPoint, Transform[] rayEndPoint, string[] rayLayerToDetect)  { 
      
        int rayArraySize1 = rayStartingPoint.GetLength;  
        int rayArraySize2 = rayEndPoint.GetLength;   
        int rayArraySize3 = rayLayerToDetect.GetLength;
     
        for(int i =0; i         {
            int j = 0;

            for(int k = 0;k < rayArraySize3;k++)
            {
            rayDetected = Physics2D.Linecast(rayStartingPoint[i].position, rayEndPoint[j].position, 1<< LayerMask.NameToLayer(rayLayerToDetect[k]));
          
            if(rayDetected)return rayDetected;
            }
            if(j < rayArraySize2)j++;
        }      
        return rayDetected;
    }


Then it would be pretty simple to swap that around to allow each option of array and two single values and two arrays and one single value, with all single values already being done.  For the debugless class overload we just delete the debug bool option and the code for that.  If we wanted to make the class useable for 3D as well, we should be able to just delete the 2D after the physics and it should work fine.

I have the full class available on my public BitBucket account:  https://bitbucket.org/milam_dobbins/milams-repo/src/

No comments:

Post a Comment