- Home /
Launch a projectile from one object to another
G'day guys, I've been trying for some time to devise a script that would enable a turret-like object to instantiate and launch a projectile prefab at a target that enters its collider. I've seen people use LookAt() for 'traditional' turrets, but my objects can't afford to 'look'. In fact, an ambition further down the line is to create multiple 'fire points' on each 'turret'.
Anyway, I've tried a few different methods, to no avail. Combining a LookAt() that instantiates a gameobject pointing in the same direction as the turret was my best idea, but I can't help but feel there must be a clean, efficient way to do this, perhaps by drawing a raycast from the turret to the target, and somehow moving the projectile down this path?
Anybody have any advice as to the best way to do this? I just need to be pointed in the right direction.
Cheers.
Answer by aldonaletto · Jan 06, 2012 at 01:05 PM
You can create a vector turret->target and use it to instantiate and fire your projectile:
var turret: Transform; // drag the turret here var prefab: Rigidbody; // drag the projectile prefab here var speed: float = 10; // projectile speed var dist: float = 2; // spawn point distance from the turret
function OnTriggerEnter(col: Collider){ // calculate the direction: var dir = (col.transform.position - turret.position).normalized; // calculate the rotation: var rot = Quaternion.FromToRotation(Vector3.forward, dir); // create the projectile var proj: Rigidbody = Instantiate(prefab, turret.position + dist dir, rot); // make the trigger ignore the projectile: Physics.IgnoreCollision(collider, proj.collider); proj.velocity = speed dir; } This code must be attached to the trigger volume, and any object entering this trigger will receive a welcome projectile. To avoid collisions with the turret object, the projectile is instantiated at dist distance from the turret.
Notice that in this case the firing code is assigned to the trigger, not to the turret. If you want to keep the actual firing code in the turret, you can use SendMessageUpwards just to tell the turret who's the target, and let the turret script aim and fire:
// Trigger script:
function OnTriggerEnter(col: Collider){ // tell the turret script who entered the trigger: SendMessageUpwards("TargetFound", col.transform); }
// Turret script:
var prefab: Rigidbody; // drag the projectile prefab here var trigger: Collider; // drag the trigger object here var speed: float = 10; // projectile speed var dist: float = 2; // spawn point distance from the turret
function TargetFound(target: Transform){ // calculate the direction: var dir = (target.position - transform.position).normalized; // calculate the rotation: var rot = Quaternion.FromToRotation(Vector3.forward, dir); // create the projectile var proj: Rigidbody = Instantiate(prefab, transform.position + dist dir, rot); // trigger must ignore projectiles! Physics.IgnoreCollision(trigger, proj.collider); proj.velocity = speed dir; } This second alternative is more versatile, because you can do smart things like checking the target tag to not shoot turret's friends, or turn the turret to the target before shooting etc.
Cheers, that's a start. It fires an endless stream of projectiles, and doesn't follow the target, but that's easily fixed. What I don't understand is why after a while it goes crazy, firing projectiles in a bizarre cicular pattern like a garden sprinkler, or a person with a gun spinning around.
Is it possible to avoid physics? I know that's a tall order, but ins$$anonymous$$d of adding velocities, could I do this the 'kinetic' way, with translate?
Dear God! The turret really starts firing like a crazy machine gun! The problem is something I thought would not happen: each projectile instantiated causes an OnTriggerEnter, and become itself another target! This can be avoided in the first alternative using Physics.IgnoreCollision:
... var proj: Rigidbody = Instantiate(prefab, turret.position + dist * dir, rot); // make trigger ignore the projectile: Physics.IgnoreCollision(collider, proj.collider); proj.velocity = speed * dir; }It's way easier to use a rigidbody (set useGravity off!), and collisions won't work fine with non-rigidbody objects, but if you want to try it, write a script for movement and collision detection and attach it to the projectile prefab:
var speed: float = 10;
function FixedUpdate(){ // moves the projectile in its forward direction transform.Translate(Vector3.forward speed Time.deltaTime); }
function OnCollisionEnter(){ // add here the code for damage, explosion etc. Destroy(gameObject); }
Your answer
Follow this Question
Related Questions
Problem in Shooting Accuracy 0 Answers
How to stop enemies from shooting each other 1 Answer
Air Strike shoot aiming at cross hairs in middle of the screen 2 Answers
Turret shooting at me 1 Answer
Turret With Raycast Camera 1 Answer