0
\$\begingroup\$

I am trying to clone the game "Flip the Gun" as an exercise.

Here is the behaviour I have so far.

And here is the code I am using:

if (Input.GetKeyDown(KeyCode.Space))
{
    rigidbody2D.AddForceAtPosition(
                transform.position-recoilPoint.transform.position * recoilForce,
                recoilPoint.position,
                ForceMode2D.Impulse
    );
}

As you can see in the video, the gun is moving too fast and rotating too fast. It seems out of control. I am not sure if the way of adding force to the gun is correct or not.

Thank DMGregory for editing the question for me. I am new to this family so that helped a lot. :)

\$\endgroup\$
1
  • 2
    \$\begingroup\$ How does the current behaviour of this code differ from what you want? Explain in words what should be different. \$\endgroup\$ – DMGregory Mar 17 at 17:37
1
\$\begingroup\$

The default rigidbody.AddForce applies the force facing the center of mass of your rigidbody, so it will never directly cause any rotation. But there is also the method rigidbody.AddForceAtPosition(Vector3 force, Vector3 position, ForceMode mode). This method can be used to apply forces to an object which are off-center and thus will result in a mix of rotation and velocity, depending on how far off-center it is.

A good way to use this would be to create a childObject to your gun which represents the point where you want the force to act and then use the position and direction of that object as input for AddForceAtPosition. Here is an (untested!) example script. This script uses a 3d Rigidbody. For a game with 2d physics, replace Rigidbody with Rigidbody2D:

[RequireComponent(typeof(Rigidbody))]
class GunRecoil : MonoBehaviour {
    
    [SerializeField] private Transform recoilPoint;
    [SerializeField] private float recoilForce = 10.0f;
    private Rigidbody myRigidbody; 

    private Start() {
        myRigidbody = GetComponent<Rigidbody>();
        if (recoilPoint == null) {
            Debug.LogWarning("You forgot to assign the Recoil Point in the inspector!");
        }
    }

    private void FixedUpdate() {
        if(Input.GetButtonDown(KeyCode.space)) {
            myRigidbody.AddForceAtPosition(
                recoilPoint.forward * recoilForce,
                recoilPoint.position,
                ForceMode.Impulse
            );
        }
    }
}
\$\endgroup\$
3
  • \$\begingroup\$ thank you for helping me! I tried your code and the result is like in the video i just uploaded and added to the question. Please check. :) \$\endgroup\$ – Frank Sun Mar 17 at 17:19
  • \$\begingroup\$ @FrankSun if Philipp's answer helped, remember to click the check mark so people know that this answer is effective. \$\endgroup\$ – OKprogrammer Mar 17 at 19:39
  • \$\begingroup\$ @FrankSun The documentation says that the force point is the point in world coordinates, so you shouldn't have to subtract it from the position of the parent. \$\endgroup\$ – Philipp Mar 17 at 22:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.