Last active
October 10, 2023 15:42
-
-
Save Pholith/585a86b0c7da0dc034aef430c8c2ebe2 to your computer and use it in GitHub Desktop.
Component to pass Input event like PointerEnter to object displayed throught a RenderTexture
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Linq; | |
using Unity.VisualScripting; | |
using UnityEngine; | |
using UnityEngine.EventSystems; | |
using UnityEngine.UI; | |
/// <summary> | |
/// Add this component to send input event on physical object rendered on a render texture that is showed on the GUI as a rawImage. | |
/// This component should be put on the main camera object. | |
/// The main camera must have a GraphicRaycaster. | |
/// The camera of the render texture should have a PhysicsRaycaster. If not it will be added. The PhysicRaycaster should be disabled. | |
/// </summary> | |
public class RenderTextureRaycaster : BaseRaycaster | |
{ | |
public GraphicRaycaster graphicRaycaster; // Reference to the PhysicsRaycaster of the main camera | |
Camera mainCamera; // The main camera | |
BaseRaycaster mainCameraRaycaster; | |
public override Camera eventCamera => mainCameraRaycaster.eventCamera; | |
// Gizmos debug purpose | |
Ray secondCameraRayOriginPosition; | |
Ray secondCameraRayComputedPosition; | |
Ray mainCameraRayGizmo; | |
RaycastHit hitGizmos; | |
private void OnDrawGizmos() | |
{ | |
Gizmos.color = Color.cyan; | |
Gizmos.DrawRay(secondCameraRayOriginPosition); | |
Gizmos.color = Color.blue; | |
Gizmos.DrawRay(secondCameraRayComputedPosition); | |
Gizmos.DrawSphere(hitGizmos.point, 0.01f); | |
Gizmos.color = new Color(0.9f, 0.5f, 0.9f); | |
Gizmos.DrawRay(mainCameraRayGizmo); | |
} | |
protected override void Awake() | |
{ | |
base.Awake(); | |
mainCamera = GetComponent<Camera>(); | |
mainCameraRaycaster = mainCamera.GetComponent<BaseRaycaster>(); | |
} | |
// Called by Unity when a Raycaster should raycast because it extends BaseRaycaster. | |
public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList) | |
{ | |
// Create a new event data so the next raycaster still have the origin eventData. | |
PointerEventData newEventData = new PointerEventData(EventSystem.current); | |
newEventData.position = Input.mousePosition; | |
List<RaycastResult> raycastResultList = new(); | |
graphicRaycaster.Raycast(newEventData, raycastResultList); | |
if (raycastResultList.Count > 0 && raycastResultList.First().gameObject.TryGetComponent(out RawImage rawImg)) | |
{ | |
RenderTexture renderTexture = rawImg.texture as RenderTexture; | |
if (renderTexture == null) return; | |
Camera secondCamera = GetCameraFromRenderTexture(renderTexture); | |
if (secondCamera == null) return; | |
PhysicsRaycaster raycaster = secondCamera.GetOrAddComponent<PhysicsRaycaster>(); | |
// Disable the raycaster to not send event when the mouse is not in the RenderTexture | |
raycaster.enabled = false; | |
#if UNITY_EDITOR // Debug only code | |
secondCameraRayOriginPosition = secondCamera.ScreenPointToRay(newEventData.position); | |
mainCameraRayGizmo = mainCamera.ScreenPointToRay(newEventData.position); | |
#endif | |
raycastResultList.Clear(); | |
Vector2 mouseRelativePositionOnTexture = rawImg.rectTransform.InverseTransformPoint(newEventData.position); | |
newEventData.position = secondCamera.ScreenToViewportPoint(mouseRelativePositionOnTexture) * new Vector2(secondCamera.pixelWidth, secondCamera.pixelHeight) * 2; | |
#if UNITY_EDITOR // Debug only code | |
secondCameraRayComputedPosition = secondCamera.ScreenPointToRay(newEventData.position); | |
Physics.Raycast(secondCameraRayComputedPosition, out hitGizmos, int.MaxValue, raycaster.eventMask); | |
#endif | |
// Remove the Render texture from the list | |
resultAppendList.RemoveAt(0); | |
raycaster.Raycast(newEventData, resultAppendList); | |
} | |
} | |
private Camera GetCameraFromRenderTexture(RenderTexture renderTexture) | |
{ | |
foreach (Camera camera in Camera.allCameras) | |
{ | |
if (camera.targetTexture != null && camera.targetTexture == renderTexture) return camera; | |
} | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment