Welcome to the first tutorial as I develop Project Hasseu – programming a machine gun or projectile launcher, probably the core mechanic in shoot-em-up games. Below you see the the YouTube video to watch this tutorial, if not interested, the text based one is below!
Two pull this off you need two objects, the projectile (bullet) and the firing source (person, tower, etc.).
Bullet:
You first will need to attach a rigidbody to the bullet and then make it a prefab.
using System.Collections; using System.Collections.Generic; using UnityEngine; public class BulletController : MonoBehaviour { public float speed = 160f; public float bullet_spread = 0.01f; public Vector2 trajectory = new Vector2(0f,1f); private Rigidbody2D rb; private float distanceTravelled = 0f; public float maxDistance = 100f; // Start is called before the first frame update void Start() { // get rigidbody reference rb = this.GetComponent<Rigidbody2D>(); } void FixedUpdate() { // get current position Vector2 currentPosition = rb.position; // move bullet by trajectory by speed and deltaTime rb.MovePosition(new Vector2(currentPosition.x + speed * trajectory.x * Time.deltaTime, currentPosition.y + speed * trajectory.y * Time.deltaTime)); // running sum of distance travelled and destory if more than max distance distanceTravelled += speed * Time.deltaTime; if (distanceTravelled > maxDistance) { Destroy(this.gameObject); } } public void SetTrajectory(Vector2 trajectory) { // normalize so speed is not a function of trajectory magnitude trajectory.Normalize(); // give some random spreading to bullet spray trajectory.x += Random.Range(bullet_spread, -1f * bullet_spread); trajectory.y += Random.Range(bullet_spread, -1f * bullet_spread); // saving trajectory to object this.trajectory = trajectory; // altering starting position of bullet with little magic to increase visual density (e.g. bullets not rendering at same distance each frame) float random = Random.Range(1f, 0f); this.transform.position += new Vector3(random * trajectory.x, random * trajectory.y, 0f); // converting trajectory into rotation angle and setting float angle = Mathf.Atan2(trajectory.y,trajectory.x)*360f/(2f*Mathf.PI)-90f; this.transform.rotation = Quaternion.Euler(0f,0f,angle); } }
Player:
For the player I have attached a rigidbody and some code to move the player, but the core functionality is to get mouse input in the Update frame and execute the FireProjectile function.
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerController : MonoBehaviour { // reference to bullet prefab public GameObject bulletPreFab; // for movement variables private float horizontalInput; private float verticalInput; private float speed = 10f; private Rigidbody2D rigidbody; void Start() { rigidbody = this.GetComponent<Rigidbody2D>(); } void Update() { // when mouse left button is down if (Input.GetMouseButton(0)) { FireProjectile(); } horizontalInput = Input.GetAxis("Horizontal"); verticalInput = Input.GetAxis("Vertical"); } void FixedUpdate() { rigidbody.MovePosition(rigidbody.position += new Vector2(speed * horizontalInput * Time.deltaTime, speed * verticalInput * Time.deltaTime)); } private void FireProjectile() { // create the new bullet GameObject newObject = Instantiate(bulletPreFab); // setting starting position of bullet at character newObject.transform.position = this.transform.position; // direction to shoot (mouse coordinates - player) Vector2 trajectory = (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition) - (Vector2)this.transform.position; // give trajectory to object newObject.GetComponent<BulletController>().SetTrajectory(trajectory); } }