- Home /
Continuous detection of object using ray cast
i have a moving gameobject in unity 3d. Gameobject is rigid body with colider. if i swipe that object slowly, i can detect object by using raycast using code
if(Physics.Raycast(ray,out GetHit,1000f, layerMask)){
hitObject = GetHit.collider.gameObject;
print(hitObject);
}
In image red colours indicate swipe. For swipe indaication i used line renderer. The point i gets i saved into a array and made line renderer.
If i swipe fast i cant able to detect the object. I cant able to get contious touch points. Why it happen so???
Probably because within one frame, your touch is no longer on the object. I suggest "saving" the object when you press down on it ins$$anonymous$$d :)
I imagine if you have some sort of mouse swipe implemented, and you swipe your mouse faster than the update function can keep up with, your mouse gets "teleported" to the new location to compensate, ins$$anonymous$$d of actually traveling there. So you could jump over the object entirely and never touch it.
You both are right. So how can i escape from this issue. Any another ideas???
The depends on what you cant to achieve. You could calculate the path in between this and last frame, then for every, lets say, half a unit, do a raycast. That would ensure consistent raycasting over distance, rather then time :)
@markpdolby I would suggest against that. It might even decrease the accuracy depending on the current framerate the OP is getting.
Answer by SinisterRainbow · Jun 28, 2013 at 10:17 AM
Couple of things: (edited to reflect Benproductions input). If you use an OnGui function, not Update(), it will send a mousedrag event, but this doesn't update every pixel, whether it runs faster than update() I'm now unsure. it's limited by the interrupt speed by a computer I believe. So one solution is to draw a line between each mouse drag event, then test maybe 5 ray casts at equal intervals along the line and see if you get a hit (the first point will be the touch point, and don't do any ray casts if the touch points are not on either side of the object (you can test by remember the last drag point raycast, and casting a ray at the point of the mousedrag event.
I'm assuming you are drawing a 2d line over a 3d object. If it's a 2d object with 2d line performance is even better, fit a rectangle around the object and use Rect.Contains() (it uses AABB).
This may not be applicable, but more efficient: if you instead get the first contact point, and last contact point, it's easy to tell if your line passed through the object, and you only have to detect on touch and on release rather than look several times a frame. If you combine this with translating the 3d object's bounding box into 2d screen space, then you don't need to go about casting tons of rays at different points in the line, you can just check the few verts of the screen space box and stop as soon as you see one vert above the line and one below it. You can still draw your line normally, but don't test collision until you're done touching...Not sure if that will work with your game dynamics.
OnGUI
is called per input action, but, that does not fix any problem. If you move your finger, it will only be called once, not depending on the distance traveled.
The 2d thing works great... if it's only in 2d...
If you're doing everything in 3d space, raycasting is unavoidable :)
Answer by fafase · Jun 28, 2013 at 11:35 AM
Move you object with basic input, you may have to create you own drag method and then store the object position and draw a linecast between current and previous. If the line is cut it will return false.
This is a basic drag mouse method:
public static bool DragMouse(int button){
if(Input.GetMouseButton (button)){
bool x = Mathf.Approximately(previousPosition.x, Input.mousePosition.x);
bool y = Mathf.Approximately(previousPosition.y,Input.mousePosition.y);
if(!x || !y){
previousPosition = Input.mousePosition;
return true;
}
}
previousPosition = Input.mousePosition;
return false;
}
And then you can do:
Vector3 previous;
if(DragMouse(0)){
if(Physics.Linecast(obj.position,previous)){
// Collision
}
previous = obj.position;
}