How to search for objects in a specific direction in Unity? - unity3d

I am new to Unity and created an object, let's say a car. Now I want to know the distance to the next object in a specific direction, for example in front of it or at 45 degrees.
What I want to archieve is comparable to the car sending light rays in the direction measuring the distance to the next collider.
What I can think of is checking for all objects in the scene, but hopefully there is a better solution.

Your looking for Physics.Raycast.
This creates a line from point a (origin) to point b (origin + direction * maxDistance). The documentation has a nice example.
maxDistance would only return object in that range.
You can do multiple ray casts adding rotation to the direction your rays to get a wider scan. Physics.OverlapSphere is also an option, it checks a full sphere around a location for anything that overlapse. You would need to then check if the angle between the car and the object is in your range by calculating the angle between the 2 positions.

Related

Precision in onCollisionStart in flame with flutter

I'm attempting to write a bouncing ball game using flame in flutter. To detect collisions the onCollision and onCollisionStart methods are provided. What I had hoped is that onCollisionStart would give a precise location when two objects first hit each other. However, instead it gives a list of positions indicating where the two objects overlap after the first game-tick when this happens (i.e. onCollisionStart is called at the same time as onCollision, but is not called a second time if the same two objects are still colliding on the next tick).
This is illustrated in the attached picture. The collision points are marked with red dots. If the ball were moving downwards, then the ball would have hit the top of the rectangle and so should bounce upwards. However, if the ball were moving horizontally, then its first point of contact would have been the top left corner of the box, and the ball would bounce upwards and to the left.
If I want to work out correct angle that the ball should fly off, then I would need to do some clever calculations to work out the point that the ball first started hitting the other object (those calculations would depend on the precise shape of the other object). Is there some way to work out the point at which the two objects first started colliding? Thanks
What you usually need for this is the normal of the collision, but unfortunately we don't have that for the collision detection system yet.
We do have it in the raytracing system though, so what you could do is send out a ray and see how it will bounce and then just bounce the ball in the same way.
If you don't want to use raytracing I suggest that you calculate the direction of the ball, which you might already have, but if you don't you can just store the last position and subtract it from the current position.
After that you need to find the normals of the edges where the intersection points are.
Let's say the ball direction vector is v, and the two normal vectors are n1 and n2.
Calculate the dot product (this is build in to the vector_math library) of the ball direction vector and each of the normal vectors:
dot1 = v.dot(n1)
dot2 = v.dot(n2)
Compare the results of the dot products:
If dot1 > 0, n1 is facing the ball.
If dot2 > 0, n2 is facing the ball.
After that you can use v.reflect(nx) to get the direction where your ball should be going (where nx is the normal facing the ball).
Hopefully we'll have this built-in to Flame soon!

What's the difference between ScreenToWorldPoint and ScreenPointToWorldPointInRectangle?

What's the difference between ScreenToWorldPoint and ScreenPointToWorldPointInRectangle? And when should we use which one?
Senario:
I'm using UI system creating my card game similar to Hearthstone. I want to transform my mouse drag positions to world position. RectTransformUtility.ScreenPointToWorldPointInRectangle(UIObjectBeingDragged.transform.parent as RectTransform, Input.mousePosition, Camera.main, out resultV3) works fine. But I also tried Camera.main.ScreenToWorldPoint(Input.mousePosition), and it give a different and "wrong" result.
ScreenToWorldPoint
Gives you a world position (the return value) that is along a ray shot through the near plane of the camera (the Camera whose method is being called) at some given point (the x and y components of the position parameter) and a given distance from that near plane (the z component of the position parameter).
You should use this when you:
have a specific distance from the near plane of the camera you are interested in and
don't need to know if it hit inside some rectangle or not
You could think of this as a shortcut for Ray.GetPoint that uses the x and y of position and various info of the Camera to make the Ray, and the z component of position is the distance parameter.
ScreenPointToWorldPointInRectangle
Also gives you a world position (worldPoint) along a ray shot through the near plane of a camera (cam) at a given point (screenPoint). Only this time instead of giving you the point a given distance along the ray, it gives you the intersection point between that ray and a given rectangle (rect) if it exists, and tells you if such an intersection exists or not (the return value).
You should use this when you:
have a specific rectangle you are interested in the intersection with a camera ray,
You don't know the distance between the camera or its near plane and the intersection point
Want to know if that rectangle is hit by the ray or not.
You could think of this as a shortcut for Plane.Raycast which uses cam and screenPoint to make the Ray, and rect to make the Plane, and also gives some more information of if it would intersect outside the boundaries of the rect.

Determine the direction an object is actually moving

In unity I am trying to compare the players actual direction with the direction they are facing and wish to move in but having major issues trying to find the actual movement direction.
I can determine the facing direction very easily with:
wishDir = transform.localEulerAngles;
But I cannot figure out how to get the objects movement direction so that I can compare. I have tried:
transform.InverseTransformDirection(rb.velocity);
I would expect this to be equal to 0,90,0 when I move to the right however it is equal to 0,0,0 (although jumps when there is acceleration).
How can I determine the direction an object is moving in?
I can determine the facing direction very easily with:
wishDir = transform.localEulerAngles;
This is already quite odd to me. localEulerAngles is a rotation in Euler space notation in degrees per axis x,y,z .. this is no "direction".
Usually if you want the direction you are looking in you would rather use transform.forward
wishDir = transform.forward;
And then
transform.InverseTransformDirection(rb.velocity);
should indeed return the direction in local space.
Note that the Debug.Log beautifies (rounds) this value to make it more human readable. If you want the exact values you could try and log e.g.
var relative = transform.InverseTransformDirection(rb.velocity);
Debug.Log(relative.ToString(F4));
which should print the values always with 4 digits after the decimal point.

Unity3D angle between vectors/directions on specific axis

I have two directions and i am trying to calculate the angle on a specific axis. The object from which the directions are derived is not a static object so i'm struggling to get my head round the maths to work out what i need to do.
FYI, I have the start and end points that i have used to calculate the directions if they are needed.
Here's a diagram to show what i am looking for:
The above image is from a top-down view in unity and it shows the angle i want.
The problem can be seen from the above image, which is that the directions are not on the same height so i can't use the vector3.angle function as it won't give me the correct angle value.
In essence i want to know how much would i have to rotate the red line to the left (top view) so that it would line up with the blue (top-view).
The reason i need this is as i am trying to find a way of getting the side-to-side angles of fingers from my leap motion sensor.
This a generic version of my other question:
Leap Motion - Angle of proximal bone to metacarpal (side to side movement)
It will provide more specific information as to the problem if you need it and it has more specific screenshots.
**UPDATE:
After re-reading my question i can see it wasn't particularly clear so here i will hopefully make it clearer. I am trying to calculate the angle of a finger from the leap motion tracking data. Specifically the angle of the finger relative to the metacarpal bone (bone is back of hand). An easy way to demonstrate what i mean would be for you to move your index finger side-to-side (i.e. towards your thumb and then far away from your thumb).
I have put two diagrams below to hopefully illustrate this.
The blue line follows the metacarpal bone which your finger would line up with in a resting position. What i want to calculate is the angle between the blue and red lines (marked with a green line). I am unable to use Vector3.Angle as this value also takes into account the bending of the finger. I need someway of 'flattening' the finger direction out, thus essentially ignoring the bending and just looking at the side to side angle. The second diagram will hopefully show what i mean.
In this diagram:
The blue line represents the actual direction of the finger (taken from the proximal bone - knuckle to first joint)
The green line represents the metacarpal bone direction (the direction to compare to)
The red line represents what i would like to 'convert' the blue line to, whilst keeping it's side to side angle (as seen in the first hand diagram).
It is also worth mentioning that i can't just always look at the x and z axis as this hand will be moving at rotating.
I hope this helps clear things up and truly appreciate the help received thus far.
If I understand your problem correctly, you need to project your two vectors onto a plane. The vectors might not be in that plane currently (your "bent finger" problem) and thus you need to "project" them onto the plane (think of a tree casting a shadow onto the ground; the tree is the vector and the shadow is the projection onto the "plane" of the ground).
Luckily Unity3D provides a method for projection (though the math is not that hard). Vector3.ProjectOnPlane https://docs.unity3d.com/ScriptReference/Vector3.ProjectOnPlane.html
Vector3 a = ...;
Vector3 b = ...;
Vector3 planeNormal = ...;
Vector3 projectionA = Vector3.ProjectOnPlane(a, planeNormal);
Vector3 projectionB = Vector3.ProjectOnPlane(b, planeNormal);
float angle = Vector3.Angle(projectionA, projectionB);
What is unclear in your problem description is what plane you need to project onto? The horizontal plane? If so planeNormal is simply the vertical. But if it is in reference to some other transform, you will need to define that first.

Getting the axis pointing up in a rotation (Unity)

I have an object in unity which has a rotation described as the following:
x, y, z, where they are both rotations ranging from 0 to 360 around their respective axis.
Now I'm trying to find out which of the vectors point up the most. Essentially I have a 6-sided dice, on which I use physics to emulate a dice-throw. I now want to find out which of the 6 faces of the die points upwards. I can imagine some rather advanced if sentences, revolving around checking the rotations individually, but I'd like to know if there is a good way to do this?
You can get the face directions with:
transform.up
-transform.up
transform.right
-transform.right
transform.forward
-transform.forward
You need to associate each direction with the appropriate face value. The side facing up will be the one with the greatest Dot Product vs Vector3.up (the world "up" direction). A dot product of 1 means a face is pointing directly up. Note that this only works because all the directions are unit vectors.
Vector3.Dot(Vector3.up, transform.up);
Given that it's only 6 (or 3 if you are clever) if statements to find the max that's probably the best way. If you are considering the general case, i.e. to support any die shape and number of faces, you could store a list of structs with a lambda expression denoting the face direction + the face value then use Linq Max().
You could, as you say, check the rotations directly manually.
Here's an alternative collider-based approach: put invisible children game objects with individual trigger colliders on each face of the die, then whenever one of them collides with the table surface, record the number of the opposite side of the face.