Deviation of projectile on shooting.

Hi guys, please help.
Really simple thing, but don’t understand how Unity behaves.
I have object which represent Cannon, with has two child objects: Launcher is used for set up initial position of projectile and Target where to shoot.
And there is prefab Projectile.

All I want to do is just to shoot straight through turret wherever I rotate the Cannon.

public class Cannon : MonoBehaviour
{
    [SerializeField]
    private GameObject ammoPrefab;
    [SerializeField]
    private float rotationSpeed = 5;
    [SerializeField]
    private Transform launcher;
    [SerializeField]
    private Transform target;

    private MoveState state = MoveState.Idle;

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            state = MoveState.Left;
        }
        else if (Input.GetKeyDown(KeyCode.D))
        {
            state = MoveState.Right;
        }

        if (Input.GetKeyDown(KeyCode.W))
        {
            state = MoveState.Up;
        }
        else if (Input.GetKeyDown(KeyCode.S))
        {
            state = MoveState.Down;
        }

        if (Input.GetKeyUp(KeyCode.A) || Input.GetKeyUp(KeyCode.D)
            || Input.GetKeyUp(KeyCode.W) || Input.GetKeyUp(KeyCode.S))
        {
            state = MoveState.Idle;
        }

        if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.L))
        {
            Fire();
        }
    }

    private void FixedUpdate()
    {
        if (state != MoveState.Idle)
        {
            SetPosition();
        }
    }

    private void SetPosition()
    {
        Vector3 rotation = transform.eulerAngles;

        switch (state)
        {
            case MoveState.Left:
                if (rotation.y > 170)
                {
                    rotation.y -= rotationSpeed * Time.fixedDeltaTime;
                }
                break;
            case MoveState.Right:
                if (rotation.y < 190)
                {
                    rotation.y += rotationSpeed * Time.fixedDeltaTime;
                }
                break;
            case MoveState.Up:
                if (rotation.x < 10)
                {
                    rotation.x += rotationSpeed * Time.fixedDeltaTime;
                }
                break;
            case MoveState.Down:
                if (rotation.x > 0)
                {
                    rotation.x -= rotationSpeed * Time.fixedDeltaTime;
                    // reset if goes below 0 degree
                    if (rotation.x > 10)
                    {
                        rotation.x = 0.0f;
                    }
                }
                break;
        }

        transform.eulerAngles = rotation;
    }

    private void Fire()
    {
        GameObject ammo = Instantiate(ammoPrefab);
        ammo.transform.position = launcher.position;
        Projectile ammoScript = ammo.GetComponent<Projectile>();

        Debug.DrawLine(launcher.position, target.position, Color.red, 5.0f);

        StartCoroutine(ammoScript.TravelTo(target.position));
    }

}
public class Projectile : MonoBehaviour
{
    [SerializeField]
    private float duration = 2.5f;

    public IEnumerator TravelTo(Vector3 endPosition)
    {
        float percentComplete = 0.0f;

        while (percentComplete < 1.0f)
        {
            transform.position = Vector3.Lerp(transform.position, endPosition, percentComplete);
            percentComplete += Time.deltaTime / duration;
            yield return null;
        }

        Destroy(gameObject, 0.1f);
    }

}

When I rotate the Cannon child objects also rotate, but when shooting the projectile start from different position depending on Cannon rotation.

Shooting on initial position of Cannon.


It’s good.

But after rotation

It’s very bad.

One possibility is that you don’t have uniform scaling on your objects.

Make sure everything going down to the positional anchor points is scale (1,1,1)

If you need to change the scale of visual objects, make them separate leaf objects below an “armature” of uniform scaled GameObjects that hold it all together.

1 Like

I can’t scale Cannon to 1,1,1, it becames to small. I set them all to (10, 10, 10), still have the same issue.

6658945--761443--Screen Shot 2020-12-26 at 01.27.52.png 6658945--761446--Screen Shot 2020-12-26 at 01.28.04.png 6658945--761449--Screen Shot 2020-12-26 at 01.28.16.png

I noticed that when I rotate Launcher in the Inspector to the same value as Cannon it seems work.

But I wasn’t able to set it programmatically.
launcher.rotation = transform.rotation;

Again, to have sub-objects behave properly, you almost certainly should keep ALL objects except leaf objects (those with no other children) at unity scaling (1,1,1)

This likely means reorganizing your current hierarchy to comply with this requirement. If you choose not to then you will likely have to put in fudge scale factors to “counter scale” every other object that goes underneath a scaled object, and that is NOT a route you want to go down, trust me. Insanity lies that way.

For instance, see this hierarchy:

6658969--761452--scaling.png

For more on the above, which is turret tracking / aiming code, see this post:

Scaling didn’t help.

And neither does that response! Perfect.

To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

Doing this should help you answer these types of questions:

  • is this code even running? which parts are running? how often does it run?
  • what are the values of the variables involved? Are they initialized?

Knowing this information will help you reason about the behavior you are seeing.

Probably I didn’t understand correctly but I changed the scale of the models in graphic app (Blender in my case), and after that updated the models in Unity. So, after setting scales in Unity to (1,1,1) the size was what I needed and it worked as expected. Thanks.