Get position from player forward at constant distance - c#

The simple way to get player front position at specific distance
Vectro3 forward = player.transform.forward * distance;
Vector3 newPlayerFronPosition= player.transform.position + new Vector3(forward.x, forward.y, forward.z);
newPlayerFronPosition= new Vector3(newPlayerFronPosition.x, newPlayerFronPosition.y - 4f, newPlayerFronPosition.z);
navigationCanvas.transform.position = newPlayerFronPosition;
navigationCanvas.transform.rotation = camRotationToWatch.transform.rotation;
its actually working fine but the problem is as my player move up or down the navCanvas become appear ver near to my player. How to mainitain spcific distance all the time.?? that no matter player look above or down the navcanvas display at specfic distance.(position)
disatnceUICam = Vector3.Distance(newPlayerFronPosition, player.transform.position);
I also logged the distance and surprisingly it the distance is changing when i am moving up or down. its changing from 6 to 12 as i am looking up to down.

If I've understood you correctly, and you want a point on in front of your player transform on the X Z Plane a set distance from the forward of your player, you should try something like this:
Vector3 horizontalForward = new Vector3(
player.transform.position.x + player.transform.forward.x,
player.transform.position.y,
player.transform.position.z + player.transform.forward.z
).normalized * distance;
I suspect what you're describing is occurring because the transform of your 'player' variable is connected to the direction of your game camera. As the camera looks up, the world position of your forward changes relative to the camera. Using just the X and Z will produce a varying distance as your camera transform rotates around the X Axis. Perhaps this diagram will illustrate what I mean a little better:
Sorry the hypotenuse is a little wonky but you get the idea right?

Related

#Unity Cube Movement (Jumping +1 Forward/Right/Backward/Left)

Hey stackoverflow Community,
First of all:
I'm still very new about programming with C# and Unity.
My question:
I'm working on an idea for a Movement of a Cube.
It is planned that the cube will move forward by pressing a key (W-Key). But it shouldn't just move forward. It should jump forward to the next point. So always plus 1 of its axis into which it should go. Accordingly, it is only intended to go forward, right, down, left. He won't be able to jump over behind. You should also see that the cube jumps in the respective direction, so it should not teleport itself. :D
Does anyone have an idea how I can realize this movement?
I am very much looking forward to your ideas.
(Sorry if my English is not so good, my English not the best. ^^)
best regards
xKarToSx
So, in order to understand movement, it's best to first understand Vectors in Unity. Since you want to be moving the cube in the forward direction, I'm going to assume this is a 3D game, in which case you want to use a Vector3.
A Vector3 has three components: X, Y, and Z. Each component is tied to an axis. In simple terms, X is tied to left and right, Y is tied to up and down, and Z is tied to forward and back. So, Vector3 position = new Vector3(0, 1, 2); will be a vector that is 1 unit above and 2 units in front of the starting position.
Assuming you've attached this script to the cube you want to move, you can track its position with transform.position. So, if you want to move the cube one unit forward, your code would look something like this:
if(Input.GetKeyDown(KeyCode.W)) // This code will activate once the user presses W.
{
transform.position += new Vector3(0, 0, 1);
}
That will move the cube one unit forward in the Z direction. However, you don't want it to teleport, you want to see it move, correct? In that case, you want to check out Unity's Vector3.Lerp function. Basically, you would use it to smoothly transition an object between two defined positions. You'll need to implement a timer and a for loop in order to make this work correctly.
So, to summarize, for moving one unit forward in the Z direction, your code would look something like this:
if(Input.GetKeyDown(KeyCode.Z))
{
float startTime = Time.time; //Time.time is the current in-game time when this line is called. You'll want to save this to a variable
float speed = 1.0f; //The speed if something you'll want to define. The higher the speed, the faster the cube will move.
Vector3 startPosition = transform.position; //Save the starting position to a different variable so you can reference it later
Vector3 endPosition = startPosition + Vector3.forward; //Vector3.Forward is equivalent to saying (0, 0, 1);
float length = Vector3.Distance(startPosition, endPosition); //You'll need to know the total distance that the cube will move.
while(transform.position != endPosition) //This loop while keep running until the cube reaches its endpoint
{
float distCovered = (Time.time - startTime) * speed; //subtracting the current time from your start time and multiplying by speed will tell us how far the cube's moved
float fraction = distCovered / length; //This will tell us how far along the cube is in relation to the start and end points.
transform.position = Vector3.Lerp(startPosition, endPosition, fraction); //This line will smoothly transition between the start and end points
}
}
I hope this helps you. This is my first time answering a question so sorry if I got some things wrong/it's not the most optimized. Good Luck!

Unity RotateAround() in combination with a specific direction

I'm trying to rotate my camera around a character, with a certain direction it needs to face. For example, I want my camera to rotate around my character, and stop the rotation when it faces another objects forward axis.
So I figured I needed a combination between RotateAround() and LookRotation().
RotateAround() to rotate the camera around the character, and LookRotation() to make the camera face that object aswell.
The problem is: I don't want my camera to move or rotate away from my character.
I tried a couple of things, the most thought out being this:
private void RotateCamera()
{
Quaternion currentCameraRotation = _camera.transform.rotation;
Quaternion futureCameraRotation = Quaternion.LookRotation(_hitObstacleStartingPoint.transform.forward);
float rotationAngle;
Vector3 rotationAxis;
Quaternion.FromToRotation(currentCameraRotation.eulerAngles, futureCameraRotation.eulerAngles).ToAngleAxis(out rotationAngle, out rotationAxis);
_camera.transform.RotateAround(_character.transform.position, _camera.transform.up, rotationAngle);
}
But that ended up in my camera rotating all over the place..
Thanks in advance!
EDIT: I'm sorry for my terrible explanation.
Here's a little drawing.
If you calculate the distance between the current rotation angle, and the target rotation angle, and you can rotate around the pivot over time.
See below:
private void RotateCamera()
{
Quaternion currentCameraRotation = _camera.transform.rotation;
Quaternion futureCameraRotation = Quaternion.LookRotation(obstacleObject.transform.forward, obstacleObject.transform.up);
float angleDelta = Quaternion.Angle(currentCameraRotation, futureCameraRotation);
_camera.transform.RotateAround(this._character.transform.position, _camera.transform.up, angleDelta * rotationSpeed * Time.deltaTime);
}
To help visualize what's going on:
void OnDrawGizmos()
{
Gizmos.color = Color.green;
Gizmos.DrawLine(_camera.transform.position, _camera.transform.forward * 20 + _camera.transform.position);
Gizmos.color = Color.red;
Gizmos.DrawLine(obstacleObject.transform.position, obstacleObject.transform.forward * 20 + obstacleObject.transform.position);
}
This doesn't work if your obstacle is rotated around x,z; it's always assuming a identity forward vector.
I ended up using fixed camera points in my scene. It avoids the problem, so I don't consider this one solved, but I have a deadline on this project and I can't afford to spend too much time on this problem anymore. Thanks to those of you who have helped me.

Finding the last Vector of a right angled triangle - Unity

For Context: I'm 90% of the way through making a wall running system in Unity, and I need help finding 2 Vector3's that I can use for a check and for adding velocity to the player to get them to move in the correct direction.
More specifically, I'm getting two Vector3's to the right and left of a contact point with a wall, then getting the distance between the right point and the players previous position, and the distance between the left point and the players previous position. Whichever point is further away from the player, is the direction we are travelling, and if you take that point and - the contact point from it and normalize that, the function returns the Vector3 to use to add velocity to the player.
Currently I'm using this function to do this for me (where hit is the contact point between the player and the wall):
Vector3 CalculateWallRunDirection(Vector3 hit, Transform wall)
{
Vector3 rightPos = hit + wall.forward;
Vector3 leftPos = hit + (wall.forward * -1);
float rightDis = Vector3.Distance(rightPos, prevPlayerPos);
float leftDis = Vector3.Distance(leftPos, prevPlayerPos);
if (rightDis < leftDis)
{
return Vector3.Normalize(leftPos - hit);
}
else
{
return Vector3.Normalize(rightPos - hit);
}
}
This works well when it works... but the problem is, because I'm using the Transform.forward of the wall to determine where these points are, if you try to wall run on the front or back face of an object, it will throw to into the wall instead of along it and the player will become stuck.
TL;DR: I need another way to determine two Vector3's instead of using transform.forward + original Vector3. From a top-down view, the problem could be displayed as this. A is the player, B is the contact point with the wall. Find C and D:
Please explain your answer, I'm not too great at math.
You were essentially trying to recreate Vector3.ProjectOnPlane(). You probably want to use that instead.
eg
Vector3 A = Vector3.ProjectOnPlane(B, C);
// A is the new velocity vector parallel to the wall
// B is the old velocity of the player at the point of impact
// C is the normal of the plane of impact
You can easily find C in the OnCollisionEnter event, simply get the contact point's normal.
Note B doesn't need to be normalized, but if it is, A will be a normalized Vector3 as well.

Unity3D: NewtonVR. Translating a point and rotation inline with changes from another point/rotation

I make NewtonVR, a free, opensource, physics based, vr interaction framework plugin for unity3d. The meat of NewtonVR is being able to hover your vr controller over a virtual object, hold a button, and "pick up" that item. Once the item is "held" any changes to the controller's position and rotation are duplicated on the item. The way we currently do this is by creating a transform (PickupTransform) at the point the item is at, then setting the parent of that transform to the controller (NVRHand).
See here: https://github.com/TomorrowTodayLabs/NewtonVR/blob/master/Assets/NewtonVR/NVRInteractableItem.cs#L180
Then, each FIxedUpdate we set the velocity and angular velocity equal to (distance / time) to get the item's position to match the controller's position plus the initial offset of position and rotation. To see this in action, check out this old blog post: http://www.vrinflux.com/newton-vr-physics-based-interaction-on-the-vive/
However, we've had a variety of issues with simply distance/time which I suspect is do to the position of the transform not being updated quite inline with the position of the rigidbody.
See here: https://github.com/TomorrowTodayLabs/NewtonVR/blob/master/Assets/NewtonVR/NVRInteractableItem.cs#L88
So what I'm trying to do is translate the "create a transform" solution to a more math based approach that solely relies on Rigidbody.position and Rigidbody.rotation. But I'm having some significant issues with that. On pickup I get a bunch of variables that might be helpful:
PickupPointItem = this.Rigidbody.position;
PickupRotationItem = this.Rigidbody.rotation;
PickupPointHand = hand.Rigidbody.position;
PickupRotationHand = hand.Rigidbody.rotation;
PickupPointDiff = PickupPointHand - PickupPointItem;
PickupRotationDelta = Quaternion.Inverse(PickupRotationHand) * PickupRotationItem;
Here's my current thought process for getting the deltas I need to apply the velocity:
For rotation I want to get the delta from the hand's initial rotation to the hands current rotation (currentHandRotationDelta). Then I want to apply that rotation to the initial rotation of the item (PickupRotationItem) to get the target rotation. Then the delta between the current rotation and that target rotation should be correct (but doesn't seem to be). Here's my code:
Quaternion currentHandRotationDelta = Quaternion.Inverse(PickupRotationHand) * AttachedHand.Rigidbody.rotation;
Quaternion targetRotation = PickupRotationItem * currentHandRotationDelta;
rotationDelta = Quaternion.Inverse(this.Rigidbody.rotation) * targetRotation;
Position is more complicated. I get the currentPickupPoint, which is the position on the object that the hand should have been over when it was first picked up. I calculate that by getting the point of the current item position plus the initial position delta and rotating that around the pivot of the current item position. Then I take the difference in position from that calculated point and the current rigidbody to get the global delta. Then I use that plus the current hand position as a point to rotate around the pivot of the hand by the rotation of the delta from the initial hand rotation to the current hand rotation. Here's the relevant code for that:
Vector3 currentPickupPoint = RotatePointAroundPivot(PickupPointDiff + this.Rigidbody.position, this.Rigidbody.position, Quaternion.Inverse(PickupRotationItem) * this.Rigidbody.rotation);
Vector3 currentDiff = this.Rigidbody.position - currentPickupPoint;
Vector3 targetPosition = RotatePointAroundPivot(AttachedHand.Rigidbody.position + currentDiff, AttachedHand.Rigidbody.position, Quaternion.Inverse(PickupRotationHand) * AttachedHand.Rigidbody.rotation);
positionDelta = targetPosition - this.Rigidbody.position;
Here's the RotatePointAroundPivot method:
private Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Quaternion rotation)
{
Vector3 dir = point - pivot; // get point direction relative to pivot
dir = rotation * dir; // rotate it
point = dir + pivot; // calculate rotated point
return point; // return it
}
Here's a link to the nonworking code on the development branch of our github repo: https://github.com/TomorrowTodayLabs/NewtonVR/blob/development/Assets/NewtonVR/NVRInteractableItem.cs
This doesn't seem to be working at all :D But I'm not super sure why. I'm pretty new to quaternion math and pretty bad at vector math. Any help would be greatly appreciated.

Vector/Angle math

I have two objects in a game, which for this purpose can be considered points on a 2d plane, but I use Vector3s because the game itself is 3d.
I have a game camera which I want to align perpendicularly (also on the plane) to the two objects, so that they are both in view of the camera. Due to the nature of the game, the objects could be in any imaginable configuration of positions, so the directional vector between them could have any direction.
Part1: How do I get the perpendicular angle from the two positional vectors?
I have:
Vector3 object1Position; // x and z are relevant
Vector3 object2Position;
I need:
float cameraEulerAngleY;
Part2: Now, because of the way the game's assets are modelled, I want to only allow the camera to view within a 180 degree 'cone'. So if the camera passes a certain point, it should use the exact opposite position the above math might produce.
An image is attached of what I need, the circles are the objects, the box is the camera.
I hope this post is clear and you guys won't burn me alive for being total rubbish at vector math :P
greetings,
Draknir
You'll need to specify a distance from the object line, and an up vector:
Vector3 center = 0.5 * (object2position + object2position)
Vector3 vec12 = object2position - object1position
Vector3 normal = Cross(vec12, up)
normal.Normalize()
Vector3 offset = distance * normal
Vector3 cameraA = center + offset
Vector3 cameraB = center - offset
< choose which camera position you want >
Instead of using Euler angles, you should probably use something like LookAt() to orient your camera.
Assuming Y is always 0 (you mentioned "X and Z" are your relevant components), then you can use some 2-d math for this:
1.Find any perpendicular vector (there are two). You can get this by calculating the difference between the two vectors, swapping the components, and negating one of them.
Vector3 difference = (object1Position - object2Position);
Vector3 perpendicular = new Vector3(difference.z, 0, -difference.x);
2.Using your separating plane's normal, flip the direction of your new vector if it's pointing opposite of intended.
Vector3 separatingPlaneNormal = ...; // down?
if(Vector3.Dot(separatingPlaneNormal, perpendicular ) < 0)
{
perpendicular = -perpendicular ;
}
// done.
Well, for the first bit, if you have points (x1, y1) and (x2, y2) describing the positions of your objects, just think of it in terms of triangles. The angle you're looking for ought to be described by
arctan((y2-y1)/(x2-x1))+90
I don't completely understand what you want to do with the second part, though.

Categories