Reputation: 325
I'm using this:
void Update(){
if(leftJoystick){
rb.AddRelativeForce(0, 0, 400f, ForceMode.Impulse);
}
}
to move my character forward in the air (using jetpack). When I let go of the joystick my character stops immediately. What I want is that the character keeps moving forward after joystick is released and with time slow down and gradually stop. It looks stupid that my character stops like it hit a wall. What kind of force/velocity/transform I should use so that physics slow down my character after I let go of the joystick?
My rigidbody settings:
Character also has a capsule collider that is NOT trigger and has no physics material.
EDIT: here is the full code so you can see if there is any conflicts in my code
using UnityEngine;
using System.Collections;
using UnityStandardAssets.CrossPlatformInput;
public class JetpackController : MonoBehaviour{
Rigidbody rb;
// controller axes
[SerializeField]
public string speedAxis = "Vertical";
public string rotateAxis = "HorizontalRotate";
[SerializeField]
public float forwardSpeed;
public float upSpeed;
public float rotateSpeed;
public float rotationIgnoreZone;
public float MAX_HEIGHT;
float speedInput;
float rotateInput;
public bool leftJoystick;
public bool rightJoystick;
ParticleSystem jetpackFire1;
Vector3 originalGravity;
// access Joystick script in Standard assets to detect when right joystick is held down
Joystick joystick_left;
Joystick joystick_right;
void Start () {
if (GetComponent<Rigidbody> ()) {
rb = GetComponent<Rigidbody> ();
} else {
Debug.LogError ("Player needs to have a rigidbody.");
}
// get Joysticks
if (GameObject.Find ("MobileJoystick_left").GetComponent<Joystick> ()) {
joystick_left = GameObject.Find ("MobileJoystick_left").GetComponent<Joystick> ();
} else {
Debug.LogError ("Either gameobject with name 'MobileJoystick_right' does not exist in the scene or it does not have script called Joystick.cs attached to it.");
}
if (GameObject.Find ("MobileJoystick_right").GetComponent<Joystick> ()) {
joystick_right = GameObject.Find ("MobileJoystick_right").GetComponent<Joystick> ();
} else {
Debug.LogError ("Either gameobject with name 'MobileJoystick_right' does not exist in the scene or it does not have script called Joystick.cs attached to it.");
}
jetpackFire1 = GameObject.Find("JetpackFire1").GetComponent<ParticleSystem> ();
jetpackFire1.playbackSpeed = 5.0f;
originalGravity = Physics.gravity;
}
void FixedUpdate () {
GetInput ();
// move forward and backward according to left joysticks input
if(leftJoystick){
// left joystick held down
rb.AddRelativeForce(0, 0, forwardSpeed*speedInput, ForceMode.Impulse);
}
// if right joystick is used
if (rightJoystick) {
jetpackFire1.Play ();
if (transform.position.y < MAX_HEIGHT) {
// allow going up
//rb.AddRelativeForce (0, upSpeed, 0, ForceMode.Impulse);
rb.AddForce(transform.forward * forwardSpeed);
} else if (transform.position.y >= MAX_HEIGHT) {
// prevent player to go any further up and also falling
Physics.gravity = Vector3.zero; // no gravity to prevent player from falling
rb.velocity = Vector3.zero;
}
// rotate
// always keep rotating (player can go past look at joystick dir)
if (rotateInput >= rotationIgnoreZone || rotateInput <= -rotationIgnoreZone) {
transform.Rotate(Vector3.up * rotateInput, Time.deltaTime * rotateSpeed);
}
} else {
jetpackFire1.Stop ();
// if right joystick is released
Physics.gravity = originalGravity; // normal gravity -> player can fall
}
}
public void GetInput(){
speedInput = CrossPlatformInputManager.GetAxis (speedAxis);
rotateInput = CrossPlatformInputManager.GetAxis (rotateAxis);
// access Joystick.cs script to grab wether right joystick is pressed or not
leftJoystick = joystick_left.leftJoystickPressed;
rightJoystick = joystick_right.rightJoystickPressed;
}
}
Upvotes: 3
Views: 26263
Reputation: 96
You could do a simple linear slow down.
void Update(){
if(leftJoystick){
rb.AddRelativeForce(0, 0, 400f, ForceMode.Impulse);
}
if(noJoystick){
rb.velocity = rb.velocity * 0.9f;
}
}
Note that the update function gets called on frame update, so I would suggest putting this in a FixedUpdate() function that way the slow rate won't depend on the frame rate.
Upvotes: 0
Reputation: 431
Can't comment yet
Like J.Small said, you could multiply the velocity with a number around 0.95 to slowly slow the rigidbody down. If you put the multiplication in the Update method I suggest you to multiply the ~0.95 number with Time.deltaTime, so the velocity decrease will be proportional to the passed time.
void Update(){
if(leftJoystick){
rb.AddRelativeForce(0, 0, 400f, ForceMode.Impulse);
}
if(noJoystick){
rb.velocity = rb.velocity * 0.95f * Time.deltaTime;
//Or: rb.velocity.x
}
}
You could also apply a small amount of force instead of multiplying the velocity if you want to slow down the rigidbody in a more configurable way (the amount should be based on Time.deltaTime if you put it into Update - which gets called once a frame), but the method above is easier.
Upvotes: 2
Reputation: 21
I'm not a pro at coding, so I'm not sure if this'll work for everyone, but I tried something like this to fix a similar issue.
void FixedUpdate()
{
playerRigidbody.AddRelativeForce(Vector2.up * forwardInput * playerSpeed * Time.fixedDeltaTime);
if (forwardInput <= 0)
{
playerRigidbody.velocity = playerRigidbody.velocity / 1.005f; // <-- This will gradually slow down the player when they're idle.
}
}
Upvotes: 2