Firing a projectile, keeping a static angle (2D Top-Down Shooter)

Hey,

I’m currently working on a game in which the player fires projectiles at enemies via a cannon on a pivot at the bottom of the screen the angles the cannon can go from are 0-89 and 360-271. However I can’t seem the get the projectiles working after they are being instantiated, they always seem to fly off in the wrong direction. I’ve puzzled over this for numerous hours now so I thought I’d try and save the time and ask on here, many thanks to anybody who can help.

Script to spawn the projectiles

    using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour
{

    enum State
    {
        Unassigned,
        Rock,
        Paper,
        Scissors
    }

    private State state = State.Unassigned;

    public static int Score = 0;
    public static int Missed = 0;
    public static int Combo = 0;
    public static int TargetsHit = 0;
    public static int PlayerAsteroid = 0;

    public GameObject Rock;
    public GameObject Paper;
    public GameObject Scissors;

    GameObject playerRock;
    GameObject playerPaper;
    GameObject playerScissors;
    GameObject firePosition;
    
    Vector3 origPos, curMousePos;

    // Use this for initialization
    void Start()
	{
    }

    // Update is called once per frame
    void Update()
    {
      //  print(Time.deltaTime.ToString());
        if (Input.GetKeyDown("q") | Input.GetKeyDown("mouse 1"))
        {
            playerRock = GameObject.FindWithTag("Rock");
            playerPaper = GameObject.FindWithTag("Paper");
            playerScissors = GameObject.FindWithTag("Scissors");
            DestroyObject(playerPaper);
            DestroyObject(playerRock);
            DestroyObject(playerScissors);
            if (PlayerAsteroid > 0)
            {
                PlayerAsteroid--;
            }
        }

        // Dont use input axis use left and right makes it easier to check if its the right direction :)
        if ((gameObject.transform.localEulerAngles.z < 90) || (gameObject.transform.localEulerAngles.z > 270))
        {
            if (Input.GetKey(KeyCode.LeftArrow))
            {
                if (gameObject.transform.localEulerAngles.z < 89 || (gameObject.transform.localEulerAngles.z > 270))
                {
                    gameObject.transform.Rotate(0, 0, 1f); // Minus tiltAroundZ so it moves in the correct direction
                }
            }
            if (Input.GetKey(KeyCode.RightArrow))
            {
                if ((gameObject.transform.localEulerAngles.z > 271) || (gameObject.transform.localEulerAngles.z < 90))
                {
                    gameObject.transform.Rotate(0, 0, -1f);
                }
            }
        }

        if (Input.GetKeyUp("a"))
        {
            if (PlayerAsteroid >= 1) // Wait for until there are less than 5 enemies at one time.
            {
                Debug.Log("Play Sound");
            }
            else if (PlayerAsteroid < 1)
            {
                state = State.Rock;

                firePosition = GameObject.FindWithTag("FirePosition");
                Vector3 position = new Vector3(firePosition.transform.position.x, firePosition.transform.position.y, firePosition.transform.position.z);
                Instantiate(Rock, position, Quaternion.identity);
                PlayerAsteroid++;
            }
        }
        if (Input.GetKeyUp("s"))
        {
            if (PlayerAsteroid >= 1) // Wait for until there are less than 5 enemies at one time.
            {
                Debug.Log("Play Sound");
            }
            else if (PlayerAsteroid < 1)
            {
                state = State.Paper;

                firePosition = GameObject.FindWithTag("FirePosition");
                Vector3 position = new Vector3(firePosition.transform.position.x, firePosition.transform.position.y, firePosition.transform.position.z);
                Instantiate(Paper, position, Quaternion.identity);
                PlayerAsteroid++;
            }
        }
        if (Input.GetKeyUp("d"))
        {
            if (PlayerAsteroid >= 1)
            {
                Debug.Log("Play Sound");
            }
            else if (PlayerAsteroid < 1)
            {
                state = State.Scissors;

                firePosition = GameObject.FindWithTag("FirePosition");
                Vector3 position = new Vector3(firePosition.transform.position.x, firePosition.transform.position.y, firePosition.transform.position.z);
                Instantiate(Scissors, position, Quaternion.identity);
                PlayerAsteroid++;
            }
        }

    }

    void OnGUI()
    {
        GUI.Label(new Rect(10, 10, 120, 20), "Score:" + PlayerController.Score.ToString());
        GUI.Label(new Rect(10, 30, 60, 20), "Missed:" + PlayerController.Missed.ToString());
        GUI.Label(new Rect(10, 50, 120, 20), "Combo:" + PlayerController.Combo.ToString());
        GUI.Label(new Rect(10, 70, 120, 20), "State:" + state);
    }
}

Script to control projectiles

using UnityEngine;
using System.Collections;

public class PlayerAsteroid : MonoBehaviour {

    GameObject missileTrajectory;

	// Use this for initialization
	void Start () 
    {
        missileTrajectory = GameObject.FindWithTag("Player");
        print("X Pos:" + missileTrajectory.transform.position.x.ToString());
        print("Y Pos:" + missileTrajectory.transform.position.y.ToString());
        print("Z Pos:" + missileTrajectory.transform.position.z.ToString());
        print("X Rot:" + missileTrajectory.transform.rotation.x.ToString());
        print("Y Rot:" + missileTrajectory.transform.rotation.y.ToString());
        print("Z Rot:" + missileTrajectory.transform.rotation.z.ToString());
        rigidbody.AddRelativeForce(10, 0, 0);
	}
	
	// Update is called once per frame
	void Update () 
    {
            rigidbody.AddForce(transform.position.x, -transform.position.y, 0);

        if (transform.position.y <= -5.3f || transform.position.x <= -6.1f || transform.position.x >= 6.5f || transform.position.y >= 7f)
        {
            PlayerController.Missed++;
            PlayerController.Combo = 0;
            PlayerController.PlayerAsteroid--;
            Destroy(gameObject);
        }
	}
}

Ok, so all that code is pretty tl;dr. Also, I’m not sure what kind of behavior you’re looking for. This line:

 rigidbody.AddForce(transform.position.x, -transform.position.y, 0);

adds a force to the projectile based on its position. So, for example, a projectile at the origin will not have any force applied to it, while projectiles far from the origin
will have potentially massive forces. Applying a force inversely of Y position will make
the projectiles tend to stay on or very near the X axis, on which they will accelerate
exponentially due to the X component of the force increasing with X distance. I don’t know exactly what you’re trying to do, but if you want projectiles to just move in a given direction, this is not the way to do it. A very easy way to just get a rigidbody to move in a given direction (one line of code, literally) is with Rigidbody.MovePosition(), like so (taken directly from script reference):

private Vector3 speed = new Vector3(3, 0, 0); //or whatever
void FixedUpdate() {
    rigidbody.MovePosition(rigidbody.position + speed * Time.fixedDeltaTime);
}

To get the projectile to move in the direction the cannon is facing, get the speed like so:

float howFastYouWantItToGo = [whatever];
Vector3 vel = transform.forward.normalized * howFastYouWantItToGo;

This gets the “forward” direction of the cannon, makes it length 1, and then stretches it by whatever value you give it.

Also, when moving rigidbodies, you should use the FixedUpdate() method instead of the Update() method; otherwise, things glitch out and get weird.

Good luck; hope this helps!