- Home /
Raycast inside a RenderTexture
Hello everyone!
I have a Scene with the Main Camera that looks at a Mesh. The Mesh texture is a RenderTexture from a second "portal" Camera (nothing fancy here, it's the usual setup for minimaps or portals).
I need to be able to touch the elements inside the RenderTexture, so I have written this code here:
if (Mouse.current.leftButton.wasPressedThisFrame)
{
Ray ray;
RaycastHit hit;
ray = mainCamera.ScreenPointToRay(Mouse.current.position.ReadValue());
if (Physics.Raycast(ray, out hit) && hit.collider == portalMeshCollider)
{
ray = portalCamera.ViewportPointToRay(hit.textureCoord);
if (Physics.Raycast(ray, out hit))
{
Debug.Log("something inside the render texture was hit " + hit);
}
}
}
and it works, but in order to make it work I first have to turn on/off the convexity of the MeshCollider like this first:
portalMeshCollider.convex = true;
portalMeshCollider.convex = false;
I don't understand why this is the case and especially I don't understand if this is a reliable workaround or if there might be problems.
Thanks for your help!
Answer by mylastggeast · Oct 27, 2021 at 12:22 PM
In the end I think I got what was going on: I had disabled "Auto Simulation" and "Auto Sync Transforms" from the Physics tab in the Project Settings so colliders were not updating when I moved or animate them. "Auto Sync Transforms" seems to be enough if physics is not needed.
Answer by Eno-Khaon · Sep 30, 2021 at 08:52 AM
When you instruct a MeshCollider to be convex, Unity generates a new collision shell around the Mesh.
Because of this, it's no longer a 1:1 representation of that Mesh. If you hit the collider, there's no longer a correlation between where on the collider you hit and the exact location on the UV coordinate space that you hit.
What it essentially boils down to is:
Is it absolutely necessary to use the UV coordinates to determine where on the Mesh/Collider the Raycast hit?
If the surface is simply a flat plane anyway (or any shape, technically, depending on how much work it will involve), there are other ways you can resolve the relative point of impact of the Raycast.
For an example using a 1x1 quad surface, the point of impact would be something like:
Vector3 localHitPoint = portalMeshCollider.transform.InverseTransformPoint(hit.point);
// If I'm not mistaken, this should be necessary to
// offset into the right local coordinate for Unity's
// "Quad" object, where its pivot point is at its center
Vector3 halfOffset = new Vector3(0.5f, 0.5f, 0.0f);
ray = portalCamera.ViewportPointToRay(localHitPoint + halfOffset);
Answer by mylastggeast · Sep 30, 2021 at 10:17 AM
Thanks for your reply!
The surface I am casting against resembles a flat plane but it's not 100% flat, as it's a little curved and can be animated over time. Think of it as a page in a book that can flip left or right or be curved etc. This is the main reason why I was going for the uv approach.
I will later try your approach, but I also wanted to ask if in your opinion having the convex turned on and off could cause issues?
Whether having the Convex Collider generated would "cause issues" depends on whether you intend for the GameObject to be moved around automatically by the physics engine.
When Unity updated to a newer version of PhysX with Unity 5.0, this removed the possibility of a Concave Collider being able to be physics-driven.
If you don't need to move the object around (as in, naturally moving and/or tumbling), then your approach should be just fine using a Concave Collider.
The "risk" it poses, for reference, is that a Convex Collider effectively has volume to it, while a Concave Collider is like a paper-thin shell. In a worst-case scenario, it's more-possible for other objects to pass through a Concave Collider without the objects' positions being properly rectified (i.e. they'd be embedded in each other).
At any rate, having a little bit more context like this, there's definitely no "problem" doing things the way you are, and using a Concave Collider to do so. The aforementioned "risk" is generally quite $$anonymous$$imal to begin with. If you have a specific, absolute *NEED* to have the object be driven by a non-kinematic Rigidbody, then it would be time to look at any of a large variety of alternative methods to using a UV coordinate look-up directly from the RaycastHit.
Thanks for the super detailed answer! The object is going to be completely static beside animations, so I guess my approach above will work and I will stick to it for the time being. If I can bother you one last time, I still don't quite understand why I need to set convex to true and then to false immediately to make this work?
Hmm... now that you mention it, that does seem kind've strange...
Based on a quick reference of a previous answer here and a linked page from it here, I would suspect that changing the attributes of the Mesh forces it to be readable (when the Collider is forcibly rebuilt, then reset).
With that in $$anonymous$$d, are there any elements of your Mesh creation/animation/usage which seem like it would specifically be unloaded from memory?