- Home /
Shooting when raycast hits player with delay between shots, Coroutine not working as I intend
Hello I am working on the start of my first game, wave shooter where enemies will be instantiated come to a certain distance stop, then start shooting once the player is within range. To get this started I am having the enemy look at the player then use a raycast to identify when the gun is pointed at the player, within the right distance, and shoot within different intervals.
I am thinking their may be a better way to do this, possibly when the ray collides with the "player" tag I enable a script that shoots using invoke repeating to shoot, disabling the script when the player is no longer within the raycast. Maybe that's not better I don't know. However, the approach I have taken is to start a Coroutine when the raycast intersects with the player that will fire projectiles at the player.
The problem I am coming across is that there is no real delay between when the raycast intersects and when the bullets start firing, in addition the bullets are firing 2 at a time or more and I am not really sure why. Would someone be able to take a look at my code and video as my example and help explain what I am doing wrong. If there is a better way to do this please let me know. Video: https://youtu.be/kRiRQfI1lrU
Code:
public Rigidbody rocketPrefab;
public Transform barrelEnd;
public int speed = 10;
public float rayDistance = 2;
public bool rayHit;
void FixedUpdate()
{
RaycastHit hit;
Vector3 forward = transform.TransformDirection(Vector3.forward) * rayDistance;
Debug.DrawRay(transform.position, forward, Color.green);
if (Physics.Raycast(transform.position, forward, out hit, rayDistance))
{
if (hit.collider.tag == "Player")
{
StartCoroutine(ShootWeapon(2f));
rayHit = true;
Debug.Log("Raycast hit a player");
}
else if (hit.collider.tag != "Player")
{
rayHit = false;
StopCoroutine(ShootWeapon(0));
Debug.Log("Stop shooting");
}
}
}
private IEnumerator ShootWeapon(float waitTime)
{
Rigidbody rocketInstance;
rocketInstance = Instantiate(rocketPrefab, barrelEnd.position, barrelEnd.rotation) as Rigidbody;
rocketInstance.AddForce(barrelEnd.forward * speed);
yield return new WaitForSeconds(4f);
}
As a side note my bool isn't enabling when raycast hits. Any hints here would help, but not my main concern.
Answer by SuperScience · Oct 23, 2018 at 04:47 PM
Hi Church,
I hope you don't mind if I really change a lot of your stuff here...
I recommend you use Update for player interactions. FixedUpdate is really for physics.
You will only ever hit this line : else if (hit.collider.tag != "Player") ... if there is a collision that is not a player. That might be why your bool isn't being set false.
You should try to use the particle system rather than what you are doing here. The particle system is pretty robust, and you can emit mesh particles like rockets as well as traditional particles.
Also... it looks to me that you are calculating forward, which should be unnecessary.
private void Update() {
RaycastHit hit;
// rayDistance is the look distance,
// transform.forward is forward relative to this object's transform
if(Physics.Raycast(transform.position, transform.forward, out hit, rayDistance){
// collision detected
if(hit.collider.tag == Player){
// we have a collision, and it is a player
getComponent<ParticleSystem>().Play();
}else{
// we have a collision, but it is not a player
}
}else{
// no collision at all
}
}
So basically, you can make the particle system do everything you need here. Drop the mesh and texture into the particle renderer, give it an initial velocity, and set the collisions to the world space. Set the emission to 1 and make it so that it doesn't repeat. Set PlayOnAwake to false. And you should, whenever Play() is pressed, emit 1 particle of type rocket. You can even assign your explosion animation in the emitter which will trigger automatically upon death.
For targets, I think its "OnParticleCollision(Emitter)" or something like that. But basically you can query the thing that emitted to calculate damage, and this way you can use the same mechanism for bullets, rockets, shrapnel ... anything, really.
Hey @SuperScience I appreciate the feedback on your previous comment, I am not too familiar with the Particle system and am about to start some tutorials on it. If this is an ignorant question just let me know and I will continue to research. From the particle system I have seen in the past was used for effects like fire and smoke on an object rather than instantiating a bullet/rocket to shoot at a player/enemy. So I didn't think I could use it in the context of shooting a projectile.
Also one thing I left out was the projectile I am shooting at the player will reflect back at the enemy when the players shield blocks the projectile. So again not sure if particle system will do this, I already have the script setup for this on the projectile and is working.
Anyway I am off to learn about the particle system I appreciate the help you have given me on my first post in the help section. :)
Hi Church,
The particle system will do everything that you need. It is pretty robust. Not only can you make it instantiate your rocket, have it fire in a line (or a cone if you want to make the accuracy imperfect), even apply gravity or other forces... you can put a collider on the rocket and have it transmit collision data to the target.
You can also set up sub-emitters for your muzzle flash and explosion at the end.
It really is the best way to do projectiles because so much is built-in and handled for you.