Parent rigidbody locks child rigidbody rotation (previously an input system question)

Hi, I have been trying to learn the new input system and have been running into a problem with my top down 2d shooter.

My gun rotates towards the mouse position and that works great until I use the attack action which then locks up the z rotation. I debug logged all the numbers and they are still being changed but the rotation is no longer being effected.

This is the rotation script

public class FlipAndPoint : MonoBehaviour
{
    [SerializeField]
    private PlayerInput playerInput;
    private Rigidbody2D rb;
    
    private Vector2 aimPosition;
    private InputAction mousePosition;
    private bool pointingRight = true;
    private SpriteRenderer sr;


    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        sr = GetComponent<SpriteRenderer>();
        mousePosition = playerInput.actions["AimPosition"];
    }

    // Update is called once per frame
    void Update()
    {
        aimPosition = Camera.main.ScreenToWorldPoint(mousePosition.ReadValue<Vector2>());
        Vector3 diff = aimPosition - rb.position;
            if (diff.x >= 0 && !pointingRight)
            {
                transform.localScale = new Vector3(1, 1, 1);
                pointingRight = true;
            }
            else if (diff.x < 0 && pointingRight)
            { 
                transform.localScale = new Vector3(1, -1, 1);
                pointingRight = false;
            }

        Vector2 lookDir = aimPosition - rb.position;
        float angle = Mathf.Atan2(lookDir.y, lookDir.x) * Mathf.Rad2Deg;// - 90f;
        rb.rotation = angle;
    }

    
}

Not that I think it effects it but this is the fire weapon script (seperate so that I can easily attach the roation script to any weapon)

public class RifleBehaviour : MonoBehaviour
{

    [SerializeField]
    private PlayerInput playerInput;

    //Inputs
    private InputAction fireAction;
    private InputAction reloadAction;

    public Transform firePoint;
    public GameObject normalBullet;

    public float fireRateAmount = 0.5f;
    private float fireRate;
    


    void Start()
    {
        fireAction = playerInput.actions["Attack"];
        reloadAction = playerInput.actions["Reload"];
    }

    void Update()
    {
        //Firerate
        fireRate -= 1f * Time.deltaTime;

        if (fireAction.IsPressed())
        {
            if(fireRate <= 0){
                Fire();
            }
        }
        if(reloadAction.IsPressed())
        {
            Reload();
        }

        
    }

    public void Fire()
        {
            fireRate = fireRateAmount;
            Instantiate(normalBullet, firePoint.position, firePoint.rotation);
        }



    public void Reload()
        {
            Debug.Log("reloadActioning!");
        }
}

Any help would be appriciated. I’ve tried changing things in and out of fixed update and change around how it rotates but that didn’t seem to help

It doesn’t look like a code problem given these scripts. But since you instantiate bullet, perhaps these are colliding with your player object and that may cause problems. Log the angle and the aimPosition.

Worth noting: while the fire or reload key is pressed, the Fire() and Reload() methods will run every Update! This may mean, you’ll run them 20 times over 20 consecutive frames even for a short tap. This may become a problem with Reload(), which also could run in the same frame as Fire().

For Reload() better check .wasJustPressed instead.

SpriteRenderer has flipX and flipY properties, prefer to use those over setting a negative scale.

I will look into it, but the rifle that instantiates/rotates doesn’t have a collider so I am not sure how it would affect it.

Thanks for the tips! Your constant replies of this forum have helped over the years of looking into my frequent issues!

Also, I tried this and it doesn’t work. Looked into the documentation and it doesn’t seem there is a method for that so I will look into it more.

Sorry it’s actually: WasPressedThisFrame()

No worries!

I took upon your idea of the instantiation and temporarily commenting it out fixes it, so it has to do with that.

Thanks a ton!

Fixed the bullet instantiate, but the real issue is now/always the player moving around causes the rifle to not rotate. Tried changing all the possible settings on rigid bodies and colliders to no avail. Gonna look into my movement script to see if that is causing it.

For anyone looking for an answer or having a similar problem (I might update the title to something more accurate to my issue). After lots of trouble shooting it has something to do with the fact that I am rotating my child and moving my parent using rigid bodies. So I changed my child script to use a transform.rotation = Quaternion.Euler and that seemed to fix it.

Still not entirely sure why I can’t rotate a child object with rigid body and move the parent with rigid body at the same time but I found a solution

Generally you never parent dynamic (non-Kinematic) Rigidbodies because it doesn’t make sense: if the parent moves, by Transform parenting rules the child moves too… but that child Rigidbody has momentum and velocity of its own, so who wins? You’ll get all kinds of issues.

NOTE: This does not apply to kinematic Rigidbodies, such as ones placed on child GameObjects for the purpose of sensing collisions or triggers. Since they’re kinematic, they not trying to move themselves, so the Transform parenting rules work correctly.

That makes sense.

Since both my parent and child were kinematic should they still have behaved the way they did? With conflicting rigidbody’s?

At this point I am just curious if it is a hard and fast rule to not move children using their rigidbody’s if their parents have it as well or if I was doing something wrong either in code or in inspector that would cause this to act oddly. Regardless, it is working now with the new way to rotate the child.

Well, they behaved as you noted, which surprised you. Mostly when this happens it is because of an actual mathematical reason. Very rarely the reason is spurious.

If you can replicate it by creating it afresh in another scene, you can take the behaviour as “that’s how it is.”

Since you have the code above, you can construct your own forensic experiments to get to the bottom of what might be going wrong. Parenting and rotation is often a source of misunderstandings simply because of the inherent complexity of 3D transform parenting.

Some of the deepest learnings I’ve had are from doing such forensics, but they do take time, time to theorize “how can I prove what is going on?”, time to dig up timing and process order information (either through debugging or the documentation), time to construction, debug and run the experiments, cross-check your results, etc.

At the end of the day, if that’s how it is, it might be time better spent just getting a new solution to work rather than undersatnding why the old solution fails.