unity3d Raycast Encapsulating Raycast calls


Example

Having your scripts call Raycast directly may lead to problems if you need to change the collision matrices in the future, as you'll have to track down every LayerMask field to accommodate the changes. Depending on the size of your project, this may become a huge undertaking.

Encapsulating Raycast calls may make your life easier down the line.

Looking at it from a SoC principle, a gameobject really shouldn't know or care about LayerMasks. It only needs a method to scan its surroundings. Whether the raycast result returns this or that shouldn't matter to the gameobject. It should only act upon the information it receives and not make any assumptions on the environment it exists in.

One way to approach this is to move the LayerMask value to ScriptableObject instances and use those as a form of raycast services that you inject into your scripts.

// RaycastService.cs
using UnityEngine;

[CreateAssetMenu(menuName = "StackOverflow")]
public class RaycastService : ScriptableObject
{
    [SerializeField]
    LayerMask layerMask;

    public RaycastHit2D Raycast2D(Vector2 origin, Vector2 direction, float distance)
    {
        return Physics2D.Raycast(origin, direction, distance, layerMask.value);
    }

    // Add more methods as needed

}
// MyScript.cs
using UnityEngine;

public class MyScript : MonoBehaviour
{
    [SerializeField]
    RaycastService raycastService;

    void FixedUpdate()
    {
        RaycastHit2D hit = raycastService.Raycast2D(Vector2.zero, Vector2.down, 1f);
    }
}

This allows you to make a number of raycast services, all with different LayerMask combinations for different situations. You could have one that hits only ground colliders, and another that hits ground colliders and one way platforms.

If you ever need to make drastic changes to your LayerMask setups, you only need to update these RaycastService assets.

Further reading