I have a Camera Player in a scene. 3D Scene with 2d Compass GUI. Scene contains a fixed north which i want to indicate on my compass with needle but how can i do it?
I tried this code using a Tutorial so far but my needle movement direction is not appropriate according to my north.
public void ChangeNortDirection() {
northDirection.z = player.eulerAngles.y;
northLayer.localEulerAngles = northDirection;
}
You are setting the north direction to the y axis of the player, so if the player rotates so does the north direction.
What you want to do is have a variable indicating the absolute north direction and then just rotate the compass in the opposite direction the player has rotated.
Another thing is, is this in 2D or 3D space? In 2D you only want to rotate the z axis at all times and not touch the x and y axis. And in 3D the north direction should be defined in only the z axis so that only the x and y plane rotates.
For a definitive answer please provide more information.
After looking at the tutorial and seeing what you did I came up with an idea.
The only problem you have is that the pointer is not looking at north but at something else while it is still rotating with the character.
In your case you can easily add one simple value that adds up to the compass pointer's initial state.
The compass pointer will still rotate with your characters Y rotation but the compass pointer will point to a different direction than it normally would.
public float extraOffset; /* Edit this inside the editor on playmode until
your pointer points towards your north.
Then remember that value and set it while you are not in playmode.*/
public void ChangeNortDirection() {
northDirection.z = extraOffset + player.eulerAngles.y; // Just added the simple extraoffset variable and you are good to go.
northLayer.localEulerAngles = northDirection;
}
Also remember to explain your question as good as possible since it can be really hard for us to know what the exact problem is.
For example tell us if your game is going to be 2D or 3D and what the initial idea behind the subject of the problem is.
Hope this helps you out a bit.
Mennolp
I guess your question is related to the previous one : that's nice to see you're using Unity UI system now (but you could have given people over here a bit of feedback to their answers/comments) !
Regarding your current question, one of the best (and simplest) solution is to get your player's forward transform (blue axis in scene view) and to used it's X an Z values (Y doesn't matter here) to get the angle you want :
northLayer.localEulerAngles = new Vector3(0.0f, 0.0f, Mathf.Atan2(player.forward.x, player.forward.z) * Mathf.Rad2Deg);
This example is considering your northDirection vector is 0,0,1 and your northLayer is pointing north when its localEulerAngles.z is set to 0 (and of course that northLayer is a RectTransform component).
Hope this helps,
Related
I'm not really like to post questions about problems without doing the research, but I'm close to give up, so I thought I give it a shot and ask you about my problem.
I want to create a custom collision detection in Unity ( So please don't advice "use rigidbody and\or colliders" because I don't want to use them by purpose).
The main idea: I want to detect Basic Sphere and Basic Box collision. I already find AABB vs Sphere theme with the following solution:
bool intersect(sphere, box) {
var x = Math.max(box.minX, Math.min(sphere.x, box.maxX));
var y = Math.max(box.minY, Math.min(sphere.y, box.maxY));
var z = Math.max(box.minZ, Math.min(sphere.z, box.maxZ));
var distance = Math.sqrt((x - sphere.x) * (x - sphere.x) +
(y - sphere.y) * (y - sphere.y) +
(z - sphere.z) * (z - sphere.z));
return distance < sphere.radius;
}
And this code does the job, the box bounding and the sphere center point with radius works fine, I can detect the Sphere collision on Box.
The problem is, I want to Rotating the Cube in Runtime, so that will screw up everything, the bounding will split away and the collision will gone (or collide on random places). I've read about some comments where they said, bounding not works with rotation, but I'm not sure what else can I use to solve this problem.
Can you help me with this topic please? I'll take every advice I can get (except Colliders & Rigidbodies of course).
Thank you very much.
You might try using the separating axis theorem. Essentially, for a polyhedron, you use the normal of each face to create an axis. Project the two shapes you are comparing onto each axis and look for an intersection. If there is no intersection along any of the axes, there is no intersection of shapes. For a sphere, you will just need to project onto the polyhedron's axes. There is a great 2D intro to this from metanet.
Edit: hey, check it out-- a Unity implementation.
A good method to find if an AABB (axis aligned bounding box) and sphere are intersecting is to find the closest point on the box to the sphere's center and determine if that point is within the sphere's radius. If so, then they are intersecting, if not then not.
I believe you can do the same thing with this more complicated scenario. You can represent a rotated AABB with a geometrical shape called a parallelepiped. You would then find the closest point on the parallelepiped to the center of the sphere and again check if that point exists within the sphere's radius. If so, then they intersect. If not, then not.
The difficult part is finding the closest point on the parallelepiped. You can represent a parallelepiped in code with 4 3d vectors: center, extentRight, extentUp, and extentForward. This is similar to how you can represent an AABB with a 3d vector for center along with 3 floats: extentRight, extentUp, and extentForward. The difference is that for the parallelepiped those 3 extents are not 1 dimensional scalars, but are full vectors.
When finding the closest point on an AABB surface to a given point, you are basically taking that given point and clamping it to the AABB's volume. You would, for example, call Math.Clamp(point.x, AABB.Min.x, AABB.Max.x) and so on for Y and Z.
The resulting X,Y,Z would be the closest point on the AABB surface to the given point.
To do this for a parallelepiped you need to solve the "linear combination" (math keyword) of extentRight(ER), extentUp(EU), and extentForward(EF) to get the given point. In other words, what scalars do you have to multiply ER, EU, and EF by to get to the given point? When you find those scalars you need to clamp them between 0 and 1 and then multiply them again by ER, EU, and EF respectively to get that closest point on the surface of the parallelepiped. Be sure to offset the given point by the Parallelepiped's min position so that the whole calculation is done in its local space.
I didn't want to spend any extra time learning how to solve for a linear combination (it seems it involves things like using an "augmented matrix" and "gaussian elimination") otherwise I'd include that here too. This should get you or anyone else reading this off to the right track hopefully.
Edit:
Actually I think its a lot simpler and you don't need a parallelepiped. If you have access to the rotation (Vector3 or Quaternion) that rotated the cube you could get the inverse of that and use that inverse rotation to orbit the sphere around the cube so that the new scenario is just the normal axis aligned cube and the orbited sphere. Then you can do a normal AABB - sphere collision detection.
So, I'm working on Unity project. I have a mortar, which is leaned towards player gameobject. I want to rotate it so it follows player movement.
I came up with this simple code in my Update method:
Vector3 directionToFace = _player.position - transform.position;
directionToFace.y = 0;
Debug.DrawRay(transform.position, directionToFace, Color.green); // for visualization
transform.rotation = Quaternion.LookRotation(directionToFace);
But setting y to 0 caps rotation of x axis to 0 but I want my mortar to be leaned forward a bit. I've tried setting y to many different values but then distance between two objects determines how much the mortar leans. Yes, I know that I can make it child of an empty gameobject and apply script to the parent but if there is any other way to fix this problem inside my code... Your help will be appreciated.
The only idea I have is to calculate distance between two gameobjects and change value of directionToFace.y accordingly. But I will have to get local rotation that's assigned to mortar in the inspector and then calculate the value using Pythagorean Theorem... but I don't want to torture myself that much :D
Hope I understand your problem! I found it was possible to lean your gameObject forward by adding in this line after your code
transform.rotation = Quaternion.Euler(xOffset,transform.rotation.eulerAngles.y, transform.rotation.eulerAngles.z);
where xOffset is the amount you want your game object leaning, it would also be possible to add an explicit value for z in a similar way.
Let me know if this isn't what you meant.
I'm creating an asteroid mining game in Unity 3D, where "down" is the center of the planet you are on (So I am mostly using local rotations when dealing with vectors). I have a working physics-based character controller, but it has problems dealing with slopes. This is because when I add a force to the character, currently it pushes along the player's forward vector (see picture). What I want to do is calculate the vector that is parallel to this terrain surface, but in the direction that the player is facing (so that the player can move up the slope).
I originally thought that i could just find the vector perpendicular to the normal, but then how do I know which direction it will be in. Also complicating matters is the fact that the player could be oriented in any way in relation to the global x, y, and z.
Either way, I have the surface normals of the terrain, I have all of the player's directional vectors, but I just can't figure out how to put them all together. I can upload code or screenshots of the editor if necessary. Thanks.
The usual way is to factor out the component of the forward vector that is parallel to the surface normal:
fp = f - dot(f, n) * n
See vector rejection.
This formulation will also make fp shorter the steeper the slope is. If you don't want that, you can re-scale fp afterwards to have the same length as f.
What happens when I set the transform.up value in unity. Specifically could you explain this video in the link below
https://youtu.be/_XdqA3xbP2A
I know it changes what the object is looking at. But, does it look at a position, or how does it
work? What happens when I change the direct transform.up? I can’t seem to find a good explanation. Why does the vector in the video make a direction that is facing the mouse, why not use the mousePosition itself instead of subtracting?
Aside from that could you also explain what is going on in the video?
Thanks in advance!
Basically, when you move an object, you take its position and rotation as reference, so if you increment +1 on the Y position of an object and this object is rotated, you'll increment on that direction.
but with Vector3.up, you use the world space as reference, so
i want to give you a full answers here, but i would have to enter with some math, simplifying, the transform.up is the direction which the sprite is pointing, he gets the direction saying this:
"mousePosition.y" (GREEN) is the position Y of the mouse, and "mousePosition.x" (RED) is the X position of the mouse, with this two values, you have a coordinate, or a direction (Blue traced line), which unity transforms to quaternions and apply the value to your rotation (this in 2d). you want to use the Vector3 which uses a world space reference, because if you use a local reference, would happen something like this
and you would get the wrong direction.
Transform object automatically calculates a quaternion rotation using this up Vector like from default Vector3.up to new transform up vector.
I am testing out some ideas in Unity where a player can walk around a circle while staying on it (so the circle has its own gravity) and also being oriented properly. This game is currently being done in 2D, so all objects are sprites.
I do hope I can explain myself properly. Please ask if you need any further clarification...
It appeared that I succeeded with my idea until I noticed something odd.
So as expected, the player moves around the circle without falling off (custom gravity worked just fine) and its Z rotation is affected as it aligns itself with a direction:
// Align code:
// We reverse the direction so the object is standing up the right way.
private void Update()
{
transform.up = -(planet.position - transform.position);
}
It works... mostly. However, when the player object's rotation Z naturally reaches 180, it appears to flip horizontally (like a mirror effect) and then it returns to normal as rotation Z leaves 180. The visual flip happens because for some reason the object's Y becomes 180 at the same time too. At no other point does X or Y change in regards to rotation. Only Z. So the moment Z hits 180, Y is affected and the moment we leave Z 180, Y returns to 0.
I'm happy to provide a quick video of it happening in-game if anybody needs some visual understanding of what's going on.
The visibility of this bug tends to rely on how fast you're moving around the circle. If you're moving fast enough, you can probably skip over 180 and not see it happen at all, however if you move slow enough there's no denying it's there. It's also problematic for the fact that I simply make the camera a child of the player so when the player flips, so does the camera causing the entire scene to flip which can look extremely glitchy for a player to see.
I really have no idea how to tackle this issue as I have no clue why it would do such a thing. At every other rotation value it behaves just fine. It's only at Z = 180 (so the object is exactly upside down) does it decide to rotate in the wrong ways.
EDIT: Changed tag to Unity3D
It's probably because of converting quaternions (which is what's actually used internally for rotations) to euler angles for display. Can you try to use Quaternion.Slerp to rotate?