Orbital cannon jitters while following/facing mouse position

Hello everyone, I have a simple scenario where a flying 2d dynamic Rigibody “Spaceship” gameobject floating in space using addforce and addtorque (translation and rotation). A child (of “Spaceship”) gameobject “Cannon” that orbits around the spaceship relative to the current mouse position. The cannon can only move between object x and y (limited angle) and is always facing the mouse position while in range. See the picture below for more details:

Everything was ok. But after implementing a camera script that follows the spaceship (in LateUpdate and it´s attached to the main camera), the orbital cannon starts to jitter while the ship is moving. My guess is that the mouse position (ScreenToWorldPoint) is now changing constantly while the camera is moving and the orbital cannon is trying to follow and face the position. Probably that´s what´s causing this weird jitter motion!! You can have a look at the OrbitalCannon controller. The cannon object does not have a 2d Rigibody component attached to it. Only the spaceship does.

using UnityEngine;

public class OrbitalCannonController : MonoBehaviour
{
    public float SlidingSpeed = 1;
    private Transform orbitalCannon;
    private float orbitRadius;
    private float currentAngle;
    private Vector3 centerToMouseVector; // vector from Ship center to the world mouse position
    private Vector3 nexPosition;

   void Awake()
    {
        orbitalCannon = this.transform; // cach transform.
        orbitRadius = Vector2.Distance(Ship.position, orbitalCannon.position);
        centerToMouseVector = orbitalCannon.position - Ship.position;
    }

    private void Update()
    {
        //get the vector between mouse position (projected in game world) and the center of the circle (Ship)
        centerToMouseVector = Camera.main.ScreenToWorldPoint(Input.mousePosition) - Ship.position;
        centerToMouseVector.z = 0; // zero z axis since we are using 2d

        float x = Vector2.SignedAngle(centerToMouseVector, Ship.up);
        if ((x > 20 && x < 70) || centerToMouseVector.magnitude < orbitRadius) return;

        // we normalize the new direction so you can make it equal to the radius length
        // then we add it to the circle (aka Ship) center position
        nexPosition = Ship.position + (orbitRadius * centerToMouseVector.normalized);

        // get the correct angle between the circle (Ship) and mouse position in the world space
        currentAngle = Mathf.Atan2(centerToMouseVector.y, centerToMouseVector.x) * Mathf.Rad2Deg;

        orbitalCannon.position = Vector3.MoveTowards(orbitalCannon.position, nexPosition, Time.deltaTime * SlidingSpeed); // lerp cannon to the position
        orbitalCannon.rotation = Quaternion.Euler(new Vector3(0, 0, currentAngle - 90)); // rotate orbital cannon to face the mouse.
    }
}

Can anyone help me solve this problem? What am I doing wrong here? And if there is any better/optimized approach to achieve the same control, I would love to know it (using rotateAround() or something similar) because I believe that the current implementation is a performance overkill.

Try to put the calculation stuff in FixedUpdate(). If it doesn’t work change the camera’s script’s calculation to Update() or FixedUpdate().

This is what every method do:

  • Update runs every frame, just before LateUpdate.

  • LateUpdate runs just after Update does, and runs just before the Camera renders.

  • FixedUpdate runs on a constant timing, and by default as close as possible to the physics calculation.

Let me know if it worked.