- Home /
How can I make my prefab fire out at a random velocity every 2 secs
Hi guys, I'm a novice when it comes to writing scripts in any language. What I'm trying to do is fire a prefab I made (cannonball) out of a cannon every 2 seconds at a random velocity each time it fires. The cannon is supposed to fire once the scene loads. When the prohectile is fired it is going to hit a target and when it does, it is supposed to be teleported to the right side of the screen to be collected. Hope that wasn't too confusing. What I need help with is the random velocity every 2 seconds and when the projectile hits the target and gets transported. Here is my code thus far. To test if things worked I made it so the ball with the left mouse button. I want this changed obviously to the constant, every 2 seconds when the scene loads. #pragma strict
//Attach to empty object, in front of barrel
var projectile : Rigidbody; //The Bullet
var speed = 250; //Speed Of The Bullets
var fireRate = .5;//Time Delay Between Shots!
function Update()
{
InvokeRepeating("Fire",fireRate,0.3); //Shoot Delay
}
//function Fire()
{
if(Input.GetMouseButtonDown(0))
{
//audio.Play();
var gunShot : AudioClip;
var instantiatedProjectile : Rigidbody = Instantiate(projectile, transform.position, transform.rotation );
instantiatedProjectile.velocity = transform.TransformDirection( Vector3( 0, 0, speed ) );
audio.PlayOneShot(gunShot);
CancelInvoke();
}
}
@script RequireComponent(AudioSource)
Its probably something very little I have to do, knowing my luck. I just can't see it. Once again, I'm a noob at this stuff. I understand the code, but to put what I want to do into code is another thing. I'm scripting in JavaScript, I'm just starting to learn C#. Thanks a bunch!
For it to work with Get$$anonymous$$ouseButtonDown, I think you'd have to press the mouse button in the same frame as Fire() is called, which is pretty unlikely.
Is there a reason function Fire() is commented out? That'd mess some stuff up.
Also, the second parameter in InvokeRepeating is the delay before Fire() is called, so you'd presumably want fireRate as the third parameter.
Get rid of the Vector3 inside TransformDirection, it only needs the numbers.
See what all that does and get back to me.
Alrighty, I made the changes. First, the commented out part was my mistake. I was tinkering with it before I posted it and forgot to uncomment the function. Now, what I wanted to do was have the balls shoot out Automatically when the scene loads. I just used the Get$$anonymous$$ouseButtonDown to test what I already knew I could do. $$anonymous$$aking it fire automatically is where I'm getting stuck. Fixing the InvokeRepeating worked like a charm, and I got rid of the Vector3. So basically now, I just need help with getting these damn balls to shootout on their own with a 2 second delay between shots. Then I need to work on a hit detection script that will work in tandem with a target and the ball.
This should give you what you want. It's line 31 in your code. The velocity in the Z axis should be random between 50 and 250. Also I believe InvokeRepeating goes outside of your update function.
instantiatedProjectile.velocity = transform.TransformDirection( Vector3( 0, 0, RandomRange(50,250) ) );
I don't think you want the call to InvokeRepeating in your Update without any states around it, otherwise every frame your game will spawn another instance of Fire. Not sure why you would call something via InvokeRepeating (which you want to keep going) and then cancel it after one pass. Update the code with your changes so we see where you are.
Put a sphere collider (as trigger if you prefer) on your Cannonball prefab and use OnTriggerEnter or OnCollision within the prefab to detect hit/collision.
Right. I've never used InvokeRepeating myself, but it makes sense that it wouldn't be in Update().
Answer by superluigi · Jan 16, 2014 at 10:36 AM
Try this code. If you need help reading it let me know I'll help you out.
var projectile : Rigidbody; //The Bullet
var fireRate : float = .5;//Time Delay Between Shots!
var shootTime: float = 0.3;
//RandomizedShotSpeed//
var switchSpeed : float = 2.0;
var currentSpeed : float = 100;
function Update()
{
var speed = Array(50,100,150,200,250);
if(Time.time >= switchSpeed )
{
var index = Random.Range(0, speed.length);
switchSpeed += 2.0;
currentSpeed = speed[index];
print(currentSpeed);
}
if(Time.time >= shootTime)
{
var instantiatedProjectile : Rigidbody = Instantiate(projectile, transform.position, transform.rotation );
instantiatedProjectile.velocity = transform.TransformDirection( Vector3( 0, 0, currentSpeed ) );
shootTime += fireRate;
}
}
Thanks for the script, I tried using it but it threw 3 errors. 2 saying that index is a unknown identifier one saying that "The best overload method 'Array.get_item(int)' is not compatible with the argument list '(error)'.
I think I know the 'item' problem. Is it because it wasn't set as a variable? The other, I dunno.
This is in js not c# fyi. If you copy this code and paste it to a script and add that script to an object, it should give you no errors. Well you would need to drag your projectile in the inspector and it would need to have a rigidbody attached but once you did that there should be no errors. I would like for you to a least look at the code in action, maybe it's exactly what you're looking for, maybe not. I'm willing to stick around and help. If you create a new scene you could literally gets this code working in under 5 $$anonymous$$utes.
ok, well I tried your suggestion. and I wasn't able to clear those errors. Here is the code I used, which is word for word what you gave me:
var projectile : Rigidbody; //The Bullet
var fireRate : float = .5;//Time Delay Between Shots!
var shootTime: float = 0.3;
//RandomizedShotSpeed//
var switchSpeed : float = 2.0;
var currentSpeed : float = 100;
function Update()
{
var speed = Array(50,100,150,200,250);
if(Time.time >= switchSpeed )
{
index = Random.Range(0, speed.length);
switchSpeed += 2.0;
currentSpeed = speed[index];
print(currentSpeed);
}
if(Time.time >= shootTime)
{
var instantiatedProjectile : Rigidbody = Instantiate(projectile, transform.position, transform.rotation );
instantiatedProjectile.velocity = transform.TransformDirection( Vector3( 0, 0, currentSpeed ) );
shootTime += fireRate;
}
}
These are the erros I'm Getting: Assets/Scripts/CannonTest.js(14,8): BCE0005: $$anonymous$$ identifier: 'index'. Assets/Scripts/CannonTest.js(16,29): BCE0005: $$anonymous$$ identifier: 'index'. BCE0017: The best overload for the method 'Array.get_Item(int)' is not compatible with the argument list '(error)'.
Not sure how to get rid of these. It wont let me attach the script to an empty game object or anything. Be cause I get a message that it has to compile first.
That is the weirdest thing. I don't get any errors but I also copied it word for word. $$anonymous$$aybe you have an older version of Unity or monodevelop it weird. Anyway I think I know what's wrong. Add var before index. That'll create the index variable. As it stands the code shouldn't work but for some unknown reason works for me. Lol just figured it out you have #pragma strict before your code which is a good thing. Idk why I took that off I always leave it there. This should give you a warning but it will in no way stop the code from working. I'll work on fixing that but as it is you can hit play and it'll work guaranteed.
Answer by jhart08 · Jan 16, 2014 at 08:54 AM
function FireRepeating() {
while(/*condition*/) {
var bullet = Instantiate(prefab, /*position*/, /*rotation*/);
bullet.velocity = /*whatever you want*/;
yield WaitForSeconds(2);
}
}
Then you can call it by using:
StartCoroutine(FireRepeating());
Thank you sir! Some good code to play around with. I'm learning a lot from you guys!