- Home /
Getting rid of double movement speed?
Hi, I currently have a ball that rolls around when you press one of the WASD keys
But when I press two simultaneously, it gives the speed from both keys to that direction
Such as (W give 10 speed forward, D gives 10 speed right, but WD gives 20 speed top-right)
Is there a way I can fix this? Please explain your idea if you can too, trying to learn here =D Let me know if there is any additional info you need, Thanks again!
Here is the script I have for movement so far
var Speed = 0;
function Move()
{
if (Input.GetKey (KeyCode.W))
{
rigidbody.AddTorque(Vector3.right * Speed);
rigidbody.AddForce(0, 0, Speed);
}
if (Input.GetKey (KeyCode.S))
{
rigidbody.AddForce(0, 0, -Speed);
rigidbody.AddTorque(Vector3.left * Speed);
}
if (Input.GetKey (KeyCode.A))
{
rigidbody.AddForce(-Speed, 0, 0);
rigidbody.AddTorque(Vector3.forward * Speed);
}
if (Input.GetKey (KeyCode.D))
{
rigidbody.AddForce(Speed, 0, 0);
rigidbody.AddTorque(Vector3.back * Speed);
}
}
function FixedUpdate()
{
if (Input.GetKey (KeyCode.W))
{
Move();
}
if (Input.GetKey (KeyCode.S))
{
Move();
}
if (Input.GetKey (KeyCode.A))
{
Move();
}
if (Input.GetKey (KeyCode.D))
{
Move();
}
if (Input.GetKey(KeyCode.Space))
{
if (letJump)
{
Jump();
}
}
}
Answer by animalphase · May 20, 2013 at 10:25 PM
This is an old, "classic" problem dating back to the beginning of the FPS days. A lot of competitive FPS players use this "trick" in affected games to gain a speed boost. I think it is called "crossing the square", but google is really failing me right now on the subject.
To manage input, instead of checking for key pressed, it is probably better to use Input.GetAxis(). This will return a value of from -1 to 1 in each movement direction, and on the plus side will automatically work with gamepads and joysticks.
So the updated code would go something like this:
Vector3 direction = new Vector3(0,0,0);
direction.x = Input.GetAxis("Horizontal");
direction.z = Input.GetAxis("Vertical");
direction.Normalize();
rigidbody.AddForce( direction * Speed );
The above should be the entire contents of the Move() function, aside from any extras that you may put in there. The line "direction.Normalize()" will take the vector that is already pointing in the correct direction and make it only 1 unit long. Thus, you will be able to multiply by "Speed" to get the correct amount.
Thanks yours really did the trick, just gotta get my Jump function in there somehow and I should be golden
Answer by TomPendergrass · Feb 03, 2018 at 11:15 PM
A better answer is to use ClampMagnitude. Normalizing your movement vector will always restrict it to a magnitude of 1 (or zero if the vector's magnitude is too small). ClampMagnitude on the other hand will leave your magnitude alone unless it exceeds a your maxLength value. Since you're multiplying by speed, you will want to clamp to the maxLength of 1.
Answer by Lairinus · May 20, 2013 at 10:09 PM
Vector normalization, for one.
Basically you want to multiply the speed by (roughly) 0.7071 if you're going to be moving on an angle. It has something to do with the length of the vector making the distance traveled ridiculous.
What I would do is organize the code better so that instead of directly calling move after each individual input, you could do something like if ( W && D) Speed * 0.7071, which is the other reason why it's not working.
If you hit 2 buttons with your current code, the function is called twice.
Basically, record all of the input you receive. Then at the end of the function, use another Move() method to actually call the direction. If it's a diagonal, multiply the speed by .7071 (I believe Vector3.normalize does the same thing).
Ahh I see what you meant about the "calling it twice thing" just deleting all of the stuff in the FixedUpdate and leaving one $$anonymous$$ove() function fixed most of my problem
So I would do 12 if statements at the end of my function to check for multiple keys? Or am I interpreting that wrong?
Yes you're interpreting it right, I just don't use Unityscript so I can't give you a source code of what I really meant :(
Look up enums and how to use them ins$$anonymous$$d of if statements. It makes your code cleaner and faster, especially in situations like this when you're frequently checking 8+ options.
Basically with the enum you could do things like:
case(the enum's if-statement) currentDirection = Direction.Left: //do your code