How do I make a shooting system that shoots out 3 bullets in a fan-like shape? I’ve got a MultipleShotSystem script in my Shotgun gameobject and I want to use this as a basis for all my other weapon that shoots multiple shots.
I’ve tried codes online but none of the code works for some reason. I know I have to use Quaternion to determine my angles but I’m not sure how to implement it on my bullet. Here’s the code I have so far:
using UnityEngine;
using System.Collections;
public class MultipleShotSystem : MonoBehaviour
{
public float fireRate;
public int bulletCount;
public GameObject bullet;
public GameObject hitParticle;
public LayerMask enemyLayer;
private float spreadAngle = 10f;
private float lastFire = 0f;
void Update()
{
Shoot();
}
void Shoot()
{
// Store anything that the ray hits in the enemyLayer here
//RaycastHit2D hit = Physics2D.Raycast(transform.position, transform.up, 100f, enemyLayer);
// Shooting code here
if (Input.GetKey(KeyCode.Space) && Time.time > fireRate + lastFire)
{
// Shoots 3 bullets at once
for (int i = 0; i < bulletCount; i++)
{
GameObject bulletClone = (GameObject)Instantiate(bullet, transform.position, transform.rotation);
Destroy(bulletClone, 1f);
lastFire = Time.time;
}
}
}
}
You can do a couple of things. You can take the transform.rotation and turn it into eularAngles. Or, create more bullets, and add a transform.Rotate(new Vector3(…,…,…));
When you said create more bullets and add a transform.Rotation, did you meant making 3 Instantiate(bullet) then specifying the different rotation for each of those bullet?
And for eulerAngles, I’m confused by that so can you explain how eulerAngles work? Thanks for helping by the way and sorry if I’m asking too much :S
EDIT: I kinda did make it work after a lot of trial and errors but there’s something that I’m not getting. Here’s the code:
using UnityEngine;
using System.Collections;
public class MultipleShotSystem : MonoBehaviour
{
public float fireRate;
public int bulletCount;
public GameObject bullet;
public GameObject hitParticle;
public LayerMask enemyLayer;
private float spreadAngle = 10f;
private float lastFire = 0f;
void Update()
{
Shoot();
}
void Shoot()
{
// Store anything that the ray hits in the enemyLayer here
//RaycastHit2D hit = Physics2D.Raycast(transform.position, transform.up, 100f, enemyLayer);
// Shooting code here
if (Input.GetKey(KeyCode.Space) && Time.time > fireRate + lastFire)
{
// Shoots 3 bullets at once
for (int i = 0; i < bulletCount; i++)
{
// Instantiate and rotates the bullet based on calculation: (i + 1) * spreadAngle
// So first bullet will have an angle of (0 + 1) * spreadAngle = 10, 2nd bullet = 20, 3rd bullet = 30
GameObject bulletClone = (GameObject)Instantiate(bullet, transform.position, Quaternion.Euler(0, 0, ((i + 1) * spreadAngle)));
Destroy(bulletClone, 1f);
lastFire = Time.time;
}
}
}
}
The code worked fine in making the bullet shoot in 3 different angles but it’s not shooting in the right direction :(. Here’s a GIF showing my problem (it’s not that good in quality but if you see closely, you can see how the bullet shoots in a direction way different than where my player is facing).
Here is what I was thinking, this method creates the bullet and applies a slight rotation based on the EularAngles after. You don’t want to rely on Eular too much, or you can get Gimble lock. But for this kind of stuff its harmless.
This applies a rotation “post” creation.
using UnityEngine;
using System.Collections;
public class MultipleShotSystem : MonoBehaviour
{
public float fireRate;
public int bulletCount;
public GameObject bullet;
public GameObject hitParticle;
public LayerMask enemyLayer;
private float spreadAngle = 10f;
private float lastFire = 0f;
void Update()
{
Shoot();
}
void Shoot()
{
// Shooting code here
if (Input.GetKey(KeyCode.Space) && Time.time > fireRate + lastFire)
{
CreateBullet(new Vector3(-5f, 0f, 0f));
CreateBullet(new Vector3(0f, 0f, 0f));
CreateBullet(new Vector3(5f, 0f, 0f));
lastFire = Time.time;
}
}
void CreateBullet(Vector3 offsetRotation)
{
var obj = (GameObject)Instantiate(bullet, transform.position, transform.rotation);
obj.transform.Rotate(offsetRotation);
Destroy(obj, 1f);
}
}
That’s probably the quickest and laziest way to do it.
This way you don’t even need to touch Quaternions. Which are not fun.
Oh wow, it worked like a charm! I did some tweaks to the code so I can use the bulletCount variable and I did it
The tweaked code (for those who needs it too):
using UnityEngine;
using System.Collections;
public class MultipleShotSystem : MonoBehaviour
{
public float fireRate;
public int bulletCount;
public float angle;
public GameObject bullet;
public GameObject hitParticle;
public LayerMask enemyLayer;
private float lastFire = 0f;
private float subtractOffset;
void Update()
{
Shoot();
}
void Shoot()
{
// Checks condition and assign subtractOffset a value based on bulletCount
switch (bulletCount)
{
case 3:
subtractOffset = 1f;
break;
case 4:
subtractOffset = 1.5f;
break;
case 5:
subtractOffset = 2f;
break;
}
// Shooting code here
if (Input.GetKey(KeyCode.Space) && Time.time > fireRate + lastFire)
{
// Shoots bullets with calculation: ((i - subtractOffset) * angle)
// 1st bullet's rotation is ((0 - 1) * 10) = -10, 2nd is 0, 3rd is 10
for (int i = 0; i < bulletCount; i++)
{
CreateBullet(new Vector3(0f, 0f, ((i - subtractOffset) * angle)));
}
lastFire = Time.time;
}
}
void CreateBullet(Vector3 offsetRotation)
{
GameObject bulletClone = (GameObject)Instantiate(bullet, transform.position, transform.rotation);
bulletClone.transform.Rotate(offsetRotation);
Destroy(bulletClone, 1f);
}
}
I’m using a switch statement to assign subtractOffset a value based on bulletCount with an increment of +0.5 everytime bulletCount’s value increased by 1. Is there a better way to do this with fewer lines of codes or is this the best way to do it?
Anyways, thanks for your help! You don’t know how much that means to me to fix this problem ;D