Creating a MegaMan style game, writing bullet script, need help moving it across screen.

So I’m creating a Mega Man style game, which will have the regular Mega Buster (standard bullet) and later on 8 unique weapons. As such, on my PlayerController script I have:

public GameObject[] weapons = new GameObject[9];

,at the beginning. I then have a method:

int ChooseWeapon ()
	{
		return 0;
	}

which currenly returns 0, because the only weapon in the game is that standard one that shoots a bullet. (I’ll later program a way to choose a different one). Then I have the following method to shoot.

void Shoot (int weapon)
	{
		if (Input.GetButtonDown ("Fire1")) {
			Instantiate (weapons [weapon], new Vector2 (trans.position.x, trans.position.y), Quaternion.identity);
		}

	}

,with trans being a transform. (Also need to spawn it a bit in front of the player, not right on top, but I’ll fix that later) Now I need help with the script that’s gonna be attached to the bullet prefab.

public float bulletSpeed;

	public Transform trans;

	void Start () 
	{
		trans = GetComponent<Transform> ();
	}
	
	void Update () 
	{
		trans.Translate (/*player x*/ * bulletSpeed, /*player y*/, 0);		
	}

What’s the best way to get the player’s position, or to say it’s traveling from the starting position where it’s instantiated.

Feel free to ask for more code, tough there isn’t much and thanks for the help in advance.

  • Don’t use Update(), it’s frame rate dependent, use the physic update FixedUpdate()instead.
  • Multiply your bullet speed by Time.deltaTime to convert from distance/second to distance/update.
  • Don’t use the player position when updating the bullet position, the player and bullet will move independently, use the current bullet transform.position instead.
  • You don’t need to use GetComponent<Transform>(), the transform is always available in the transform field of any class extending Component.
  • You also need to know if the bullet is going to the left or the right, you can store that in a public boolean property Direction for example, so can set it from you player script, and it won’t appear in the inspector.
  • You should not update the bullet transform position directly, but use Rigidbody2D.MovePosition() instead, so the collisions are handled properly. You will need to attach a RigidBody2D component to your bullet prefab (Body Type: Kinematic) and store it in a field like you did for the transform. (There is a rigidbody field but it’s deprecated). That field should be private, you don’t need to modify its value from outside of the bullet script.

So the bullet script should look like this:

  	public class MegaBusterBullet : MonoBehaviour {

		public float bulletSpeed;
		private Rigidbody2D rigidBody;

		public bool Direction {
			get;
			set;
		}

		public float MoveSpeed {
			get {
				return this.bulletSpeed * (this.Direction ? -1 : 1) * Time.deltaTime;
			}
		}

		private void Awake() {
			this.rigidBody = this.GetComponent<Rigidbody2D>();
		}

		private void FixedUpdate() {
			this.rigidBody.MovePosition(this.transform.position + new Vector3(this.MoveSpeed, 0f, 0f));
		}

	}
  • When you instantiate your bullet in your player script, don’t forget to set its direction to be the same as the player’s current direction.

The player script should look like this:

	public class Player : MonoBehaviour {

		private const float BULLET_SPAWN_OFFSET = 0.5f;

		[SerializeField]
		private GameObject[] weapons = new GameObject[9];

		public bool Direction {
			get;
			private set;
		}

		public int EquipedWeapon {
			get;
			private set;
		}

		private void Update() {
			if(Input.GetButtonDown("Fire1")) {
				this.Shoot();
			}

			if(Input.GetButtonDown("SwitchWeapon0")) {
				this.EquipedWeapon = 0;
			}
		}

		private void Shoot() {
			Vector3 spawnLocation = this.transform.position + new Vector3(BULLET_SPAWN_OFFSET * (this.Direction ? -1 : 1), 0f, 0f);
			MegaBusterBullet bullet = Instantiate(this.weapons[this.EquipedWeapon], spawnLocation, Quaternion.identity).GetComponent<MegaBusterBullet>();
			bullet.Direction = this.Direction;
		}

	}

Hope this helps. :slight_smile:

@SeigneurNecron Seems to work mostly fine, but the bullets still will only shoot in one direction.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class PlayerController : MonoBehaviour
{


	public float jumpLimit;
	public float jumpPower;
	public float speed;
	public float step;
	public float fireRate;
	public float nextFire;
	public float bulletSpeed;

	private bool facingRight = true;
	private bool isOnGround = true;

	private const float BULLET_SPAWN_OFFSET = 0.5f;

	public Animator anim;
	public GameObject[] weapons = new GameObject[9];
	public Rigidbody2D rb;
	public Transform trans;

	public bool FacingRight {
		get;
		private set;
	}

	void Awake ()
	{
		anim = GetComponent<Animator> ();
		rb = GetComponent<Rigidbody2D> ();
		trans = GetComponent<Transform> ();
	}

	void Update ()
	{
		MovePlayer ();
		Jump ();
		Shoot (ChooseWeapon ());
	}

	void MovePlayer ()
	{
		float translate = Input.GetAxisRaw ("Horizontal") * speed * Time.deltaTime;
		trans.Translate (translate, 0, 0);
		if (translate > 0) {
			anim.SetTrigger ("PlayerRunRight");
			if (!facingRight)
				Flip ();
		}
		if (translate < 0) {
			anim.SetTrigger ("PlayerRunLeft");
			if (facingRight)
				Flip ();
		}
		if (translate == 0)
			anim.SetTrigger ("PlayerStop");
	}

	void Jump ()
	{
		if (Input.GetButtonDown ("Jump") && isOnGround) {
			rb.AddForce (new Vector2 (0, jumpPower), ForceMode2D.Impulse);
		}			
	}

	void Flip ()
	{
		facingRight = !facingRight;
		Vector3 theScale = transform.localScale;
		theScale.x *= -1;
		transform.localScale = theScale;
	}

//both of these are wrong I know, but I’m a newbie, this can //be saved for later, just testing out character controll on a flat //surface for now

	void OnCollisionEnter2D ()
	{
		isOnGround = true;
	}

	void OnCollisionExit2D ()
	{
		isOnGround = false;
	}

	int ChooseWeapon ()
	{
		return 0;
	}

	void Shoot (int weapon)
	{
		if (Input.GetButtonDown ("Fire1")) {
			Vector3 spawnLocation = this.transform.position + new Vector3(BULLET_SPAWN_OFFSET * (this.facingRight ? -1 : 1), 0f, 0f);
			MegaBusterBullet bullet = Instantiate(this.weapons[this.ChooseWeapon()], spawnLocation, Quaternion.identity).GetComponent<MegaBusterBullet>();
			bullet.FacingRight = this.FacingRight;
		}

	}
}

With the bullet script being

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MegaBusterBullet : MonoBehaviour {

	public float bulletSpeed;
	private Rigidbody2D rigidBody;

	public bool FacingRight {
		get;
		set;
	}

	public float MoveSpeed {
		get 
		{
			return this.bulletSpeed * (this.FacingRight ? -1 : 1) * Time.deltaTime;
		}
	}

	private void Awake() {
		this.rigidBody = this.GetComponent<Rigidbody2D>();
	}

	private void FixedUpdate() {
		this.rigidBody.MovePosition(this.transform.position + new Vector3(this.MoveSpeed, 0f, 0f));
	}

}

Currently no matter what direction I’m turned to (I’m flipping my character well, so facingRight must be working) I’m shooting my bullets to the right. Can’t shoot left.