[SOLVED] Dynamic Rocket Cage Movement Physics

https://playcanvas.com/editor/project/800196

I want to “animate” the dynamic rocket cages of the dronecar in this simulation.

Dronecar

Similar to how car racing games “animate” the wheels of its cars: I want to apply physics to the rocket cages to “rotate” about the gear axis according to the relative movement and keypress.

For example, all four rocket cage gears tilt forward on KeyPressW.

There are two ways of doing this, one involves adding an animation component, and the other is to, I think, treat each “Dynamic Rocket Cage” (“DRC”) as an array [0], [1], [2], and [3] for DRC-front-right, DRC-front-left, DRC-back-left, DRC-back-right, or something similar, and then rotating each respective gear according to the relative directional controls. I want to do the latter.

What’s a good place to start?

If I understand you correctly and you want to hear an unprofessional suggestion without using animations, you could try to rotate the part(s) with 0.01 until the maximum rotation is reached when the specific key is pressed. You do the same the other way when the specific key is not pressed to bring them back in the default state.

So, I read somewhere that clamp can be used to make a maximum value. Would I combine this with applyTorqueImpulse? How would the code for this look?

Also, I tried rotating the “cages”, but it does not seem to be working.
RotateCages

It’s the same as for the yaw of the dronecar, except the script is added to the script component of the rocket cages.

To get a better visual of what I need the cages to do go to https://www.lurentz.com/research > Structural Prototype

Your entity doens’t have a rigidbody component, so that’s porbably why your way is not working.

I think it will look something like below, but you have to determine the correct axis yourself.

if (this.app.keyboard.isPressed(pc.KEY_W) {
    if (this.entity.getEulerAngles().y < 45) {
        this.entity.rotate(0,0.1,0);
    }
}
else {
    if (this.entity.getEulerAngles().y > 0) {
        this.entity.rotate(0,-0.1,0);
    }
}
1 Like

Awesome! It works :slight_smile:

I’m trying to implement the yaw left script component to the back right DRC rigidbody, but it does not seem to be working. The script and process of attaching the script is the same.

keypressayawleft

But the animation is unresponsive on KeyPressA. Am I overlooking something? By the way, this is the image I’m after:
509cc2_411841f6d4804c848c5716333a1fa06e_mv2
I am working on the front and back cage individually since each one rotates in different x directions.

1 Like

Thank you for the video, nice to see the result.

I totally don’t understand what you say here. What do you mean with yaw and what is DRC?

Can you show the code please?

1 Like
if (this.app.keyboard.isPressed(pc.KEY_A)) {
 if (this.entity.getEulerAngles().x < 33) {
     this.entity.rotate(0.1,0,0);
  }
 }
else {
if (this.entity.getEulerAngles().x > 0) {
    this.entity.rotate(-0.1,0,0);
  }
 }

Sorry, I was referring to the “Dynamic Rocket Cage” (DRC) as I established the convention in the first post lol and yaw just means “rotating about an axis.” The code is above. It’s the same as the other one with the only difference being pc.KEY_A.

The code is based on a model without a (dynamic) rigidbody. If you use my code on a model with a dynamic rigidbody it’s probably not working.

It was working with dynamic. I changed it to static, but it’s still not working :confused:

I think you can use this way also with applyTorqueImpulse like you did in your first post here, but when I looked at your project there was no rigidbody on that part of the model. So you can try it again if it has a dynamic rigidbody. Otherwise it has to be a kinematic rigidbody.

Note that there are two scripts are enabled on one of your models. Possible that they are conflicting with each other.

Okay, I got it. Basically, I made four different script files for each of the rocket cages.

fourscripts

Here’s the pseudocode I wrote to help me organize my thoughts in case you were wondering:

  1. Front left
    (((Pitch forward (KeyPressW)
    if x<33{0.1,0,0}

Pitch backward (KeyPressS)
if x>-33 {-0.1,0,0})))

Yaw left (KeyPressA)
if x>-33 {-0.1,0,0}

  1. Front right
    (((Pitch forward (KeyPressW)
    if x<33{0.1,0,0}

Pitch backward (KeyPressS)
if x>-33 {-0.1,0,0})))

Yaw right (KeyPressD)
if x>-33 {-0.1,0,0}

  1. Back left
    (((Pitch forward (KeyPressW)
    if x<33{0.1,0,0}

Pitch backward (KeyPressS)
if x>-33 {-0.1,0,0})))

Yaw right (KeyPressD)
if x<33{0.1,0,0}

  1. Back right
    (((Pitch forward (KeyPressW)
    if x<33{0.1,0,0}

Pitch backward (KeyPressS)
if x>-33 {-0.1,0,0})))

Yaw left(KeyPressD)
if x<33{0.1,0,0}

Any way to fix the rocket cages from breaking?

1 Like

To prevent it from breaking you have to use rotateLocal instead of rotate, sorry for that. Apart from that, there are a number of other issues in your project.

  • You use diffrent types of rigidbodies. My solution is only working for kinematic rigidodies, if you need to use a dynamic rigidbody you could try to use applyTorqueImpulse instead of rotateLocal. So, first determine whether or not you need to use dynamic rigidbodies. (Kinematic rigidbodies do not respond to obstacles and dynamic rigidbodies do).

    Physics Basics | Learn PlayCanvas

  • Your scripts are messy. The overview disappears and you overlook typos. Make sure you use the correct indentations.

  • Your logic is wrong. The keys are conflicting with each other. Using different rotation speeds doesn’t make it any better. If you’re using kinematic rigidbodies then your code for drcFrontRight.js should look something like below. I’m not sure if this adjustment is enough, but I hope this is enough for you to see the problem.

    if (this.app.keyboard.isPressed(pc.KEY_W) && this.entity.getLocalEulerAngles().x <= 33) {
        this.entity.rotateLocal(0.1,0,0);
    }
    else if (this.entity.getEulerAngles().x >= 0) {
        this.entity.rotateLocal(-0.1,0,0);
    } 
    
    
    if ((this.app.keyboard.isPressed(pc.KEY_S && this.entity.getLocalEulerAngles().x >= -33)) || 
        (this.app.keyboard.isPressed(pc.KEY_D) && this.entity.getLocalEulerAngles().x >= -33)) {
        this.entity.rotateLocal(-0.1,0,0);
    }
    else if (this.entity.getEulerAngles().x <= 0) {
        this.entity.rotateLocal(0.1,0,0);
    }
    
2 Likes

Thank you for the detailed explanation! I updated the scene according to what you said and it seems to be working now.

I want to keep developing the simulation to include more detailed artwork, and features like 1st person mode; walking around and getting into the dronecar, like in GTA, as well as the same perspective view of the dronecar so that the camera is not locked on to it, but it’s more fluid, like so:

Before I start a new thread, is there anyway to prevent the following?

You can achieve this by using the first person or third person example projects. Alternatively, you can also use the camera orbit example project.

This is because the setup of the collision component.

If you change the setup like below, the problem is solved.

Also I advice to set the value of the Camera Clip Far of the editor settings a bit higher to prevent your models are disappearing in the black background while you working in the editor.

1 Like

The reason why your drone loses control also has to do with this. I’ve seen you haven’t modified all your scripts yet. The scripts drcBackLeft.js and drcBackRight.js need to be improved. Since you are now using rotateLocal you should probably also use getLocalEulerAngles instead of getEulerAngles. However, the code below seems to start the problem.

image

1 Like

Firstly, I would just like to thank you for all your patience with me and attentiveness to this project!

Secondly, awesome! You managed to fix, like, 3 of the problems I was having. I believe the reason I didn’t modify the remaining scripts is because they conflict with each other. For instance, the code works here because “x<=0” applies to both instances of the “else if” statement with respect to pc.KEY_S, and pc.KEY_A

drcFrontLeftjs

But not here, because the “else if” statement for x is “<” and “>” for pc.KEY_S and pc.KEY_A. respectively.

drcBackLeft

So, I left it the way it was originally. I don’t know if there is a way around this.

1 Like

I was also wondering how to fix the following:

Basically, once the dronecar “yaws”, or rotates about its axis, 180 degrees: the WASD controls don’t follow, if that makes sense.

After the dronecar rotates 180 degrees, ‘W’ no longer makes it go relatively forward, and ‘S’ no longer makes it go relatively backward with respect to the front and rear of the drone car respectively.

Is there a localApplyImpulse of some sort that applies a force relative to the axis of the dronecar rather than relative to the axis of the map level?

In the drcBackRight.js script the W and A key are conflicting and in the drcBackLeft.js script the W and D key are conflicting. You have to combine these keys to one if statement.

1 Like