- Home /
Having several problems with rigidbody movement script
Hello!
I have this script
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour {
public float Speed;
public float LookSpeed;
public int LookRange;
public float JumpForce;
public bool IsJumping;
private float MouseX;
private float MouseY;
public bool [] IsMoving = new bool [4];
void FixedUpdate () {
// WASD Movement
if (Input.GetKey (KeyCode.W))
{
if (IsMoving [0] == false)
{
GetComponent <Rigidbody> ().velocity += transform.forward * Speed;
IsMoving [0] = true;
}
}
else if (IsMoving [0] == true)
{
IsMoving [0] = false;
}
// Mouse Look
MouseX += Input.GetAxis ("Mouse X") * LookSpeed * Time.deltaTime;
transform.rotation = Quaternion.Euler (0, MouseX, 0);
MouseY -= Input.GetAxis ("Mouse Y") * LookSpeed * Time.deltaTime;
MouseY = Mathf.Clamp (MouseY, -LookRange / 2, LookRange / 2);
Camera.main.transform.localRotation = Quaternion.Euler (MouseY, 0, 0);
// Jumping
if (Input.GetKey (KeyCode.Space) && IsJumping == false)
{
GetComponent <Rigidbody> ().velocity += Vector3.up * JumpForce;
IsJumping = true;
}
}
void OnTriggerStay (Collider Col) {
if (Col.gameObject.tag == "Block Top")
{
IsJumping = false;
}
}
}
and as you can probably see, there is a bit of movement script I have started to make.
This is one of several attempts to make a good movement script that doesn't interfere with collision. Another attempt was adding and subtracting to and from transform.position. This was very bad for physics as colliders intersected. I am now trying to use rigidbody.velocity. I also know of rigidbody.AddForce. Please let me know if I should try something else (and if so, what?) or of this code could be fixed. I just need a push, to get my new and improved movement script working.
Pros with this script:
Fixes collision sticking
Almost seems to work the same, minus some issues to work on
Cons with this script:
I glide after letting go of W.
I can't jump up while colliding with a block's side, because the velocity is set once, and is not set again after pressing W.
EDIT
This is the new bit of script I am working on:
Inputs [0] = Input.GetKey (KeyCode.W);
Inputs [1] = Input.GetKey (KeyCode.A);
Inputs [2] = Input.GetKey (KeyCode.S);
Inputs [3] = Input.GetKey (KeyCode.D);
if (Inputs [0] == true)
{
Directions [0] = transform.forward;
}
else
{
Directions [0] = Vector3.zero;
}
if (Inputs [1] == true)
{
Directions [1] = -transform.right;
}
else
{
Directions [1] = Vector3.zero;
}
if (Inputs [2] == true)
{
Directions [2] = -transform.forward;
}
else
{
Directions [2] = Vector3.zero;
}
if (Inputs [3] == true)
{
Directions [3] = transform.right;
}
else
{
Directions [3] = Vector3.zero;
}
Directions [4] = Directions [0] + Directions [1] + Directions [2] + Directions [3];
if (Directions [0] == transform.forward * Speed && Directions [1] == -transform.right * Speed && Directions [2] == -transform.forward * Speed && Directions [3] == transform.right * Speed)
{
GetComponent <Rigidbody> ().velocity += Directions [4];
Its a little broken, but hopefully you will see where I am going with this. I await the community's reply and thanks in advance!
That last part, after your edit, looks pretty good, though I don't see why you have that IF statement on the bottom. If you put this at the begging of that function, you wont need the if at all. Initialize these value to zero. They will be changed and used, only if the appropriate key is depressed.
Directions [0]=Vector3.zero;
Directions [1]=Vector3.zero;
Directions [2]=Vector3.zero;
Directions [3]=Vector3.zero;
Now, when you do the vector addition at the end, those values that didn't have a key pressed, will have no effect (adding zero).
EDIT: ah, I see you have those Vector.Zero's in their ELSE statements, ok, that should work.
one other thing:
GetComponent <Rigidbody> ().velocity += Directions [4];
does not multiply by the speed!
GetComponent <Rigidbody> ().velocity += Directions [4] * Speed;
Hi @Glurth!
Yes I think it'll work too. the only problem, though, is what if I want to add flowing water? or jumping? The problem then would be that I absolutely have to use += for velocity movement, and that's a problem, because then I need to make it only happen once. Do you know of any solution?
EDIT
Another problem is it affects falling if I use
GetComponent <Rigidbody> ().velocity = Directions [4];
ins$$anonymous$$d of
GetComponent <Rigidbody> ().velocity += Directions [4];
because it makes velocity.y set to 0.
However, using that second snippet causes obstacles as well. It keeps adding to the velocity until my speed is off the charts! How can I limit this?
Also this is the most recent version of my code as of now:
Inputs [0] = Input.Get$$anonymous$$ey ($$anonymous$$eyCode.W);
Inputs [1] = Input.Get$$anonymous$$ey ($$anonymous$$eyCode.A);
Inputs [2] = Input.Get$$anonymous$$ey ($$anonymous$$eyCode.S);
Inputs [3] = Input.Get$$anonymous$$ey ($$anonymous$$eyCode.D);
if (Inputs [0] == true)
{
Directions [0] = transform.forward * Speed;
}
else
{
Directions [0] = Vector3.zero;
}
if (Inputs [1] == true)
{
Directions [1] = -transform.right * Speed;
}
else
{
Directions [1] = Vector3.zero;
}
if (Inputs [2] == true)
{
Directions [2] = -transform.forward * Speed;
}
else
{
Directions [2] = Vector3.zero;
}
if (Inputs [3] == true)
{
Directions [3] = transform.right * Speed;
}
else
{
Directions [3] = Vector3.zero;
}
Directions [4] = Directions [0] + Directions [1] + Directions [2] + Directions [3];
One solution is to use a different input function. the Get$$anonymous$$ey function you are using will return TRUE every cycle that key is down. (like auto-fire) http://docs.unity3d.com/ScriptReference/Input.Get$$anonymous$$eyDown.html This one, Get$$anonymous$$eyDown, works a little differently, and will only return true the FIRST cycle the key is depressed.
I definitely think you want to ADD to the current velocity, rather than replace/overwrite it. You just need to manage WHEN you add it more carefully.
You might also look into using AddForce(), rather than manually adjusting the velocity. http://docs.unity3d.com/ScriptReference/Rigidbody.AddForce.html
Yes but, I want it to walk if i pause, hold w, and unpause in that order.
here is an uncompiled(may have typos) sample of how I would do something like that. Note the velocity stuff stays the same, all that changes is WHEN I'm applying it.
bool walking=false; //this variable is declared in your class
//this code would be inside fixedupdate
if(Get$$anonymous$$eyDown($$anonymous$$eyCode.W))
{
if(walking)
//adjust velocity to STOP walking ( use -= )
else
//adjust velocity to START walking ( use += )
//change the flag for next time
walking = !walking;
}