I am new at Unity. I have successfully made a player can shoot a bullet to the enemy depends on the current wave, and I make where the enemy have it is own life depends on the current wave multiply with certain value. If the enemy life is 0, the enemy dies. But, the problem is: for example there are 2 enemies on the scene and the enemy life is 5 and the player start shooting the first enemy until the enemy life decreases to 2, when the player start shooting the second enemy, the enemy life is not 5 anymore, but it is 2 until one of the 2 cubes is dead and the enemy life reset to 5.
How can I solve this problem?
Here is the bullet script:
public class BulletManager : MonoBehaviour
{
private ScoreManager scoreManager;
private PlayerController playerController;
private EnemyManager enemyManager;
public int bulletPower;
private void Start()
{
scoreManager = GameObject.Find("Game Manager").GetComponent<ScoreManager>();
playerController = GameObject.Find("Character").GetComponent<PlayerController>();
enemyManager = GameObject.Find("Game Manager").GetComponent<EnemyManager>();
bulletPower = playerController.currentWave;
}
private void OnTriggerEnter(Collider col)
{
if (col.gameObject.tag == "Enemy")
{
enemyManager.enemyLife -= bulletPower;
if (enemyManager.enemyLife <= 0)
{
scoreManager.Points += (2 * playerController.currentWave);
enemyManager.enemyLife = playerController.currentWave * 5;
Destroy(col.gameObject);
}
}
}
}
And here is the enemy script:
public class EnemyManager : MonoBehaviour
{
private ScoreManager scoreManager;
private SoundManager soundManager;
private PlayerController playerController;
public int enemyLife;
private void Start()
{
scoreManager = GameObject.Find("Game Manager").GetComponent<ScoreManager>();
soundManager = GameObject.Find("Game Manager").GetComponent<SoundManager>();
playerController = GameObject.Find("Character").GetComponent<PlayerController>();
enemyLife = playerController.currentWave * 5;
}
private void Update()
{
if (playerController.life <= 0)
{
Invoke("Restart", 1);
}
}
private void OnTriggerEnter(Collider col)
{
if (col.gameObject.tag == "Bullet")
{
soundManager.PlaySound("Enemy Dead");
Destroy(col.gameObject);
}
else if (col.gameObject.tag == "Destroyer")
{
playerController.life--;
}
}
private void Restart()
{
scoreManager.SendToHighScore();
Application.LoadLevel(0);
}
}
The problem is that all of your enemies use the EnemyManager class to manage their health. What your code does is count the amount of hits on all enemies and then destroys the last one that was hit. My suggestion is to add an EnemyStats class to manage stats specific to each enemy (name of the enemy, the amount of damage they can do, weapon graphics, sound effects, the skys the limit). I hate to give you the answer right off the bat (or at least a basic one) since this is a good learning opportunity but here is a basic script that should do what you need and the changes you need to make to your BulletManager script.
EnemyStats.cs (Attach to the enemies game object)
public class EnemyStats : MonoBehaviour
{
public int currentHealth;
public int maxHealth;
public float increasePerWave;
public int bulletPower;
// use a negative value for healing
public void ReduceHealth(int damage)
{
currentHealth -= damage;
}
public bool IsDead()
{
return currentHealth <= 0;
}
public int GetDamage()
{
return bulletPower;
}
/// Restores enemy to their max health for the current wave. Call this after creating an spawning.
public void RestoreHealth(int wave)
{
currentHealth = (int)(maxHealth * increasePerWave * (wave + 1));
}
}
BulletManager update
private void OnTriggerEnter(Collider col)
{
if (col.gameObject.tag == "Enemy")
{
EnemyStats stats = col.GetComponent<EnemyStats>();
if (stats)
{
stats.ReduceHealth(bulletPower);
if (stats.IsDead())
{
scoreManager.Points += (2 * playerController.currentWave);
Destroy(col.gameObject);
}
}
}
}
Related
Im currently trying to code a health system for my game and I want my Player GameObject to ignore collision with the Health Potion GameObject if the Player has max health. My problem is that I cannot simply turn off the collision between the Player Layer and Health Potion Layer because I only want to ignore collision if the Player has Max Health. I tried doing it myself but it didn't work. Here's my code:
public class ExampleCodeUA : MonoBehaviour{
public int PlayerMaxHealth = 100, PlayerCurrentHealth;
public HealthBar healthBar;
private void Start()
{
PlayerCurrentHealth = PlayerMaxHealth;
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("HealthPotion"))
{
if (PlayerCurrentHealth == PlayerMaxHealth)
{
Physics2D.IgnoreLayerCollision(6, 7);
}
else if (PlayerCurrentHealth > 50)
{
GetHealth(PlayerMaxHealth - PlayerCurrentHealth);
}
else if (PlayerCurrentHealth <= 50)
{
GetHealth(50);
}
}
}
void GetHealth(int healing)
{
PlayerCurrentHealth += healing;
healthBar.SetHealth(PlayerCurrentHealth);
}
}
You don't want to modify your physics configuration at runtime. What you could do to avoid the collision... is to make it impossible, by having nothing to collide with. Both of your objects have a collider. What you could do is to disable all existing HealthPotion colliders by modifying their code. An implementation could be the following:
using System.Collections.Generics;
using UnityEngine;
public class HealthPotion : MonoBehaviour
{
private static List<HealthPotion> _existingPotions = new List<HealthPotion>();
public static void EnablePotionsCollider(bool value)
{
foreach (var potion in _existingPotions)
{
potion._collider.enabled = value;
}
}
private Collider _collider;
void Awake()
{
_collider = GetComponent<Collider>();
}
void OnEnable()
{
_existingPotions.Add(this);
}
void OnDisable()
{
_existingPotions.Remove(this);
}
}
Then you just have to call the method when you want to enable/disable by doing
HealthPotion.EnablePotionsCollider(value you want);
I made two scripts. One that'll keep track of the player's health, health bar and cause the screen to flash when the player is damaged. The other script is meant to be placed on any object I wish to do damage to the player, on contact. My problem is, Nothing seems to be doing any damage to the player.
PlayerHealth.cs:
using UnityEngine;
using UnityEngine.UI;
public class PlayerHealth : MonoBehaviour
{
public int currentHealth;
public float flashSpeed = 5;
public Slider healthSlider;
public Color flashColour = new Color(1, 0, 0, 0.1f);
bool isDead;
bool damaged;
private void Awake()
{
currentHealth = 100;
}
private void Update()
{
damaged = false;
}
public void TakeDamage(int amount)
{
damaged = true;
currentHealth -= amount;
healthSlider.value = currentHealth;
}
}
AttackPlayer.cs:
using UnityEngine;
public class AttackPlayer : MonoBehaviour
{
public float timeBetweenAttacks = 0.5f;
public int attackDamage = 10;
GameObject player;
PlayerHealth playerHealth;
float timer;
private void Awake()
{
player = GameObject.FindGameObjectWithTag("Player");
playerHealth = player.GetComponent<PlayerHealth>();
}
private void OnTriggerEnter2D(Collider2D col)
{
if (col.gameObject == player)
{
Attack();
}
}
private void Update()
{
timer += Time.deltaTime;
if(playerHealth.currentHealth <=0)
{
// TODO: add death script here.
}
}
void Attack()
{
timer = 0f;
if(playerHealth.currentHealth > 0)
{
playerHealth.TakeDamage(attackDamage);
}
}
}
The player has a rigidbody2D. The player and damaging objects have Box Collider 2D's on them.
Make sure that the players Collider has isTrigger enabled.
attackDamage is public -> set in the inspector. Make sure it is not 0.
You could use
[Range(1,100)] public int attackDamage = 10;
to automatically clamp the value in the inspector.
A guess but I'ld say your Collider might not be on the GameObject player but probably on one of its children => the condition col.gameObject == player is not true.
Instead of GameObject references rather compare the PlayerHealth (since there is only one) reference like
private void OnTriggerEnter2D(Collider2D col)
{
// gets PlayerHealth component on this or any parent object
var health = col.GetComponentInParent<PlayerHealth>();
if (health == playerHealth)
{
Attack();
}
}
You have
private void Update()
{
damaged = false;
}
public void TakeDamage(int amount)
{
damaged = true;
currentHealth -= amount;
healthSlider.value = currentHealth;
}
I don't know what else should happen on TakeDamage but the value of damaged is resetted in Update so right after it was set by the Trigger because Physics events like OnTriggerEnter are executed before Update (see execution Order).
Hint: Instead of
player = GameObject.FindGameObjectWithTag("Player");
playerHealth = player.GetComponent<PlayerHealth>();
you could also use
playerHealth = FindObjectOfType<PlayerHealth>();
if that component exists only once in your scene.
Or to be more flexible (having multiple Players) all you have to do is change your OnTriggerEnter2D and Attack method to
private void OnTriggerEnter2D(Collider2D col)
{
// gets PlayerHealth component on this or any parent object
var health = col.GetComponentInParent<PlayerHealth>();
if (health != null)
{
Attack(health);
}
}
void Attack(PlayerHealth health)
{
timer = 0f;
if(health.currentHealth > 0)
{
health.TakeDamage(attackDamage);
}
}
So you wouldn't need to get the reference before.
I'm making a breakout game, and I wanted to add a healthbar that decreases when the ball touches a certain object with the tag "hazard". I have a Game Manager Script, and A Pickup interact script, but with the way I set it up, I'm kind of confused with how to trigger takedamage from my GM script to my pickup script, considering I put my playerhealth elements into my GM script, so I can attach it to empty gameobject call Game Manager, since the actual player isnt in the hierarchy, but instantiated during runtime. I'm hoping I don't have to redo the whole thing just for this purpose. If someone could help me figure this out, I'd appreciate it.
Here's my GM script:
public class GM : MonoBehaviour
{
public int lives = 3;
public int bricks = 20;
public float resetDelay = 1f;
public Text livesText;
public GameObject gameOver;
private GameObject clonePaddle;
public GameObject youWon;
public GameObject bricksPrefab;
public GameObject paddle;
public GameObject deathParticles;
public static GM instance = null;
public int startingHealth = 100;
public int currentHealth;
public Slider healthSlider;
bool isDead;
bool damaged;
void Awake()
{
currentHealth = startingHealth;
TakeDamage(10);
if (instance == null)
instance = this;
else if (instance != this)
Destroy(gameObject);
Setup();
}
public void TakeDamage(int amount)
{
damaged = true;
currentHealth -= amount;
healthSlider.value = currentHealth;
if (currentHealth <= 0)
{
LoseLife();
}
}
public void Setup()
{
clonePaddle = Instantiate(paddle, transform.position, Quaternion.identity) as GameObject;
Instantiate(bricksPrefab, transform.position, Quaternion.identity);
}
void CheckGameOver()
{
if (bricks < 1)
{
youWon.SetActive(true);
Time.timeScale = .25f;
Invoke("Reset", resetDelay);
}
if (lives < 1)
{
gameOver.SetActive(true);
Time.timeScale = .25f;
Invoke("Reset", resetDelay);
}
}
void Reset()
{
Time.timeScale = 1f;
Application.LoadLevel(Application.loadedLevel);
}
public void LoseLife()
{
lives--;
livesText.text = "Lives: " + lives;
Instantiate(deathParticles, clonePaddle.transform.position, Quaternion.identity);
Destroy(clonePaddle);
Invoke("SetupPaddle", resetDelay);
CheckGameOver();
}
void SetupPaddle()
{
clonePaddle = Instantiate(paddle, transform.position, Quaternion.identity) as GameObject;
}
public void DestroyBrick()
{
bricks--;
CheckGameOver();
}
}
And here's my Pickup Script:
public class Pickups : MonoBehaviour {
public float PaddleSpeedValue = 0.5f;
private bool isActive = false;
public float thrust=20f;
public Rigidbody rb;
GameObject player;
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Hazard")
{
isActive = true;
Destroy(other.gameObject);
}
}
}
The Pickups class should not have or store a reference to the player at all (although it is not clear from your question if this is a script attached to the player or attached to something else). Your Game Manager class should. Afterall, it is the class that is responsible for managing the game which includes the player. From there, you can use GetComponent<?>() to access any scripts attached to the player GameObject.
Then as the GM contains a public static reference to itself, any other class can get a reference to the player by doing GM.instance.player as needed, even if the player is created and destroyed several times (as the GM should always have a reference to the current one!)
Presumably the clonePaddle field is the player('s GameObject), all you have to do is make it public.
The playerLife variable doesn't update visibly in the Inspector or the on-screen Health Text, but the Player still dies because the playerLife drops below zero.
I've determined that the Player prefab attached to the Zombie GameObject is solely the Player prefab rather than the in-scene active Player. How do I make it so that the zombies always reference the in-scene active Player rather than the basic Player prefab, by script? (Also, it won't allow me to manually drag the active Player into the Zombie)
Call hierarchy for playerLife
public class Player : MonoBehaviour
{
public RaycastHit hit;
public int gunDamage = 1;
public Zombie zombie;
private float hitForce = 100f;
public float playerLife;
private Vector3 flareLower = new Vector3(0, -0.5f, 0);
void Start()
{
spawnPoints = playerSpawnPoint.GetComponentsInChildren<Transform>();
playerLife = 200;
}
void Update() //T-toggle
{
if (Input.GetButton("Fire1"))
{
LazerBeam();
}
if (reSpawn != lastToggle)
{
ReSpawn();
reSpawn = false;
}
else
lastToggle = reSpawn;
}
public void Life (float damage)
{
playerLife -= damage;
if (playerLife <=0)
{
playerLife = 100;
SceneManager.LoadScene(2);
}
}
}
public class Zombie : MonoBehaviour
{
public int currentHealth;
public Player player;
public PlayerLifeCollider playerCollider;
private int damage;
public void Damage(int damageAmount)
{
currentHealth -= damageAmount;
if (currentHealth <= 0)
{
PlayerLifeCollider.instance.ObjectsInRange.Remove(gameObject);
DestroyZombie();
}
}
public void DestroyZombie()
{
Destroy(gameObject);
// gameObject.SetActive(false);
}
public void DamagePlayer(float damage)
{
player.Life(damage);
}
}
As you said, the problem is that you are not referencing the Player object on your scene, but a prefab one. To avoid that, you can add a Start function to the Zombie script and ask to look for what should be the only Player instance in the scene. For this, you can use the FindObjectOfType function:
void Start()
{
player = FindObjectOfType<Player>();
}
Considering you will only have one Player script in your entire scene, what you can also do is to save in your Player class a static reference to your Player instance.
public class Player : MonoBehaviour
{
private static Player _instance;
public static Player Instance
{
get
{
if (_instance == null)
{
_instance = FindObjectOfType<Player>();
}
return _instance;
}
}
// Reset of your class
}
You can then get this reference in your Zombie script:
public class Zombie : MonoBehaviour
{
static Player player;
void Start()
{
if(player == null)
{
player = Player.Instance;
}
}
// Rest of your class content
}
This way, you will only have one call to the FindObjectOfType function instead of once per object using the Zombie script.
public void Damage(int damageAmount)
{
currentHealth -= damageAmount;
print(currentHealth);// will show in terminal if thats what you are asking
if (currentHealth <= 0)
{
PlayerLifeCollider.instance.ObjectsInRange.Remove(gameObject);
DestroyZombie();
}
}
In Unity3D my enemy is not taking damage upon colliding with my projectile explosion.
Although this is not the case as it the health variable is unaffected upon colliding with my projectile explosion.
My Enemy and Barrel classes inherit from Entity which handles the taking of damage (subtracting the damage variable from the health variable). Although only the barrel class is working as intended.
The tags are 100% correct and I would prefer to continue using inheritance so please no suggestions to change the method in which my classes take damage.
the class that Enemy and Barrel inherit from
using UnityEngine;
using System.Collections;
public class Entity : MonoBehaviour {
public float health = 25;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public virtual void takeDamage(float dmg){
health -= dmg;
if (health <= 0){
Destroy(this.gameObject);
}
}
}
Enemy class
using UnityEngine;
using System.Collections;
public class Enemy : Entity {
private NavMeshAgent agent;
public GameObject target;
// Use this for initialization
void Start () {
agent = GetComponent<NavMeshAgent> ();
}
// Update is called once per frame
void Update () {
agent.SetDestination (target.transform.position);
}
}
Barrel class
using UnityEngine;
using System.Collections;
public class Barrel : Entity {
private Transform myTransform;
//Effects
public GameObject barrelExplosion;
public GameObject explosionDamage;
public GameObject explosionSound;
// Use this for initialization
void Start () {
myTransform = this.transform;
}
// Update is called once per frame
void Update () {
}
public override void takeDamage(float dmg){
health -= dmg;
if (health <= 0){
Instantiate(barrelExplosion, myTransform.position, myTransform.rotation);
Instantiate(explosionSound, myTransform.position, myTransform.rotation);
Instantiate(explosionDamage, myTransform.position, myTransform.rotation);
Destroy(this.gameObject);
}
}
}
ExplosionAOE the class that sends the damage
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ExplosionAOE : MonoBehaviour {
public float damage = 100.0f;
public float lifeTime = 0.05f;
private float lifeTimeDuration;
public List<GameObject> damageTargets = new List<GameObject>();
public float radius = 15.0f;
GameManager gameManager;
void Start() {
gameManager = GameObject.FindGameObjectWithTag("GameManager").GetComponent<GameManager>();
//Destroy (this.gameObject, lifeTime);
lifeTimeDuration = Time.time + lifeTime;
transform.GetComponent<SphereCollider>().radius = radius;
}
void Update() {
//Explosion finishes, damage targets and remove AOE field
if (Time.time > lifeTimeDuration) {
foreach (GameObject target in damageTargets) {
if (target != null) {
//Calculate damage based on proximity to centre of explosion
float thisDamage = ((radius - Vector3.Distance(target.transform.position, transform.position)) / radius) * damage;
print(thisDamage);
target.GetComponent<Entity>().takeDamage(thisDamage);
//target.SendMessage("takeDamage", damage); //<< This is not good code. Let's fix this!
}
}
Destroy(this.gameObject);
}
}
void OnTriggerEnter(Collider otherObject) {
if (otherObject.gameObject.tag == "Enemy") {
damageTargets.Add(otherObject.gameObject);
}
if (otherObject.gameObject.tag == "Player") {
Vector3 jumpVector = (otherObject.transform.position - transform.position).normalized;
jumpVector *= 25;
otherObject.GetComponent<CharacterMotor>().SetVelocity(jumpVector);
}
}
}
Sorry this is a bit of a lengthy one and EVERYTHING is tagged correctly so that is not the issue, thanks.
Problem 1.
Use "Debug.Log" everywhere
void OnTriggerEnter(Collider otherObject) {
Debug.Log("in trig");
Debug.Log("otherObject.gameObject.tag is " + otherObject.gameObject.tag);
if (otherObject.gameObject.tag == "Enemy") {
Debug.Log("a");
damageTargets.Add(otherObject.gameObject);
}
if (otherObject.gameObject.tag == "Player") {
Debug.Log("b");
Vector3 jumpVector = (otherObject.transform.position -
transform.position).normalized;
jumpVector *= 25;
otherObject.GetComponent<CharacterMotor>().SetVelocity(jumpVector);
}
}
In particular, in Entity and Enemy.
Questions such as this one are instantly answered by tracking with Debug.Log.
Problem 2.
It's a PITA getting the relationships between triggers, rigidbody, etc.
It's very likely that's a problem here.
http://docs.unity3d.com/Manual/CollidersOverview.html
Go down to the annoying "trigger action matrix" and work from there.
Problem 3.
As a rule, never use the "tags" feature in Unity. (They only added tags to help "hello world" tutorials.)
In practice you use layers everywhere and always:
(Layers are particularly essential in shooting games: every single category needs a layer.)
Problem 4.
The code shown is definitely looking good. Here's some example code not unlike yours for tips.
Trivial example, note the breakaway code (the returns) inside the OnTrigger, you should do that).
Also,
use extentions
everywhere and always in Unity. Quick tutorial
it's the #1 tip if you actually want to work professionally.
public class Enemy:BaseFrite
{
public tk2dSpriteAnimator animMain;
public string usualAnimName;
[System.NonSerialized] public Enemies boss;
[Header("For this particular enemy class...")]
public float typeSpeedFactor;
public int typeStrength;
public int value;
// could be changed at any time during existence of an item!
[System.NonSerialized] public FourLimits offscreen; // must be set by our boss
[System.NonSerialized] public int hitCount; // that's ATOMIC through all integers
[System.NonSerialized] public int strength; // just as atomic!
[System.NonSerialized] public float beginsOnRight;
private bool inPlay; // ie, not still in runup
void Awake()
{
boss = Gp.enemies;
}
..........
protected virtual void Prepare() // write it for this type of sprite
{
ChangeClipTo(bn);
// so, for the most basic enemy, you just do that.
// for other enemy, that will be custom (example, swap damage sprites, etc)
}
void OnTriggerEnter2D(Collider2D c)
{
// we can ONLY touch either Biff or a projectile. to wit: layerBiff, layerPeeps
GameObject cgo = c.gameObject;
if ( gameObject.layer != Grid.layerEnemies ) // if we are not enemy layer....
{
Debug.Log("SOME BIZARRE PROBLEM!!!");
return;
}
if (cgo.layer == Grid.layerBiff) // we ran in to Biff
{
Gp.billy.BiffBashed();
// if I am an enemy, I DO NOT get hurt by biff smashing in to me.
return;
}
if (cgo.layer == Grid.layerPeeps) // we ran in to a Peep
{
Projectile p = c.GetComponent<Projectile>();
if (p == null)
{
Debug.Log("WOE!!! " +cgo.name);
return;
}
int damageNow = p.damage;
Hit(damageNow);
return;
}
Debug.Log("Weirded");
}
public void _stepHit()
{
if ( transform.position.x > beginsOnRight ) return;
++hitCount;
--strength;
ChangeAnimationsBasedOnHitCountIncrease();
// derived classes write that one.
if (strength==0) // enemy done for!
{
Gp.coins.CreateCoinBunch(value, transform.position);
FinalEffect();
if ( Gp.superTest.on )
{
Gp.superTest.EnemyGottedInSuperTest(gameObject);
boss.Done(this);
return;
}
Grid.pops.GotEnemy(Gp.run.RunDistance); // basically re meters/achvmts
EnemyDestroyedTypeSpecificStatsEtc(); // basically re achvments
Gp.run.runLevel.EnemyGotted(); // basically run/level stats
boss.Done(this); // basically removes it
}
}
protected virtual void EnemyDestroyedTypeSpecificStatsEtc()
{
// you would use this in derives, to mark/etc class specifics
// most typically to alert achievements system if the enemy type needs to.
}
private void _bashSound()
{
if (Gp.biff.ExplodishWeapon)
Grid.sfx.Play("Hit_Enemy_Explosive_A", "Hit_Enemy_Explosive_B");
else
Grid.sfx.Play("Hit_Enemy_Non_Explosive_A", "Hit_Enemy_Non_Explosive_B");
}
public void Hit(int n) // note that hitCount is atomic - hence strength, too
{
for (int i=1; i<=n; ++i) _stepHit();
if (strength > 0) // biff hit the enemy, but enemy is still going.
_bashSound();
}
protected virtual void ChangeAnimationsBasedOnHitCountIncrease()
{
// you may prefer to look at either "strength" or "hitCount"
}
protected virtual void FinalEffect()
{
// so, for most derived it is this standard explosion...
Gp.explosions.MakeExplosion("explosionC", transform.position);
}
public void Update()
{
if (!holdMovement) Movement();
if (offscreen.Outside(transform))
{
if (inPlay)
{
boss.Done(this);
return;
}
}
else
{
inPlay = true;
}
}
protected virtual void Movement()
{
transform.Translate( -Time.deltaTime * mpsNow * typeSpeedFactor, 0f, 0f, Space.Self );
}
......
/*
(frite - flying sprite)
The very base for enemies, projectiles etc.
*/
using UnityEngine;
using System.Collections;
public class BaseFrite:MonoBehaviour
{
[System.NonSerialized] public float mpsNow;
// must be set by the boss (of the derive) at creation of the derive instance!
private bool _paused;
public bool Paused
{
set {
if (_paused == value) return;
_paused = value;
holdMovement = _paused==true;
if (_paused) OnGamePause();
else OnGameUnpause();
}
get { return _paused; }
}
protected bool holdMovement;
protected virtual void OnGamePause()
{
}
protected virtual void OnGameUnpause()
{
}
protected string bn;
public void SetClipName(string clipBaseName)
{
bn = clipBaseName;
}
}
Is more easy if in ExplosionAOE/OnTriggerEnter function you call the takeDamage function:
scriptCall = otherObject.GetComponent(EnemyScript);
scriptCall.takeDamage(damage);