This is my first project in Unity and I am trying to create a simple FPS game. My problem is that no matter what I try, my rigidbody bullets won’t spawn at the designated object but instead, somewhere bellow (relative to the gun). Here is the shooting script I created…
public GameObject Spawn;
public GameObject BulletPrefab;
public GameObject Sound;
public GameObject Gun;
public ParticleSystem Emitter;
public Light GunLight;
public float EmissionTime;
public float Recoil;
public float BulletImpulse;
public Camera cam1;
public Camera cam2;
float timer;
void Start () {
Emitter.enableEmission = false;
GunLight.enabled = false;
}
void Update () {
if (Input.GetButtonDown("Fire1") && Emitter.enableEmission == false && !Input.GetButton("Fire3")){
timer = 0;
GameObject newbullet = (GameObject)Instantiate(BulletPrefab,Spawn.transform.position,Spawn.transform.rotation);
Instantiate(Sound,transform.position,Camera.main.transform.rotation);
newbullet.rigidbody.AddForce(newbullet.rigidbody.transform.forward * BulletImpulse,ForceMode.Impulse);
//newbullet.transform.position = new Vector3(Spawn.transform.position.x,Spawn.transform.position.y,Spawn.transform.position.z);
Emitter.enableEmission = true;
GunLight.enabled = true;
}
if (Emitter.enableEmission == true){
timer += 80*Time.deltaTime;
if (timer > EmissionTime){
Emitter.enableEmission = false;
GunLight.enabled = false;
}
}
}
// attach this script with your gun and put an empty game object as a child of gun which work as spawn point of bullet keep some distance between gun barrel and empty game object
public class AutoFire : MonoBehaviour {
public float frequency = 10;
public float coneAngele = 1.0f;
public bool firing = false;
public float hitSoundVolume = 5f;
public GameObject muzzleFlash;
public AudioClip soundHit;
private float _lastFireTime = -1;
private RaycastHit _hitInfo;
private Quaternion _coneRandomRotation;
private Vector3 _force;
private GameObject _bullet;
private Transform _spawnPoint;
RaycastHit hitInfo;
void Start () {
if(muzzleFlash) muzzleFlash.active = false;
_force = new Vector3(0,0,0);
_bullet=Resources.Load("Prefabs/bullet", typeof(GameObject))as GameObject;
if(!_bullet){
Debug.LogError("keep bullet prefab in Resources/Prefabs/bullet");
}
foreach(Transform tr in transform){
if(tr){
_spawnPoint=tr;
}
}
}
// Update is called once per frame
void Update () {
if (firing) {
if (Time.time > _lastFireTime + 1 / frequency) {
//coneRandomRotation= Quaternion.Euler (Random.Range(-coneAngele, coneAngele), Random.Range(-coneAngele, coneAngele),0);
_coneRandomRotation = Quaternion.Euler(0, 0, 0);
GameObject go= Instantiate(_bullet,_spawnPoint.position,Quaternion.Euler(Vector3.zero)) as GameObject;
SimpleBulletOrMissile bulletOrMissile = go.GetComponent<SimpleBulletOrMissile>();
_lastFireTime = Time.time;
Physics.Raycast (go.transform.position, go.transform.up,out _hitInfo,Mathf.Infinity,-5);
if (_hitInfo.transform)
{
print(_hitInfo.transform.tag+"hitted");
Health targetHealth = _hitInfo.transform.GetComponent<Health>();
if (targetHealth)
{
//kill or health damage of target
}
if (_hitInfo.rigidbody)
{
//if want to apply force on enemy
hitInfo.rigidbody.AddForceAtPosition(_force, hitInfo.point, ForceMode.Impulse);
}
AudioSource.PlayClipAtPoint(soundHit, _hitInfo.point, hitSoundVolume);
bulletOrMissile.dist = _hitInfo.distance;
}
else {
bulletOrMissile.dist = 50;
}
}
}
if(Input.GetMouseButton(0)){
OnStartFire();
}
if(Input.GetMouseButtonUp(0)){
OnStopFire();
}
}
void OnStartFire() {
if (Time.timeScale == 0)
return;
firing = true;
if(muzzleFlash) muzzleFlash.active = true;
if (audio) audio.Play();
}
void OnStopFire() {
firing = false;
if(muzzleFlash) muzzleFlash.active = false;
if (audio) audio.Stop();
}
//attach this script with bullet
public class SimpleBulletOrMissile : MonoBehaviour {
public float speed = 10; public float lifeTime = 0.5f; public float dist = 100;
private float _spawnTime = 0.0f;
private Transform _tr;
// Use this for initialization
void OnEnable () {
_tr = transform;
_spawnTime = Time.time;
}
// Update is called once per frame
void Update () {
_tr.position += _tr.forward * speed * Time.deltaTime;
dist -= speed * Time.deltaTime;
if (Time.deltaTime > _spawnTime + lifeTime || dist < 0) {
// print("Destroy form bullet");
Destroy(gameObject);
}
}
The bullets have no way of knowing where to come out of unless you tell them. In your code, this line (cut down) tells the bullets where they should appear:
Spawn.transform.position is just a fancy way to say transform.position, which is the gun’s position – where the little arrow-cluster is centered. That’s probably somewhere at the base of the whole thing, not at the tip.
All you have to do is tell the bullet to spawn at the tip. As citizenrafiq mentions, the most obvious way is to mark the tip with an empty, as a child to the gun. Suppose the empty is named “tip.” Add a line to look it up:
Vector3 tip = transform.Find("tip"); // new line
// your same spawn, but tell bullet to appear where "tip" is:
GameObject newbullet = Instantiate( ... , tip , ...);