Search code examples
c#unity-game-engineuser-interfacegame-physicsraycasting

Grappling hook ray cast direction problems in Unity


Hey team I'm currently working on a 3rd person game where I would like to fire grappling hooks from the player to a point that is offset from the center of the camera.

I have a screen overlay canvas with Ui images for crosshairs. When the left shift is held down the crosshairs move outward from center along the x axis and return to center once shift is released, a bit like crosshair spread in games except I want to trigger the spread via the shift key. These crosshairs are meant to dictate the location the anchors of the grappling hook land, originating from the player and hitting whatever object is directly forward of the crosshairs. (imagine attack on titan ODM gear if you've seen it). I am looking for a way to ray cast from the player to the point forward of these crosshairs while they're offset from the center.

So far I have the grappling system set up and working but am having trouble with the direction parameter when I use the crosshair spread. It separates fine but where the hooks land in relation to the cross hairs are obviously out as I'm trying to use angle calculations at the moment instead of what is forward of these reticles.

I'm basically wondering if it is possible to use these screen overlay UI images to cast forward from or if there's a better way to accomplish the same thing. I have my doubts because they're screen overlay so I imagine their coordinates wont be attached to the camera as they appear.

Thanks in advance for your help.


Solution

  • What I would do is determine the location of the reticleson the screen, then (as Aybe suggested) use ScreenPointToRay or ViewportToRay (depending on if it's easier to get a pixel position or a fractional position of each reticle) to Physics.Raycast that ray from the camera into the scene to find where the rays collide. At this point, you have two world positions the player seems to want to shoot the hooks.:

    Vector3 hookTarget1;
    Vector3 hookTarget2;
    

    So, now you actually have to fire the hooks - but as you know the hooks aren't being shot from the camera, they are being shot from the player, and they maybe offset by a bit. Let's call the originating points (which may have the same value):

    Vector3 hookOrigin1;
    Vector3 hookOrigin2;
    

    So, then you can create Rays that originate from the hook origins and point at the targets:

    Ray hookShot1 = new Ray(hookOrigin1, hookTarget1 - hookOrigin1);
    Ray hookShot2 = new Ray(hookOrigin2, hookTarget2 - hookOrigin2);
    

    Using these rays, you can do another Physics.Raycast if you would like, to confirm that there aren't any trees or other obstacles that are between the player and the target location - and if there are, that may be where the anchor should actually sink:

    Vector3 anchorPoint1;
    Vector3 anchorPoint2;
    

    The segment between the origin of these rays and these anchor points would be appropriate for rendering the cable, calculating physics for how to move the player, as well as checking for collisions with world geometry that might cause the anchor to release.