I am trying to create mid-air movement for a 3D platformer, and I am trying to use transform.forward and transform.right as floats. However, I can't seem to figure out how to change them into float values, since they are Vector3 variables. Here is what I have tried:
velX = transform.forward * Input.GetAxis("Horizontal");
velZ = transform.right * Input.GetAxis("Vertical");
What I got was an error saying the transform.forward and transform.right are Vector3 values, wheras velX and velZ are floats.
Not entirely sure what you're trying to achieve but if you're looking for a scalar representation of a vector, that is the actual vector length, then Vector3.magnitude will get it. It'll return the distance between the given vector origin and its endpoint.
You get the vector magnitude by calling:
Vector3.magnitude(point.forward)
And I'm almost certain you can even do:
point.forward.magnitude
You can go here and here for further reference.
Again, I'm not sure if that's what you're trying to get but I hope it helps.
Figured it out:
velX = (transform.forward.x + transform.right.x) * Input.GetAxis("Horizontal");
velZ = (transform.forward.z + transform.right.z) * Input.GetAxis("Vertical");
Related
I have one problem in script(Unity) that I made for car controller. When I want to rotate front wheels of car, example I'm pressing 'A' or 'D' wheels will turn on left or right(0,45 or -45,0) and immediately it will turn on starting rotation(0,0,0), I didn't have this problem when I didn't use Quaternion.Lerp, without Quaternion.Lerp it works fine. Any kind of help will be welcome.
//Rotation - WHEELS
CurrentRotation = Horizontal * RotationSpeed * Time.deltaTime;
if (CurrentRotation <= MaximumRotation || CurrentRotation >= -MaximumRotation)
{
Vector3 from_v = new Vector3(Wheels[0].transform.localRotation.x, Wheels[0].transform.localRotation.y, Wheels[0].transform.localRotation.z);
Vector3 to_v = new Vector3(Wheels[1].transform.localRotation.x, CurrentRotation, Wheels[1].transform.localRotation.z);
Quaternion from = Quaternion.Euler(from_v);
Quaternion to = Quaternion.Euler(to_v);
float lerp = 0.5F * (1.0F + Mathf.Sin(Mathf.PI * Time.realtimeSinceStartup * 3f));
Wheels[0].transform.localRotation = Quaternion.Lerp(from, to, lerp);
Wheels[1].transform.localRotation = Quaternion.Lerp(from, to, lerp);
}
I don't fully understand what you want to achieve. Is it the rolling of the wheel plus steering?
Quaternions are great, but here you don't need them. You can get and set the Euler (main axis) rotation directly. Untested code:
Vector3 rot = Wheels[0].localRotation;
rot.x += speed * Time.deltaTime;
rot.y = (current smoothed steering angle)
Wheels[0].localRotation = rot;
Wheels[1].localRotation = rot;
You should orient all your wheel game objects to point x-Axis to the right and Y-Axis to the top. The smoothing / max angles can depend on the input type / device, the game settings and the car speed.
It would be nice if you upvote my answer so I finally can write comments here.
Kind Regards,
Chris
I've been trying to make a really basic fps character controller script, but I couldn't solve the movement stacking when I'm moving sideways. I'm sure it's really basic solutin, but as a beginner it's hard for me to solve it.
float forwardSpeed = Input.GetAxis("Vertical") * movementspeed;
float sideSpeed = Input.GetAxis("Horizontal") * movementspeed;
Vector3 VecForwardSpeed = new Vector3(sideSpeed, verticalVelocity, forwardSpeed);
VecForwardSpeed = transform.rotation * VecForwardSpeed;
characterController.Move(VecForwardSpeed * Time.deltaTime);
If I understand you correctly what you mean is if moving forward and sidewards at the same time these inputs/velocities "stack" or sum up allowing the user to move faster then actually allowed.
You could solve this by normalizing them meaning you make sure that combined they never exceed a magnitude value of 1 like e.g.
// Get a vector of the combined input
var combinedInput = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
// Check if the magnitude exceeds 1
// sqrMagnitude is more efficient here and for comparing to 1
// behaves the same as magnitude
if(combinedInput.sqrMagnitude > 1)
{
// If so normalize the input vector to force it again
// to have the maximum length/magnitude of 1
combinedInput.Normalize();
}
// Until then apply the movementspeed here
combinedInput *= movementspeed;
// Now use the components of this combined and evtl normalized input vector instead
var vecForwardSpeed = transform.rotation * new Vector3(combinedInput.x, verticalVelocity, combinedInput.y) * Time.deltaTime;
characterController.Move(vecForwardSpeed);
From your question it is not sure though how the verticalVelocity comes into play.
I am trying to do client side prediction a rotation. I was thinking this would work is similar to how I did the position. But I can't seem to find a way to rotate my Quaternion.
// These are synced over the network
private Vector3 bestGuessPosition;
private Vector3 velocity;
private Quaternion bestGuessRotation;
private Vector3 angularVelocity;
// Postion
bestGuessPosition = bestGuessPosition + (velocity * Time.deltaTime);
transform.position = Vector3.Lerp(transform.position, bestGuessPosition, Time.deltaTime * latencySmoothingFactor);
// Rotation (not working)
bestGuessRotation = bestGuessRotation + (angularVelocity * Time.deltaTime);
transform.rotation = Quaternion.Lerp(transform.rotation, bestGuessRotation, Time.deltaTime * latencySmoothingFactor);
How do I rotate my bestGuessRotation? There doesn't seem to be a .Rotate like there is on a Transform.
In Unity two Quaternions are combined using "multiplaction" * (order matters!)
You can convert your Vector3 rotation angularVelocity from Euler space to a Quaternion using Quaternion.Euler
bestGuessRotation *= Quaternion.Euler(angularVelocity * Time.deltaTime);
Btw also the position can easier be written as
bestGuessPosition += velocity * Time.deltaTime;
Just guessing you are using this in Update using Lerp might not be the best option here depending what exactly you expect from this rotation.
If using Lerp in Update for example as a simple smoothing algorithm you should remove the Time.deltaTime as the interpolation factor is a percentage value and in this case should stay the same.
i have start a project in unity 3d.I want to make a spaceship that moving forward,but when i pressed the ArrowUp then i want to change its y postion to
( currentpos+ 1.5 ) but i want this smoothly.
this is my code
transform.position += transform.forward * Time.deltaTime * 10f;
if (Input.GetKey (KeyCode.UpArrow))
transform.position = new Vector3 (transform.position.x, 5f,
transform.position.z);
through the above code the Y position of object can b changed but it work so fast and i want to make it smooth.
so please help me.
I think the best solution to your problem is to use Mathf.SmoothDamp.
Example:
private float targetY = 0f;
private float verticalVelocity = 0f;
private const float smoothTime = 1f;
private void Update()
{
transform.position += transform.forward * Time.deltaTime * 10f;
if (Input.GetKey(KeyCode.UpArrow))
{
targetY = 5f;
}
float y = Mathf.SmoothDamp(transform.position.y, targetY, ref verticalVelocity, smoothTime);
transform.position = new Vector3 (transform.position.x, y, transform.position.z);
}
This example will smoothly change the y coordinate to 5 over the course of 1 second (you can change the smoothTime constant for a different time).
Based in your own code the easiest way for you to work it out could be something like this
//this sets the X position
transform.position += transform.forward * Time.deltaTime * 10f;
//if the button is pressed then modify Y
if (Input.GetKey (KeyCode.UpArrow))
transform.position += new Vector3 (0, 5f * Time.deltaTime * y_speed,0);
y_speed could be a public float y_speed = 1.0f in your script so you could modify it from the inspector to get the effect you want to achieve.
Hope it helps!
Assuming your spaceship is a rigidbody, you should take a look at Rigidbody.AddForce
https://docs.unity3d.com/ScriptReference/Rigidbody.AddForce.html
By working with forces, you can get a smooth movement in all directions very easily, and tweak it within the Rigidbody's parameters (like mass) without fiddling in the script again. It's part of the Unity physics model.
If you only want to move in y-direction, input a vector like (0,1,0) but you can also input the Transform.forward vector of your spaceship's Gameobject. That way, it will always move the direction it is facing in.
I have two objects, predator and prey. I am trying to write code so that when the predator sees the prey, it rotates in its direction and moves forward (in that same direction).
Vector3.RotateTowards (transform.forward, preyPos, Mathf.Infinity, Mathf.Infinity);
transform.Translate (transform.forward * predatorSpeed);
My understanding is that the above code should rotate transform.forward, however it is the same vector both before and after that line. Why is this happening? I have tried many things, but I can't get this to work out.
Because Vector3 in Unity is a struct (value type) thus always passed by value.
Vector3 v = Vector3.zero;
ChangeValue(v); // Change value of v.x, v.y, v.z
Debug.Log(v); // still (0, 0, 0);
That said, Vector3.RotateTowards() has to return a Vector3. Basically, you need:
transform.forward = Vector3.RotateTowards (transform.forward, preyPos, Mathf.Infinity, Mathf.Infinity);
But i'm not sure it will work because transform.forward is immutable.
https://docs.unity3d.com/ScriptReference/Vector3.RotateTowards.html
If you want rotating to face a target, consider 1 of these:
Transform.LookAt();
Quaternion.RotateTowards();
Quaternion is a struct as well so please read the docs carefully.