I have completed this course and i was wondering how would i add a key that allows for breaking. do i need to scrap the current code i have for rotation and switch it with torque or i could achieve the same result with getting access to the magnitude of drag and increasing that to slow the movement acting as a breaking system, would something like this work?
Hi Imadity,
Are you looking for Time.timeScale
?
I haven’t used Time.timescale what iu understand for unity API is that is works as a slowmotion or fast forward but wouldnt using the physics reccomended for movement, and even if i use Time.timeScale can you help me with how i can implement in the current code without braking anything
This is my current code
public class Movement : MonoBehaviour
{
Rigidbody rb;
AudioSource audioSource;
[SerializeField] float mainThrust = 1000f;
[SerializeField] float rotationSpeed = 0f;
[SerializeField] AudioClip mainEngine;
[SerializeField]ParticleSystem thrusterParticle;
[SerializeField]ParticleSystem leftThrusterParticle;
[SerializeField]ParticleSystem rightThrusterParticle;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
audioSource = GetComponent<AudioSource>();
}
// Update is called once per frame
void Update()
{
ProcessThrust();
ProcessRotation();
}
void ProcessThrust()
{
if (Input.GetKey(KeyCode.W))
{
StartThrusting();
}
else
{
StopThrusting();
}
void StartThrusting()
{
rb.AddRelativeForce(mainThrust * Time.deltaTime * Vector3.up);
if (!audioSource.isPlaying)
{
audioSource.PlayOneShot(mainEngine);
}
if(!thrusterParticle.isPlaying)
{
thrusterParticle.Play();
}
}
void StopThrusting()
{
audioSource.Stop();
thrusterParticle.Stop();
}
}
void ProcessRotation()
{
if (Input.GetKey(KeyCode.A))
{
RotatingLeft();
}
else if (Input.GetKey(KeyCode.D))
{
RotatingRight();
}
else
{
StopRotating();
}
void RotatingLeft()
{
transform.Rotate(rotationSpeed * Time.deltaTime * Vector3.forward);
rb.freezeRotation = false;
if (!rightThrusterParticle.isPlaying)
{
rightThrusterParticle.Play();
}
}
void RotatingRight()
{
transform.Rotate(rotationSpeed * Time.deltaTime * -Vector3.forward);
rb.freezeRotation = false;
if (!leftThrusterParticle.isPlaying)
{
leftThrusterParticle.Play();
}
}
void StopRotating()
{
rb.freezeRotation = true;
rightThrusterParticle.Stop();
leftThrusterParticle.Stop();
}
}}
If you set Time.timeScale
to, for example, 0f, the game pauses. If you set it to 1f, you get the normal game speed, 0.5f would slow the game down, 2f would speed it up. Of course, the physics simulation is also affected by the time scale.
What exactly would you like to achieve?
I would like thr game object (rocket) to slow down if the player hits the space key not the
for eg. if the rocket is moving forward and the player hits the space key the rocket should slowy start to slow down till the time rocket doest have any momentum in the intial direction it was moving which in our case would be forward, now the part i dont understand is do we use the Time.timeScale in the method where we are declaring the main thrust or in rotation aswell
Time.timeScale
won’t work because what it does is slow down the entire game, so it’s not a brake, the rocket would move at the exact same speed but in slow motion.
It depends on how you want to slow down your rocket. I suggest think about your rocket, How does it slow down? It uses thrusters? Is it using some sort of air device? I know this sounds silly, but that’ll actually give you the answer. I’ll give you two examples:
Thruster brake: I would apply an opposite force to the own that pushes the rocket up.
Air brake: I would gradually change the velocity to 0, I suggest using the function Vector3.Lerp
for an easy way to achieve this.
There many other ways to decrease your rocket’s speed, but as I said, don’t think code-wise, think how would a brake work in your game’s world.
Maybe it is sufficient to significantly increase the value of drag
when the rocket is supposed to slow down.
I thought about the drag but I noticed a problem on the moment you try to set it to the regular value, it might cause some weird unexpected movement, a sudden acceleration that feels a little bit weird, it doesn’t happen all the time but it does happen. I just tested it quickly, so there might be a way to fix that easily, I suppose you could cache the rigidbody’s velocity, set the drag to the regular value and right after that set it to what it was right before the drag adjustment.
Ohk i tried lerping between 2 values of min break and maximum break and set a time for the that lerp to complete in and used that in the add relative force that applies force in the opposite direction of the main thrust. I have shared my code at the start of the thread and these are the changes I made
[SerializeField] float minBreak = 100f;
[SerializeField] float maxBreak = 1000f;
[SerializeField] float breakDuration = 1.5f;
float breakPressure;
//Added The Lerp in Update
void Update()
{
breakPressure = Mathf.Lerp(minBreak, maxBreak, breakDuration);
ProcessThrust();
ProcessRotation();
}
//Added an if statement for GetKey
void StopThrusting()
{
if (Input.GetKey(KeyCode.Space))
{
rb.AddRelativeForce(breakPressure * Time.deltaTime * Vector3.down); ;
}
audioSource.Stop();
thrusterParticle.Stop();
}
After testing and playing around with the values I don’t know if the lerp is working or not and i don’t know how to Debug this to see how the value increases. What have i done wrong here?
Using drag to slow the movement down was my first thought aswell as rockets doest have any breaks they get slow down from 2 variable thruster output and drag but i dont really understand how to use that logic to implement in my code
I also tried to use the Drag to slow down the rocket i think I’m just getting the 1 value of the lerp and it does’t gradually increase toward the target value there’s something defiantly wrong with the code
But here’s my attempt to use Drag
[SerializeField] float airDrag = 1f;
[SerializeField] float breakDrag = 3f;
[SerializeField] float dragSpeed = 0.5f;
//In start
void Start()
{
//starting the lerp dont know if this should be here
Mathf.Lerp(airDrag, breakDrag, dragSpeed);
rb = GetComponent<Rigidbody>();
audioSource = GetComponent<AudioSource>();
}
void StopThrusting()
{
if (Input.GetKey(KeyCode.Space))
{
rb.drag = Mathf.Lerp(airDrag, breakDrag, dragSpeed * Time.deltaTime);
}
if (!Input.GetKey(KeyCode.Space))
{
rb.drag = airDrag;
}
audioSource.Stop();
thrusterParticle.Stop();
}
When I press Space the drag of the object increases from 1 to 1.01-.02 and fluctuates in between these values. I know this is a pathetic attempt but I don’t really understand what line of code belongs where other than caches variables and methods
Really nice that you are pushing yourself!
I’m seeing some few logic errors within your code, you’ll eventually get how the Lerp function works, for now it’s probably a good idea to stick with the drag solution, since you don’t really need to use Lerp for that.
The idea is to simply gradually increment the drag.
if (Input.GetKey(KeyCode.Space))
{
rb.drag += Time.deltaTime;
}
That would be more than enough, but, the brake would be too slow, so you just have to multiply the Time.deltaTime
value with something else.
[SerializeField] float brakeForce = 5f;
private void Brake()
{
if (Input.GetKey(KeyCode.Space))
{
rb.drag += Time.deltaTime * brakeForce;
}
}
This causes an issue, the drag will stay up, and your rocket will not accelerate as intended, so you’ll have to reset the drag to its initial value.
To achieve this you’ll need a reference of the initial drag value and a way to revert it, this might cause some issues when a player tries to accelerate and brake at the same time, the rocket might behave a little crazy, but as far as I tested, as long as your rocket isn’t moving super fast, the issue is barely noticeable.
The complete brake behaviour would look something similar to this:
[SerializeField] float brakeForce = 5f;
float initialDrag;
private void Awake()
{
initialDrag = rb.drag;
}
private void Brake()
{
if (Input.GetKey(KeyCode.Space))
{
rb.drag += Time.deltaTime * brakeForce;
}
if(Input.GetKeyUp(KeyCode.Space))
{
rb.drag = initialDrag;
}
}
Hope this helps!
This makes a lot more sense defiantly and is easier that setting up a lerp value for drag also if i wanted to clamp the values of the drag if in the future this way would be easier to navigate through better gameplay wise.
There’s just one error when we set the float value of initialDrag and don’t assign it any value the console is printing and error that says Object reference not set to instance of object
do we say that the initialDrag = new something soo it doest misbehave?
NullReferenceException means that a reference (“link”) to an instance is missing. Double click on the error message to see to which line in your code it is referring. If you exposed a field in the Inspector, make sure that it’s not empty.
@Yee defined initialDrag
at the top of the class. Since it is of type float and since he did not assign any value to it, the default value is 0f. Actually, you should not get a NullReferenceException unless rb
is null
. Of course, you have to assign a Rigidbody object to rb
like you did in your own code.
I tried adding value to float initialDrag but the console still prints
Line 23-
void Awake()
{
initialDrag = rb.drag;
}
any solution to get around this error ?
In your original code, you had this line:
rb = GetComponent<Rigidbody>();
This line assigns a Rigidbody object to rb
if GetComponent finds a Rigidbody component.
Do you execute this line in your new code, too? If so, where?
I am using that line in void Start and i tried using it void Awake to see if that makes it work but it didnt
Awake gets executed before Start. If you call GetComponent in Start but access rb
in Awake, you’ll get a NullReferenceException error.
i tried placing it in awake aswell but it still didnt work
ohk never mind i placed the rb.GetComponent line after getting thr drag value switching them around worked
Where/how did you place it in Awake? Could you please share the relevant code?