- Home /
How to let handled events / raycasts pass through
First, i really appreciate the way unity team is going with design decision. Looks like they finally started using interfaces and let us override core classes more. But to the problem:
I am using new EventSystem and my GO has a script which implements EventSystems.IPointerClickHandler attached. I am receiving mouse click events. But what i'd like to do, is to optionally let this raycast pass through (after the event is handled), based on the event handler result.
An example would be an object with alpha cut texture. I want to apparently ignore clicking on transparent parts (and let objects behind being clicked on instead), but this decision (whether object with alpha texture was hit or not) should be done by the object itself.
Does the EventSystem or other classes involved support this behaviour?
If not then: I guess i will have to re-raycast with the object being ignored, in that case, is there some way how to invoke the same raycast?
Edit: I've noticed that BaseRaycaster.Raycast works with a list of hit objects; in that case, re-raycasting seems redundant and this should be possible to resolve other way?
Answer by Pangamini · Oct 03, 2014 at 01:11 PM
So i solved this by deriving from the PhysicsRaycaster class
Raycaster first checks the hit gameoObject for components with my IRaycastFilter interface and if it finds some, it will call a method on it, giving it a chance to discard this gameObject from hit list
Since this is still in beta, there's no documentation and no source codes, so i had to use .net reflector to see how the raycaster should work
Any chance you could share this script ? I'm trying to do similar.
Well here it is, but it's quite old now, written in older version of unity so i am not sure if it still works (i am not using it right now)
import UnityEngine
import UnityEngine.EventSystems
class $$anonymous$$yPhysicsRaycaster (PhysicsRaycaster):
override def Raycast(eventData as PointerEventData, resultAppendList as System.Collections.Generic.List[of RaycastResult] ):
if (self.eventCamera != null):
ray = self.eventCamera.ScreenPointToRay(eventData.position)
distance = self.eventCamera.farClipPlane - self.eventCamera.nearClipPlane
arr = Physics.RaycastAll(ray, distance, self.finalEvent$$anonymous$$ask)
if (arr.Length > 1):
comparision = def(one as RaycastHit, two as RaycastHit):
return one.distance.CompareTo(two.distance)
arr.Sort[of RaycastHit](arr, comparision)
if (arr.Length != 0):
eventData.worldPosition = arr[0].point
eventData.worldNormal = arr[0].normal
index = 0
length = arr.Length
while (index < length):
filters = arr[index].collider.gameObject.GetComponentsInParent(IRaycastFilter)
if CheckAllFilters(filters, arr[index]):
item = RaycastResult()
item.gameObject = arr[index].collider.gameObject
item.module = self
item.distance = arr[index].distance
item.index = resultAppendList.Count
resultAppendList.Add(item)
index++
def CheckAllFilters(filters as (Component), raycast as RaycastHit):
if filters.Length == 0:
return true
for filt as IRaycastFilter in filters:
if filt.FilterRaycast(raycast):
return true
return false
import UnityEngine.EventSystems
interface IRaycastFilter():
def FilterRaycast(physHit as RaycastHit) as bool
Here you need to implement this interface in your component and override the method so it returns true when the object is to be hit (use raycasthit data to find the pixel color or whatever you want)