What's a reliable way to detect if an object is no longer being hit by a ray?

I’m aware raycasts are event driven and that colliders can’t physically detect if they’re being hit by a ray, and I’m aware of a way around it by sending a message to whatever a ray hits and keeping an object of its last hit and sending a message to that cached object when the ray returns not hitting anything, but it doesn’t seem to be working 100% of the time.

void CreateRay(Ray ray, float length)
	{
		if(Physics.Raycast (ray, out hit, length))
		{
			if(lastHit == null)
				lastHit = hit.collider.gameObject;
			if(lastHit != null && lastHit != hit.collider.gameObject)
			{
				lastHit.SendMessage("NotHitByRay", 0, SendMessageOptions.DontRequireReceiver);
				lastHit = hit.collider.gameObject;
			}
			lr.SetPosition (1, hit.point);
			ReflectionInfo ri = new ReflectionInfo(ray.direction, hit);
			if(hit.collider.gameObject.tag == "reflector")
			{
				hit.collider.gameObject.SendMessage("HitByRay", ri, SendMessageOptions.DontRequireReceiver);
			}

		}
		else
		{

			if(lastHit != null)
				lastHit.SendMessage ("NotHitByRay", 0, SendMessageOptions.DontRequireReceiver);
			lastHit = null;
			lr.SetPosition (1, start+(direction * 20f));
		}

	}

You can see I’m redundant about sending the NotHit message only because I still can’t make it trigger all the time.

This is the receiver

void HitByRay(ReflectionInfo info)
	{
		reflectInfo = info;
		if (!active) {
			reflect ();
			active = true;
		}
	}
	
	void NotHitByRay(int num)
	{
		Destroy (reflection);
		active = false;
	}

The main issue is NotHitByRay is not beingcalled, and the laser reflections persist when the source laser stops hitting the object. IDK, is there an approach I am not seeing that could make it work?

Don’t use SendMessage. Just make the method public, get the receiver component, and invoke the method on it. Vastly superior.

public void HitByRay(){}

Receiver receiver = hit.collider.GetComponent<Receiver>() as Receiver;
if (receiver) receiver.HitByRay();

“keeping an object of its last hit and sending a message to that cached object when the ray returns not hitting anything”

This is not foolproof. Not without a good bit of case-planning and forethought. Caching the object and sending a “not hitting something” event might seem like a smart optimization, but comes with complications that make it unfavorable, which you’re obviously witnessing.

Just invoke the receiver method on the hit object each frame. This is not really more expensive in this particular situation, and should be 100% foolproof.

Generally this means changing your logic around a bit. You’re creating the equivalent of an “OnRaycastStay” event instead of Enter/Exit events. Enter/Exit events can be done, but you have to plan for every possible contingency. In many if not most cases, the performance gain isn’t worth it. Sounds like a breeding ground for bugs to me, unless you know exactly what you’re doing.