- Home /
Area Effect Damage
I have a script on a cannonball so that when it hits a target directly, it kills them instantly, if it hits near them, they might die instantly, or they might get severely damage. If they're farther away, less damaged, etc. So I tried doing that with this script:
#pragma strict
var explosion : GameObject;
var blast : AudioClip;
var waterHit : GameObject;
var waterBlast : AudioClip;
var target : Transform;
var closeAreaEffect : float = 1.5;
var mediumAreaEffect : float = 3;
var farAreaEffect : float = 5;
private var speed : float = 100;
private var destroyTime : float = 5;
private var detachChildren : boolean = false;
private var closeDamage : float = 100;
private var mediumDamage : float = 50;
private var farDamage : float = 25;
function Update ()
{
transform.Translate(Vector3.forward * Time.deltaTime * speed);
}
function Awake ()
{
Invoke ("DestroyNow", destroyTime);
}
function DestroyNow ()
{
if (detachChildren) {
transform.DetachChildren ();
}
DestroyImmediate(gameObject);
}
function OnCollisionEnter (collision : Collision) {
if(collision.gameObject.CompareTag("British")){
Instantiate(explosion, transform.position, transform.rotation);
audio.PlayOneShot(blast);
}
if(collision.gameObject.CompareTag("Terrain")){
Instantiate(explosion, transform.position, transform.rotation);
audio.PlayOneShot(blast);
}
if(collision.gameObject.CompareTag("Water")){
Instantiate(waterHit, transform.position, transform.rotation);
audio.PlayOneShot(waterBlast);
}
Destroy(gameObject);
var distance = Vector3.Distance(target.transform.position, transform.position);
if(collision.gameObject.CompareTag("British")){
collision.collider.gameObject.SendMessage("ApplyDamage", closeDamage, SendMessageOptions.DontRequireReceiver);
}
if(collision.gameObject.CompareTag("British") && distance <= closeAreaEffect){
collision.collider.gameObject.SendMessage("ApplyDamage", closeDamage, SendMessageOptions.DontRequireReceiver);
}
if(collision.gameObject.CompareTag("British") && distance <= mediumAreaEffect){
collision.collider.gameObject.SendMessage("ApplyDamage", mediumDamage, SendMessageOptions.DontRequireReceiver);
}
if(collision.gameObject.CompareTag("British") && distance <= farAreaEffect){
collision.collider.gameObject.SendMessage("ApplyDamage", farDamage, SendMessageOptions.DontRequireReceiver);
}
}
@script RequireComponent(Rigidbody);
The problem with this script is that the only way for it to calculate the distance is according to it's target. Well the target is a transform, but the cannonball itself is a GameObject, so I can't assign the transform. How should I change this?
Also i believe that a collider that qualifies for your close damage distance will also get medium and far damage.
Answer by aldonaletto · Oct 23, 2011 at 12:07 AM
The idea should be modified a little: in a explosion, objects that are near but were not directly hit should also be damaged. It's usually done with Physics.OverlapSphere centered at the explosion position, and with a farAreaEffect radius: this function returns an array of all colliders that intersect the spherical volume, and you can check the individual distances to apply the damage. You could modify the last part of the OnCollisionEnter function this way:
function OnCollisionEnter (collision : Collision) {
if (collision.gameobject.CompareTag("British")){
Instantiate(explosion, transform.position, transform.rotation);
audio.PlayOneShot(blast);
}
if (collision.gameobject.CompareTag("Terrain")){
Instantiate(explosion, transform.position, transform.rotation);
audio.PlayOneShot(blast);
}
if (collision.gameobject.CompareTag("Water")){
Instantiate(waterHit, transform.position, transform.rotation);
audio.PlayOneShot(waterBlast);
}
Destroy(gameObject);
// This is the modified part:
// find the colliders inside a sphere of radius farAreaEffect
var colls = Physics.OverlapSphere(transform.position, farAreaEffect);
for (var col: Collider in colls){
if (col.CompareTag("British")){ // if it's a bloody British...
// calculate the distance from the impact...
var distance = Vector3.Distance(col.transform.position, transform.position);
var damage = farDamage; // assume farDamage initially...
if (distance <= closeAreaEffect){
damage = closeDamage; // but if inside close area, change to max damage
}
else
if (distance <= mediumAreaEffect){
damage = mediumDamage; // else if inside medium area, change to medium damage
}
// apply the selected damage
col.SendMessage("ApplyDamage", damage, SendMessageOptions.DontRequireReceiver);
}
}
}
This answers my question, but I have switched to C# and have been unable to convert it. This is my try :
using UnityEngine;
using System.Collections;
public class Explosive : $$anonymous$$onoBehaviour {
public float closeAreaEffect = 1.0F;
public float mediumAreaEffect = 2.5F;
public float farAreaEffect = 5.0F;
public float closeDamage = 75.0F;
public float mediumDamage = 50.0F;
public float farDamage = 25.0F;
private Transform explosive;
void Awake () {
explosive = transform;
}
void Start () {
}
void Update () {
}
void OnCollisionEnter () {
Collider colls = Physics.OverlapSphere(explosive.position, farAreaEffect);
for (Collider col = Collider in colls){
if (col.CompareTag("Player")){
float distance = Vector3.Distance(col.transform.position, explosive.position);
float damage = farDamage;
if(distance <= closeAreaEffect){
damage = closeDamage;
}
else if(distance <= mediumAreaEffect){
damage = mediumDamage;
}
col.Send$$anonymous$$essage("ApplyDamage", damage, Send$$anonymous$$essageOptions.DontRequireReceiver);
}
}
}
}
It almost works, except the for loop doesn't work correctly. I'm getting errors saying "unexpected symbol 'in'"and assignment errors. There are a lot, so you should try running it in Unity for the full list. I'm not exactly sure how to fix it. I think most of the errors will go away when you fix one or two of the errors.
I suspect the error is in:
Collider colls = Physics.OverlapSphere(explosive.position, farAreaEffect);
for (Collider col = Collider in colls){
I think it should be:
Collider[] colls = Physics.OverlapSphere(explosive.position, farAreaEffect);
foreach (Collider col in colls){
Hi, um is it possible for you to convert this into 2d?? Thank you
Hi
I know this is an old post but I will try my luck anyway. I have used the script you have made but I have a problem. When I hit multiple enemies with my missile only one of them dies. Is that because they have the same tag?
Here is the script.
It works. Every single error was based off those lines. Thank you again.
Answer by chemicalvamp · Oct 22, 2011 at 11:38 PM
http://unity3d.com/support/documentation/ScriptReference/Collision-contacts.html With this you can get the position of where your cannonball hit. but from that position i would probably use a physics overlap sphere to populate an array of who should take any damage. Then you could do a foreach loop to apply it to only whoever you want. Or perhaps 3 overlap spheres with different radius' that way enemies near the hit would be detected in all 3 (3x damage), middle would be detected by only mid and near, and those at the outer radius would only be detected by 1.
Your answer
Follow this Question
Related Questions
Instantiate rigidbody, transform or gameobject? 1 Answer
I want to move a cube with rotation but I find this problem 1 Answer
Converting GameObject into Transform? 1 Answer
Is there any way to convert Collision to a Gameobject or Transform? 1 Answer
Difference between Vector3, Transform and GameObject 2 Answers