Search Unity

bend a raycast

Discussion in 'Scripting' started by Mike L, Jun 10, 2011.

  1. Mike L

    Mike L

    Joined:
    Sep 14, 2010
    Posts:
    1,035
    is there a way to bend a raycast, to match say a parabola?
     
  2. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    Only if you "split" the raycast into small pieces. You would need more raycast calls, but with shorter rays.
     
  3. Mike L

    Mike L

    Joined:
    Sep 14, 2010
    Posts:
    1,035
    yeah, thats what i thought, and that sounds a little processor intensive, especially for the mobile platforms
     
  4. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    The only thing you could do, is to try different lengths for the rays. I don't know how you plan to use it, but depending on that, you may try different ray lengths and compare how expensive each of those tests is. But I would also tend to say - even without having any mobile experience - it is probably too expensive.
     
  5. Mike L

    Mike L

    Joined:
    Sep 14, 2010
    Posts:
    1,035
    well, its for a grenade aiming system using the quadratic formula, and all im trying to do is put a big blue dot (or it can be a light) where the grenade will land
     
  6. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    Depending on how the environment looks, different tactics may be useful. I personally would make a few raycasts. Depending on where a hit is detected, split that ray again to go closer to the actual hit position and maybe again... That may produce the problem that you miss certain objects with the raycast, so a spherical raycast would be better, but also more expensive.
    I expect you are already aware of that. At the end it very much depends on the environment and how precise that big blue dot should be.
     
  7. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    um why all this fear about mobile cpu performance? physx on mobile is very fast with raycasts. I would just get a curve line going then slot in raycast in place of the line drawing code and try it.

    You will probably find nothing slows down.

    If it slows down and IF it was benchmarked as being the cause then you have several options: reducing resolution of curves, yielding after n millisecs of time to spread across frames, setting up physics so it doesn't raycast every object in the game etc etc...

    All this pre-emptive optimisation is worthless.
     
  8. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    hippocoder, as I have NO experience with mobiles, it is better to be sceptic than optimistic. But you are right. JM Studios needs to test it and then decide what to do.
     
  9. bryanleister

    bryanleister

    Joined:
    Apr 28, 2009
    Posts:
    130
    Is it just for aiming? Couldn't your raycast ignore certain layers so that you can place your blue dot?

    Bryan
     
  10. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    You usually will slow down from graphics long before cpu becomes an issue (its the same for desktops, and practically been the case since forever with desktop cpu's - unless you are doing something like a simulation).

    Nearly always the gpu will be the bottleneck, so it is better to just make it and optimize afterwards as especially with mobiles you can't really be too sure where the bottleneck is in advance. You can take a good guess, and if I had to guess it wouldn't be raycasts - unless you're doing 100 per frame or something :)

    My current developed app has around 256 lines, 64 balls, rotating worlds and 64 modified sound effects per frame with reverb plus full screen normal mapped graphics at 30fps, so I'm probably thinking that its the graphics which dropped my framerate as it was 60fps before the normal mapping.
     
    Last edited: Jun 12, 2011
  11. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    actually thats not true.
    It heavily depends on the game, but slowing down the graphics prior hitting the cpu is normally only happening with badly done artwort that uses blending etc instead of using proper geometry, in which case the fillrate will hammer you.

    Drawcalls for example is a cpu bottleneck, not a gpu one. Same goes for animation, collision, physics
     
    Nihil688 likes this.
  12. Mike L

    Mike L

    Joined:
    Sep 14, 2010
    Posts:
    1,035
    hey, im sorry, i was gone for a week, what was this about physx?
     
  13. Joviex

    Joviex

    Joined:
    Jan 23, 2011
    Posts:
    44
    Maybe I have mis-understood the problem, but two things come to mind:

    A) Why do you need more than 2 ray casts? A parabola is merely a refined curve along two right triangles.

    which leads to B....

    B) Why a raycast at all? You have point A and you calculate a parabola based on the ? you need an input here, is the power a fixed number? Even if it wasn't and it was based on some type of metric, like the player holds a button and releases at the right time to get max power....

    That whole time you could be adjusting the end point mere based on the starting point + parabolic function == end point of parabola which is a straight vector

    Then you just draw the cross hair at the end point.

    Sorry if any of that is confusing, but you shouldn't need to cast multiple rays at all or at the most two, but I think any standard quadradic (ax^2+bx+c) should suffice?

    Again, sorry if I have mis-understood.
     
  14. Sycle

    Sycle

    Joined:
    Nov 24, 2009
    Posts:
    446
    You can't raytrace a straight line because you won't detect when the top of the curve would clip something. (or where the grenade would land if you're throwing it onto a sloped surface) Its an interesting problem.

    I agree with hippocoder - try raycasting in segments first before assuming it will be inefficient.
     
  15. Mike L

    Mike L

    Joined:
    Sep 14, 2010
    Posts:
    1,035
    well, the problem is its uneven terrain, so thats the problem i had with that, i need it to project the light on the place where it will land
     
  16. k3ch0ng

    k3ch0ng

    Joined:
    Jan 23, 2011
    Posts:
    13
    Hi, just wondering if you ever found a solution to this ?
     
  17. Mike L

    Mike L

    Joined:
    Sep 14, 2010
    Posts:
    1,035
    No, but I'm thinking of some now
     
  18. Ntero

    Ntero

    Joined:
    Apr 29, 2010
    Posts:
    1,436
    The Solution is to do it in increments. Instead of 1 Raycast, do 10 or 100.

    Although depending on the need sometimes you could either avoid it all together, or somewhat fake it.
     
  19. Matheusfig

    Matheusfig

    Joined:
    Nov 24, 2012
    Posts:
    5
    you can configure a particle sytem to do it
     
  20. wccrawford

    wccrawford

    Joined:
    Sep 30, 2011
    Posts:
    2,039
    If only you were here over a year ago when they were having the discussion!
     
  21. sjmurray

    sjmurray

    Joined:
    Feb 14, 2013
    Posts:
    1
    Whats this about using particle systems?
     
  22. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    That's also what I wanted to ask. How can a particle system be used to bend or split a raycast?
     
  23. WarpB

    WarpB

    Joined:
    Nov 12, 2013
    Posts:
    14
    I know I'm responding to a very old thread, but in case any one finds this like I did whilst on a search for curved ray cast options, I'm pretty sure Matheusfig was referring to using particle collisions like you would a ray cast. With the ability to add forces over the particles lifetime etc you could potentially get all sorts of weird and wonderful shaped "rays". I just started experimenting with it. Thanks for the point in the right direction Matheusfig! :)

    I would imagine this could potentially be a much easier way to set up raycast bullets too, seeing as you can configure projectile speed and gravity right there in the particle system, without having to mess about simulating it with standard rays.
     
  24. Xelnath

    Xelnath

    Joined:
    Jan 31, 2015
    Posts:
    402
    Here's a curved 2d raycast. Tweak as needed:

    Code (csharp):
    1.  
    2.  
    3.     public static void GetArcHits( out List<RaycastHit2D> Hits, out List<Vector3> Points, int iLayerMask, Vector3 vStart, Vector3 vVelocity, Vector3 vAcceleration, float fTimeStep = 0.05f, float fMaxtime = 10f, bool bIncludeUnits = false, bool bDebugDraw = false )
    4.     {
    5.         Hits = new List<RaycastHit2D>();
    6.         Points = new List<Vector3>();
    7.  
    8.         Vector3 prev = vStart;
    9.         Points.Add( vStart );
    10.  
    11.         for ( int i = 1; ; i++ )
    12.         {
    13.             float t = fTimeStep*i;
    14.             if ( t > fMaxtime ) break;
    15.             Vector3 pos = PlotTrajectoryAtTime (vStart, vVelocity, vAcceleration, t);
    16.  
    17.             var result = Physics2D.Linecast (prev,pos, iLayerMask);
    18.             if ( result.collider != null )
    19.             {
    20.                 Hits.Add( result );
    21.                 Points.Add( pos );
    22.                 break;
    23.             }
    24.             else
    25.             {
    26.                 Points.Add( pos );
    27.  
    28.             }
    29.             Debug.DrawLine( prev, pos, Color.Lerp( Color.yellow, Color.red, 0.35f ), 0.5f );
    30.  
    31.             prev = pos;
    32.         }
    33.     }
    34.     public static Vector3 PlotTrajectoryAtTime (Vector3 start, Vector3 startVelocity, Vector3 acceleration, float fTimeSinceStart)
    35.     {
    36.         return start + startVelocity*fTimeSinceStart + acceleration*fTimeSinceStart*fTimeSinceStart*0.5f;
    37.     }
    38.  
    39.  
    40.  
     
    Last edited: Mar 4, 2016
  25. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    Out of curiosity, what would be the usage of a curved raycast?
     
  26. Xelnath

    Xelnath

    Joined:
    Jan 31, 2015
    Posts:
    402
    In my case, I use it to test if a monster can make a jump before it does.
     
    ericbegue likes this.
  27. Mortalyx

    Mortalyx

    Joined:
    Mar 20, 2015
    Posts:
    7
    Hi guys!
    Just saw this topic and remember i did a catapult launcher (2 years ago) with drawable trajectory of bullet. Maybe some one need this.

    Here is the link

    And here is the code i used for trajectory:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. #if UNITY_EDITOR
    5. using UnityEditor;
    6. #endif
    7.  
    8. public class CatapultMechanism : MonoBehaviour {
    9.    
    10.     public float SpringForceFactor = 1f;
    11.     public bool UseSpringForceFactorForGrenadeImpulse = false;
    12.     public bool ResetPositionAfterImpulse = false;
    13.  
    14.     public float ImpulseFactor = 10;
    15.     [HideInInspector]
    16.     public bool showTrajectory = false;
    17.     [HideInInspector]
    18.     public TrajectorySimulation trajectorySimulation;
    19.  
    20.     Vector3 tensionVector = Vector3.zero;
    21.     float tension = 0;
    22.     Vector3 dormancyPosition;
    23.     Transform spoonTransform;
    24.     Transform scopeTransform;
    25.  
    26.     FiringItem firingItem;
    27.     // Use this for initialization
    28.     void Start () {
    29.         if (trajectorySimulation != null) {
    30.             firingItem = trajectorySimulation.firingItem;
    31.         }
    32.         drawTrajectory (false);
    33.     }
    34.    
    35.     // Update is called once per frame
    36.     void Update () {
    37.             if (showTrajectory) {
    38.                 drawTrajectory();
    39.             }
    40.     }
    41.  
    42.     void drawTrajectory(bool toDraw) {
    43.         if (trajectorySimulation == null) {
    44.             return;
    45.         }
    46.         trajectorySimulation.gameObject.SetActive (toDraw);
    47.  
    48.         if (toDraw) {
    49.             //drawing line between cup and scope
    50.             trajectorySimulation.additionalStartPoints = new Vector3[] { spoonTransform.position };
    51.  
    52.             //calculating impulse strength
    53.             tensionVector = scopeTransform.position - spoonTransform.position;
    54.             firingItem.fireStrength = (tensionVector * (UseSpringForceFactorForGrenadeImpulse ? SpringForceFactor : 1) * ImpulseFactor).magnitude * 5;
    55.  
    56.             //calculating length
    57.             trajectorySimulation.segmentCount = (int)(firingItem.fireStrength / 25);
    58.         } else {
    59.             firingItem.fireStrength = 0;
    60.             trajectorySimulation.sightLine.SetVertexCount (0);
    61.         }
    62.     }
    63.  
    64.         void drawTrajectory() {
    65.             drawTrajectory (showTrajectory);
    66.         }
    67.  
    68. }
    69.  
    70. #if UNITY_EDITOR
    71.  
    72. [CustomEditor(typeof(CatapultMechanism))]
    73. public class CatapultMechanismEditor : Editor
    74. {
    75.     public override void OnInspectorGUI()
    76.     {
    77.         base.OnInspectorGUI ();
    78.         var catapultMechanism = target as CatapultMechanism;
    79.  
    80.         catapultMechanism.showTrajectory = GUILayout.Toggle(catapultMechanism.showTrajectory, "Show Trajectory");
    81.  
    82.         if (catapultMechanism.showTrajectory) {
    83.             catapultMechanism.trajectorySimulation = EditorGUILayout.ObjectField (catapultMechanism.trajectorySimulation,  catapultMechanism.trajectorySimulation.GetType (), true) as TrajectorySimulation;
    84.         }
    85.  
    86.     }
    87.  
    88.  
    89. }
    90. #endif
    91.  
     
  28. GlennKo

    GlennKo

    Joined:
    Oct 27, 2016
    Posts:
    4
    If using simple trajectory parabola without air resistance/wind, and you need a resolution independant method to precisely (ie. perfectly) determine intersection (without relying on increased line segment divisions), here's an alternate approach:

    I assume you know the quadratic formula that projects out the segments/points along the trajectory curve. But how to detemine **exact** time of impact without relying on multiple straight line segments along path of trajectory? (since straight line segments don't really represent a true curve)

    Instead of raycasting multiple times over each straight line segment , which depends on your line segment count for accruacy, you could do a straight line raycast in 2D dimension first (top view) of the trajectory line, check for entry/exit point intersections first in 2D across bounding edges/volumes in your 3D environment (check neearest candidates first), to get entry/exit time stamps of bounding volume , then check if position at that candidate's 2D intersection time stamps from entry through exit points crosses through the volume's height bounds . If so , there is a chance the arc might hit on a surface of that bounding volume object. So, what you do immediately at that point: is project a 2D line slope across each 3D polygon of that object along the line of fire of the trajectory, and see where it interesects on that slope, and if it does, whether that intersection point (at that added time to hit slope) lies within bounds of that polygon. If so, you've got a hit candidate on that polygon. If no nearest hit is found, then proceed to next further bounding volume candidate.

    To determine exact time of impact of trajectory curve over a given sloped line plane y=mx+c segment, you can refer to this old legacy flash code reference. The intersection against the slope is determined not from straihgt line segments, but from the curve itself vs sloped straight line. http://fl.corge.net/c/316X

    The image below shows how the each y=mx+c slope segment is being traced along the line of fire.
    trajectory_raycasting.png
     
    Last edited: Apr 11, 2018
  29. BlueFire9020

    BlueFire9020

    Joined:
    Jan 24, 2018
    Posts:
    2
    I know this is kind of reviving a dead thread, but I was playing around with this and got something somewhat similar. It's by no means perfect, and could definitely use some improvement, but it does work and isn't that performance intensive. The iterations represents the scale of the curvature, as well as the scale of the ray. The Ray should have the same position as the startPos parameter and the Ray's direction is used to move the raycasts. You can tag things with a "Permeable" tag to get the raycast to pass through them (it only works once as I only included one secondary for loop, you can include more if you want to add more penetration). Like I said, it's not perfect but it could definitely be a start. Hope this helps! :D

    Code (CSharp):
    1. void curvedRaycast(int iterations, Vector3 startPos, Ray ray, int velocity)
    2.     {
    3.         RaycastHit hit;
    4.         Vector3 pos = startPos;
    5.         var slicedGravity = Physics.gravity.y / iterations / velocity;
    6.         Ray ray2 = new Ray(ray.origin, ray.direction);
    7.         print(slicedGravity);
    8.         for (int i = 0; i < iterations; i++)
    9.             {
    10.                 if (Physics.Raycast(pos, ray2.direction * velocity, out hit, velocity))
    11.                 {
    12.                     Debug.DrawRay(pos, ray2.direction * hit.distance, Color.green);
    13.                 if (hit.transform.tag == "Permeable")
    14.                 {
    15.                     Debug.DrawRay(pos, ray2.direction * velocity, Color.green);
    16.                     pos += ray2.direction * velocity;
    17.                     ray2 = new Ray(ray2.origin, ray2.direction + new Vector3(0, slicedGravity, 0));
    18.                     for (int x = 0; x < iterations; x++)
    19.                     {
    20.                         if (Physics.Raycast(pos, ray2.direction * velocity, out hit, velocity))
    21.                         {
    22.                             Debug.DrawRay(pos, ray2.direction * hit.distance, Color.yellow);
    23.                             return;
    24.                         }
    25.                         Debug.DrawRay(pos, ray2.direction * velocity, Color.magenta);
    26.                         pos += ray2.direction * velocity;
    27.                         ray2 = new Ray(ray2.origin, ray2.direction + new Vector3(0, slicedGravity, 0));
    28.                     }
    29.                 }
    30.                 else
    31.                 {
    32.                     return;
    33.                 }
    34.             }
    35.                 Debug.DrawRay(pos, ray2.direction * velocity, Color.cyan);
    36.                 pos += ray2.direction * velocity;
    37.                 ray2 = new Ray(ray2.origin, ray2.direction + new Vector3(0, slicedGravity, 0));
    38.         }
    39.         Debug.DrawRay(startPos, pos, Color.red);
    40.         /*for (int i = 0; i < iterations; i++)
    41.         {
    42.             Debug.DrawRay(pos, ray2.direction * velocity, Color.red);
    43.             pos += ray2.direction * velocity;
    44.             ray2 = new Ray(ray2.origin, ray2.direction + new Vector3(0, slicedGravity, 0));
    45.         }*/
    46.     }
    47.  
    This is the experimental version I was working on to try and reduce the number of parameters. Only issue with this one is that the rays don't connect, despite the math and logging suggesting they should. If anyone figures out why and can fix it feel free to let me know!
    Code (CSharp):
    1.  
    2. void ZCast(Vector3 startPos, Vector3 velocity)
    3.     {
    4.         Vector3 pos = startPos;
    5.         for (int i = 0; i < 99; i++)
    6.         {
    7.             velocity += Physics.gravity;
    8.             Debug.DrawRay(pos, (pos + velocity), Color.magenta);
    9.             pos += velocity;
    10.         }
    11.     }