Unity2D: Making a cloned particle system fire once only - c#

I a have this enemy prefab that gets instantiated from a spawn point in my game, on the enemy prefab I have a particle system componet that if the player shoots the enemy more than 2 times the particle system will play. However I'm having problems with firing the particle system on only one of the enemy prefab that the player shot. Is there a way when the enemy prefab gets shot at to fire the particle system on that enemy prefab rather than the particle system playing when the enemy prefab gets shoot at and any other enemies prefabs that didn't get shot at without using ontriggerenter2d as I had some problems.
This is the script attached to the player:
public GameObject enemy;
public static bool firePar = false;
public static int combo = 0;
void Start (){
firePar = false;
combo = 0;
}
void OnTriggerEnter2D(Collider2D col) {
if(col.tag == "Enemy") {
Destroy(col.gameObject,0.2f);
}
}
void Update() {
if(combo >= 10) {
firePar = true;
} else if (combo < 10) {
firePar = false;
}
}
This is the code on the enemy (for firing the particles):
private ParticleSystem par;
void Start (){
par = GetComponent<ParticleSystem>();
}
void Update () {
if(Playerbullet.firePar == true) {
par.Play();
} else {
par.Stop ();
}
}

Related

Ghost enemy AI that follows the player by copying the players position

Okay, the plan is simple.
My plan is to make a simple AI that record every player.positions, and then follow the player by using those positions. So the AI will always be some steps behind the player. But when the player stops moving the AI should collide with player and then the player dies.
So my problem is when the player has been chased down by the AI, but it always runs out of position before the enemy AI is ever able to touch the player...
I used Queue for making a list of position, this was recommended by someone after I tried with List<>.
Here's a video showing the problem
public Transform player;
public Transform ghostAI;
public bool recording;
public bool playing;
Queue<Vector2> playerPositions;
public bool playerLeftRadius;
void Start()
{
playerPositions = new Queue<Vector2>();
}
// Update is called once per frame
void Update()
{
if (playerLeftRadius == true)
{
StartGhost();
}
Debug.Log(playerPositions.Count);
}
private void FixedUpdate()
{
if (playing == true)
{
PlayGhost();
}
else
{
Record();
}
}
void Record()
{
recording = true;
playerPositions.Enqueue(player.transform.position);
}
void PlayGhost()
{
ghostAI.transform.position = playerPositions.Dequeue();
}
public void StartGhost()
{
playing = true;
}
public void StopGhost()
{
playing = false;
}
private void OnTriggerExit2D(Collider2D other)
{
Debug.Log("Player leaved the zone");
playerLeftRadius = true;
}
How do improve it so it will be able to touch the player?
At the moment the player touch the zone, method OnTriggerExit2D() is called. Then, method PlayGhost() is called and Record() is stoped. So, the ghost can't record player.positions after player out zone.
You can remove else in method FixedUpdate() to fix it.
private void FixedUpdate()
{
if (playing == true)
{
PlayGhost();
}
Record();
}

Collider won't trigger if my player isn't moving in 2D

PLAYER = Ninja Boy
ENEMY = Ninja girl
I have two game objects, one is enemy and the other is player both having colliders2D and rigidbody2D.
I made a script for enemy chase my when i;m in his sight(i made a boxcollider2d for this) and when he's close enought he start's attacking. To detect collision between he's sword and me i made an edge collider that he enables it when starts attacking and disable when the attack animation is done
The problem is that when i don't move, the player OnEnterTrigger2D function doesn't detect the collision
if i'm in this position (the player is clearly inside the collider)
This is the Player class
public override IEnumerator TakeDamage()
{
if (!immortal && !IsDead)
{
health -= 10;
Animator.SetLayerWeight(1, 0);
if (!IsDead)
{
Animator.SetTrigger("damage");
Rigidbody.velocity = Vector2.zero;
immortal = true;
yield return new WaitForSeconds(immortalTimer);
immortal = false;
}
}
if(IsDead)
{
Animator.SetTrigger("dead");
}
}
protected override void OnTriggerEnter2D(Collider2D collider)
{
Debug.Log(collider.name);
base.OnTriggerEnter2D(collider);
}
and the player inherits from Character
public abstract IEnumerator TakeDamage();
protected virtual void OnTriggerEnter2D(Collider2D collider)
{
if (damagingObjects.Contains(collider.tag))
{
StartCoroutine(TakeDamage());
}
}
and i noticed that if a manualy activate the enemy's trigger while playing, the player will take damege even if he's not moving

Prefabs don't sync for different players

I have Bullet prefab with Network Transform and Network Identity.
Player script for spawn bullet:
using UnityEngine;
public class Weapon : MonoBehaviour {
bool ready = true;
public Transform firePoint;
public bool shot;
public GameObject bulletPrefab;
void FixedUpdate () {
if ((Input.GetKey(KeyCode.Space)) || shot)
{
if (ready)
{
Shoot();
}
else
{
// click sound
}
}
}
void Shoot()
{
ready = false;
var bulletGo = Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);
LeanTween.delayedCall(6f, () => { ready = true; });
}
}
But when I shoot, my enemy don't see this bullet.
Why it doesn't sync? My player also has Network Transform and Network Identity, and all is ok.
To spawn a networked object Unity provides a specific function NetworkServer.Spawn (https://docs.unity3d.com/ScriptReference/Networking.NetworkServer.Spawn.html)
This function needs to be called after you instantiate an object so that all the clients spawn it in their scene.
In your case, after you instantiate your bulletGo object you should call:
NetworkServer.Spawn(bulletGo)

Destroy particle system when initalised programmatically

I have a game with a player and an enemy.
I also have a particle system for when the player dies, like an explosion.
I have made this particle system a prefab so I can use it multiple times per level as someone might die a lot.
So in my enemy.cs script, attached to my enemy, I have:
public GameObject deathParticle;
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.name == "Player" && !player.dead){
player.dead = true;
Instantiate(deathParticle, player.transform.position, player.transform.rotation);
player.animator.SetTrigger("Death");
}
}
So this plays my particle system when the player gets killed by an enemy. Now on my player script, I have this. This specific function gets played after the death animation:
public void RespawnPlayer()
{
Rigidbody2D playerBody = GetComponent<Rigidbody2D>();
playerBody.transform.position = spawnLocation.transform.position;
dead = false;
animator.Play("Idle");
Enemy enemy = FindObjectOfType<Enemy>();
Destroy(enemy.deathParticle);
}
This respawns the player like normal but in my project each time I die I have a death (clone) object which I don't want. The last 2 lines are meant to delete this but it doesn't.
I have also tried this which didn't work:
Enemy enemy = FindObjectOfType<Enemy>();
ParticleSystem deathParticles = enemy.GetComponent<ParticleSystem>();
Destroy(deathParticles);
There is no need to Instantiate and Destroy the death particle, that will create a lot of overhead, you can simply replay it when you want it to start and stop it, when you dont need it
ParticleSystem deathParticleSystem;
private void OnTriggerEnter2D(Collider2D collision)
{
#rest of the code
deathParticleSystem.time = 0;
deathParticleSystem.Play();
}
public void RespawnPlayer()
{
//rest of the code
deathParticleSystem.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
}
or you can enable and disable the gameObject associated with your particle prefab
public GameObject deathParticlePrefab;
private void OnTriggerEnter2D(Collider2D collision)
{
#rest of the code
deathParticlePrefab.SetActive(true);
}
public void RespawnPlayer()
{
//rest of the code
deathParticlePrefab.SetActive(false);
}
You could always create a new script and assign it to the prefab that destroys it after a certain amount of time:
using UnityEngine;
using System.Collections;
public class destroyOverTime : MonoBehaviour {
public float lifeTime;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
lifeTime -= Time.deltaTime;
if(lifeTime <= 0f)
{
Destroy(gameObject);
}
}
}
So in this case you would assign this to your deathParticle. This script is useful in a multitude of scenarios if you're instantiating objects so that you don't have a load of unnecessary objects.

Audio play issue on button click

I'm working with unity and have problem with audio. Here is scenario when user click on button, Object falls on ground and destroy. When click on button sound effect of object falling is play. And destroy, Object is instantiate again then same click sound effect is play again. But when one object is falling and does not collide at this time user click again that button sound play again. I want that when one object is complete destroy than again click happen and sound is play.
Code CubeScript:
public class Cube : MonoBehaviour {
Rigidbody2D body;
void Start () {
body = GetComponent<Rigidbody2D>();
body.isKinematic = true;
}
}
Code ColliderScript:
public class Ground : MonoBehaviour {
private Button bt;
public GameObject cube;
public AudioSource source;
public AudioClip clip;
void Start () {
bt = GameObject.FindGameObjectWithTag ("Button").GetComponent<Button> ();
bt.onClick.AddListener (() => Fall ());
}
void OnCollisionEnter2D(Collision2D col) {
Destroy (col.gameObject);
Instantiate (cube,new Vector3(0f,4.19f,0f),Quaternion.identity);
}
public void Fall(){
GameObject.FindGameObjectWithTag ("Player").GetComponent<Rigidbody2D> ().isKinematic = false;
source.PlayOneShot(clip);
}
}
void OnCollisionEnter2D(Collision2D col) {
Destroy (col.gameObject);
Instantiate (cube,new Vector3(0f,4.19f,0f),Quaternion.identity);
isFalling = false; // here
}
private bool isFalling = false; // here
public void Fall()
{
GameObject.FindGameObjectWithTag ("Player").GetComponent<Rigidbody2D> ().isKinematic = false;
if(isFalling == false){
source.PlayOneShot(clip);
isFalling = true; // here
}
}
Pretty much when you press, it calls Fall, if nothing is falling down, the sound happens. On Collision, the isFalling is reset. Tho I am not entirely sure about your logic.

Categories