but when player kills enemy the enemy doesn’t disappear right away but stays there for a few seconds (which is what I want) what I don’t want is any more score points - only 1 max per enemy
so if player hits enemy again the score count will count another point for same dead enemy which is not what I want, the death is triggered upon collision form player
WHAT I WANT is to only be able to count 1 point on score from each enemy no matter how many times after is dead enemy is hit/(oncollision2d)
doesn’t matter still will only give u 1 point per enemy no more.
again I want enemy to stay for a few seconds after death but don’t want more than 1 point .
using UnityEngine;
using System.Collections;
public class playercscorecard : MonoBehaviour
{
public GUIText countText;
private int count;
void Start()
{
count = 0;
SetCountText ();
}
//void FixedUpdate () {
//}
//void OnTriggerEnter2D(Collider2D other) {
void OnCollisionEnter2D(Collision2D coll) {
if (coll.gameObject.tag == "Player")
//if(other.gameObject.tag == "Player")
{
//other.gameObject.SetActive (false);
count = count + 1;
SetCountText ();
}
}
void SetCountText ()
{
countText.text = "Count: " + count.ToString();
}
}
You can disable the collider so OnCollisionEnter2D won’t be called again.
If you want to still be able to detect collisions with the enemies (for some physic simulation) you can just set a bool in the enemy to tell if it’s dead or not instead of disabling the collider, then on your OnCollisionEnter2D check if the enemy is alive before adding a point:
using UnityEngine;
using System.Collections;
public class playercscorecard : MonoBehaviour
{
public GUIText countText;
private int count;
private bool isDead; //defaults to false
void Start()
{
count = 0;
SetCountText ();
}
void OnCollisionEnter2D(Collision2D coll) {
if (coll.gameObject.tag == "Player")
{
if (!isDead)
{
count = count + 1;
SetCountText ();
isDead = true;
}
}
}
void SetCountText ()
{
countText.text = "Count: " + count.ToString();
}
}
You can use a simple boolean logic and a coroutine to achieve what you want. But I am confused, why are you keeping your count variable as a private one. You should be using a public variable for that if you want to achieve something like a killcount of the player. In order to do that, create a new C# script and name it, in this example, LevelManager. This will be the content of that script :
using UnityEngine;
using System.Collections;
public class LevelManager : MonoBehaviour {
[System.NonSerialized] // do not show it in the inspector, alternative is : [HideInInspector]
public int killCount; // general value for killCount, this will be increased through enemy scripts.
public GUIText countText; // the GUIText that will show the count
public void SetKillCount() // public void because we will call this from the enemy script.
{
countText.text = "Count: " + killCount.ToString();
}
}
Create an empty game object in the scene and attach this script to it. And for the enemy script :
using UnityEngine;
using System.Collections;
public class playercscorecard : MonoBehaviour
{
public int increaseAmount; // how much will the count increase when the player hits enemy, one time only
public LevelManager levelManager; // the instance of the LevelManager class. The empty game object which is attached with LevelManager script. Drag and drop the emptyGO.
public float waitTime; // how much time is it going to take for the enemy to be destroyed after hit.
private bool canStartCoroutine; // boolean to handle simple " one time only " logic
void Start()
{
canStartCoroutine = true;
}
void OnCollisionEnter2D(Collision2D coll) {
if (coll.gameObject.tag == "Player")
{
if(canStartCoroutine)
{
canStartCoroutine = false; // after one hit, boolean is made false immediately to prevent it from updating again.
StartCoroutine(WaitToDestroy(waitTime));
}
}
}
IEnumerator WaitToDestroy(float time)
{
levelManager.killCount += increaseAmount; // increase the kill count by increaseAmount value
levelManager.SetKillCount(); // refresh the kill count
yield return new WaitForSeconds(time); // wait for the desired time
Destroy(gameObject); // destroy the gameobject itself.
}
}
PS. As seen above, in the start function the canStartCoroutine boolean is set to true, for it to be able to cast the coroutine function for the first time. If you are not going to destroy your enemies, but deactivate them and make them active again in somewhere else, you should be using void OnEnable() to set the canStartCoroutine boolean as true. Because Start function will not be processed for the second time.
This is a very simple but effective way, another way to manage something like this, you can use static variables. Or if you do not want to create a level manager object, and drag & drop it on the enemyscript, you can use Singleton Method. This enables you to create an instance of a class and make it reachable very easily, perfect for handling levels. Hope that these helped !
GameObject enemy = Instantiate(enemyPrefab, Vector3 (x, y, z), Quaternion.identity); //you probably have this line somewhere enemy.GetComponent().LevelManager = LevelManagerFromThisScene //Between “GetComponent” and “()” you must specify the type of the component, playercscorecard in this case