Determine the direction an object is actually moving - unity3d

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.

Related

Rotation flipping when moving around the sides of objects

I want to make a game in Unity where a person can pick a surface and walk along all of its sides. I've gotten the movement working, but when I rotate my character around certain angles of corner the character flips 180 degrees in some direction (it's different depending on the corner) and when I want them to move forward the game freaks out as they keep going across the corner over and over again, turning, and going forward across the border again. I'd strongly prefer to keep my character from doing these 180-degree spins and I think it's just due to a flaw in the formula I use to calculate the angle they stand at (which is based around making sure their transform.up is aligned with the point they are meant to stand on). Any ideas on how I fix this rotation formula in Update?
Current formula:
angle = Vector3.Angle(closestPoint, transform.position);
var t = transform;
var angles = t.eulerAngles;
t.LookAt(GravityWellPoint.transform.position);
t.RotateAround(transform.position, -transform.right, 90);
transform.rotation = Quaternion.Lerp(transform.rotation, t.rotation, Time.deltaTime * 5.0f);
Got this solution from a different forum and it worked:
So this is actually not a trivial problem to solve. If you try doing it by calculating angles etc you almost always end up with a similar spinning/flipping issue in certain positions. You can solve it by doing the maths, but its a pain. I usually like to use Quaternion.LookRotation to solve this kind of problem. you can feed in the desired forward and upward directions. So you can calculate the desired upward direction like so:
Vector3 targetUpDirection = transform.position - GravityWellPoint.transform.position;
Then you would do the following:
transform.rotation = Quaternion.LookRotation(transform.forward,targetUpDirection);
but this doesnt quite work. LookRotation will ensure that your forward direction is exactly the one you specify, and then chooses the upward direction that's the closest possible to the one you specify. So you will find that we don't actually manage to point our object upwards in the way we intended. However, there is an unintuitive solution we can apply instead.
Calculate the upward direction in the same way, then use LookRotation to rotate our object to point its forward face in exactly our desired upwards direction, and its upward face towards the current forward direction:
Vector3 targetUpDirection = transform.position - GravityWellPoint.transform.position;
transform.rotation = Quaternion.LookRotation(targetUpDirection, transform.forward);
Now our object is aligned perfectly, but is the wrong way up. We can use LookRotation again, to swap the upwards and forwards directions:
transform.rotation = Quaternion.LookRotation(transform.up, transform.forward);
For clarity/TLDR here is the complete code for my solution:
//find the desired up direction:
Vector3 targetUpDirection = transform.position - other.position;
//face forward/upward via black magic
transform.rotation = Quaternion.LookRotation(targetUpDirection, transform.forward);
transform.rotation = Quaternion.LookRotation(transform.up, transform.forward);

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

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.

Which rotation is shown in the Inspector?

The chest bone of my player can be rotated while aiming.
Now I wanted to evaluate how much (minimum and maximum rotation) I should let the chest be rotatable.
To do that, I allowed all degrees of rotation and took a look at the Inspector.
For example, the minimum value that the chest should be rotatable to the left should be Y=-15.
At Y=-15 (seen in the Inspector), it still looked natural.
Now I wanted to code this.
To my surprise, chest.localRotation.Y was a completely different value than what the Inspector is showing.
I have then taken a look at the chest variable and extended the view.
I just can't see the rotation value that the Inspector is showing.
How should I go on in this case, please?
I'm using this to rotate the bone:
Chest.LookAt(ChestLookTarget.position);
Chest.rotation = Chest.rotation * Quaternion.Euler(Offset);
Thank you!
The reason why it doesn't work:
Quaternion is not a human readable value.
One Quaternion is allways unique but can have multiple (infinite?) different representations in Euler space! The other way round one Euler represents allways exactly one Quaternion value.
If you look at the docs it explicitly says
Don't modify this directly unless you know quaternions inside out.
Than as said what you see in the inspector is the localRotation in relation to the parent Transform.
Better said it is one of the many possible Euler inputs that result in the Quaternion. What you see in the debug at localEulerAngles is another possible Euler representation. Unity usually in localEulerAngles also gives you only values > 0.
It seems that the chest anyway will only rotate around the Y axis, right?
If this is the case you can simply get the Angle between the chest's original forward vector and the target. It is way easier to handle Vector3 values than Quaternions ;)
It seems to be the same use case as in this post
// get the target direction
Vector3 targetDir = ChestLookTarget.position - Chest.position;
// Reset any difference in the Y axis
// since it would change the angle as well if there was a difference I the height
// between the two objects
targetDir.y = 0;
// however you currently rotate
// instead rotate only the Vector3 variable without applying it to the transform yet
Vector3 newDir = Vector3.RotateTowards(Chest.forward, targetDir, RotationSpeed * Time.deltaTime, 0.0f);
// Compare the target direction to the parents forward vector
float newAngle = Vector3.Angle(Chest.parent.transform.forward, newDir);
if (newAngle > MaxRotationAngle)
{
// What should happen if angle gets bigger?
return;
}
// If angle still okey set the new direction
Chest.rotation = Quaternion.LookRotation(newDir);

Move Cannon.JS Body Toward Dynamic Position?

I'm having a hard time wrapping my head around how to do this.
What I'm trying to do, is move a physics body, by the means of velocity, toward another body, until it reaches and hits said body. (Think AI following a player)
One solution is the following:
body.velocity.x = target.position.x-body.position.x;
body.velocity.z = target.position.z-body.position.z;
This has issues, though. One being that the velocity is higher depending on the distance between the two bodies. I would prefer a fixed speed. Another way would be to use the following example: Position a body in cannon.js relative to local rotation
But in this case, I need a way of rotating the quaternion, so it faces the target position, this with only knowing the 2 positions of the bodies.
So the question is, how do I calculate the velocity OR direction of the body, so that it can follow and collide with the target body, by using a fixed speed/velocity?
To get a fixed speed, .normalize() your velocity vector and then scale (.mult()) the result by the speed you want. The result will be a vector that always has the length you want.
To get a quaternion that makes your body face in a certain direction, you can use Quaternion.setFromVectors(u,v). This method creates a quaternion which will rotate u so it points in the same direction as v. If you set u to your forward vector and v to the direction you want the body to look, you will get the correct "look at" behavior. Note that the "forward" vector might be different for your game.
// Compute direction to target
var direction = new CANNON.Vec3();
target.position.vsub(body.position, direction);
direction.y = 0;
direction.normalize();
// Get the rotation between the forward vector and the direction vector
var forward = new CANNON.Vec3(0,0,1);
body.quaternion.setFromVectors(forward, direction);
// Multiply direction by 10 and store in body.velocity
var fixedSpeed = 10;
direction.mult(fixedSpeed,body.velocity);

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.