unity particle doen't play second time - c#

I have a particle system defined in my game objects. When I call Play it plays (it plays for 5 seconds by design). when I call Play again nothing happens. I tried to call Stop and Clear before recalling Play but that didn't help.
Can particle systems play more than once?
My code is in this method, which is called when a button is clicked.
public void PlayEffect()
{
for (int i=0;i<3;i++)
{
NextItemEffectsP[i].Stop();
NextItemEffectsP[i].Clear();
NextItemEffectsP[i].Play();
}
}
NextItemEffectsP is an array that contains particles that I populate in the editor

You should rework how your bullet works. Have some code on the bullet Prefab to control when it gets destroyed.
private float fuse = 1.0;
private float selfDestructTimer;
void Awake() {
// Time.time will give you the current time.
selfDestructTimer = Time.time + fuse;
}
void Update() {
if (selfDestructTimer > 0.0 && selfDestructTimer < Time.time) {
// gameObject refers to the current object
Destroy(gameObject);
}
}
Then with that control set up, you'll always just create new bullets whenever the fire button is pressed.

Related

Particle system unity not always showing, unity

So I'm trying to add a particle effect to a little space game of mine, I get axis "Vertical", then check if it is greater than 0 the particle system plays (going forward)
flyfloat = Input.GetAxis("Vertical");
if(flyfloat > 0)
{
particles.Play();
}
else
{
particles.Stop();
}
That controls whether it is playing the particle system, but the issue i have is that it only gives some particles and then stops, I've viewed the flyfloat and it is at 1.
What may the problem be here?
Thanks
You question is incomplete as for example I don't know where you are using these lines of code.. inside an Update() method or a Start() method.
Assuming you are calling it in Update() method. Let me explain first what is happening wrong here. So as Update() gets called each frame when you pressing UP_Arrow key flyfloat = 1 . that's ok but now as you go inside the if loop to check flyfloat > 0 and calls partciles.Play() it is being called every Update() loop means every frame so what's happening is your ParticleSystem is getting played every frame so not playing at all. Also whenever you stops pressing the UP_Arrow key the flyfloat = 0 for which it's going inside the else loop and stops playing the ParticleSystem.
So to solve this you can introduce a Boolean which makes partciles.Play() and partciles.Stop() gets called once when you are pressing UP_Arrow key.
below code will make the ParticleSystem play when you press UP_Arrow key and stops it when you press DOWN_Arrow key
public ParticleSystem particles;
public float flyfloat;
bool isParticlePlaying = false;
private void Update()
{
flyfloat = Input.GetAxis("Vertical");
if (flyfloat > 0 && !isParticlePlaying)
{
particles.Play();
isParticlePlaying = true;
}
else if (flyfloat < 0 && isParticlePlaying)
{
particles.Stop();
isParticlePlaying = false;
}
}

Unity attack once during animation

Since I am still very beginner question maybe dumb but I am really cant find any solution. I am creating 3rd person adventure game and trying to implement enemy attack. The problem is that I cannot implement it in a way that enemy do damage only once during attack animation. In my code alreadyAttacked bool is changing to false only when the transitions between animations happens. However I want to reset this value everytime when the attack animation starts or finish.
void FixedUpdate()
{
playerInSightRange = Physics.CheckSphere(transform.position, sightRange, playerMask);
playerInAttackRange = Physics.CheckSphere(transform.position, attackRange, playerMask);
if (!playerInSightRange && !playerInAttackRange) Patroling();
if (playerInSightRange && !playerInAttackRange) Chasing();
if (playerInSightRange && playerInAttackRange) Attacking();
}
private void Attacking()
{
animator.SetInteger("Condition", 2);
agent.SetDestination(player.position);
if (animator.GetCurrentAnimatorStateInfo(0).normalizedTime > 0.4f
&& animator.GetCurrentAnimatorStateInfo(0).normalizedTime < 0.6f
&& alreadyAttacked == false)
{
player.GetComponent<Health>().healthValue -= damage / 100f;
alreadyAttacked = true;
}
if (animator.GetCurrentAnimatorStateInfo(0).normalizedTime > 0.7f )
{
alreadyAttacked = false;
}
}
You might rather want to look into Animation Events.
Without having to query states from the Animator you can rather simply invoke certain events directly from your animation state itself!
Simply rather make it
public void CauseDamage()
{
if(player) player.GetComponent<Health>().healthValue -= damage / 100f;
}
and then in your animation itself add an Event
and select the method you want to call in the Event's inspector.
Then everytime your animation passes that key frame the event will be Invoked exactly once.

How to check if a certain animation state from an animator is running?

I created an animator called "m4a4animator". Inside it, the main function is called "idle" (nothing), and other 2 states: "shoot" (mouse0) and "reload" (R). These 2 animation states are transitioned to "idle". Now, everything is working... but the only problem I have is this: if I am in the middle of reloading and and press mouse0 (shoot), the animation running state immediately changes to shoot... but I want to block that.
Now, the question: How can I stop CERTAIN animation changes while an animation is running?
Here is my animator
And here is my script:
using UnityEngine;
using System.Collections;
public class m4a4 : MonoBehaviour {
public Animator m4a4animator;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown (KeyCode.R)) {
m4a4animator.Play("reload");
}
if (Input.GetMouseButton(0)) {
m4a4animator.Play("shoot");
}
}
}
For the legacy Animation system, Animation.IsPlaying("TheAnimatonClipName) is used to check if the animation clip is playing.
For the new Mechanim Animator system, you have to check if both anim.GetCurrentAnimatorStateInfo(animLayer).IsName(stateName) and anim.GetCurrentAnimatorStateInfo(animLayer).normalizedTime < 1.0f) are true. If they are then animation name is currently playing.
This can be simplified like the function like the Animation.IsPlaying function above.
bool isPlaying(Animator anim, string stateName)
{
if (anim.GetCurrentAnimatorStateInfo(animLayer).IsName(stateName) &&
anim.GetCurrentAnimatorStateInfo(animLayer).normalizedTime < 1.0f)
return true;
else
return false;
}
Now, everything is working... but the only problem I have is this: if
I am in the middle of reloading and and press mouse0 (shoot), the
animation running state immediately changes to shoot... but I want to
block that.
When the shoot button is pressed, check if the "reload" animation is playing. If it is, don't shoot.
public Animator m4a4animator;
int animLayer = 0;
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.R))
{
m4a4animator.Play("reload");
}
//Make sure we're not reloading before playing "shoot" animation
if (Input.GetMouseButton(0) && !isPlaying(m4a4animator, "reload"))
{
m4a4animator.Play("shoot");
}
}
bool isPlaying(Animator anim, string stateName)
{
if (anim.GetCurrentAnimatorStateInfo(animLayer).IsName(stateName) &&
anim.GetCurrentAnimatorStateInfo(animLayer).normalizedTime < 1.0f)
return true;
else
return false;
}
If you need to wait for the "reload" animation to finish playing before playing the "shoot" animation then use a coroutine. This post described how to do so.
There are other threads about that: https://answers.unity.com/questions/362629/how-can-i-check-if-an-animation-is-being-played-or.html
if (this.animator.GetCurrentAnimatorStateInfo(0).IsName("YourAnimationName"))
{
//your code here
}
this tells you if you are in a certain state.
Animator.GetCurrentAnimatorStateInfo(0).normalizedTime
this give you the normalized time of the animation: https://docs.unity3d.com/ScriptReference/AnimationState-normalizedTime.html
Try to play with those function, I hope that solve your problem

Play sound while button is held down

I have a 1.5 seconds audio file - a single gunshot sound. I want to be able to play the sound while the mouse is pressed (like an automatic weapon), and I used InvokeRepeating to call the shoot method, with a very low repeatRate:
if (Input.GetButtonDown("Fire1"))
{
InvokeRepeating("Shoot", 0f, 1f/currentWeapon.fireRate);
} else if (Input.GetButtonUp("Fire1"))
{
CancelInvoke("Shoot");
}
And this is the Shoot method:
void Shoot()
{
shootSound.PlayOneShot(shoot);
}
The problem is the sound cuts off and the shot can't be heard, it's playing for a fraction of a second instead of the whole audio clip. I tried play() and playOneShot().
Is there an option to play each clip to its fullest separately, like creating clones of it?
Thanks!
Most things in your code are just unnecessary. You don't need InvokeRepeating for this. Since you want to continue to player sound(shooting effect) while the button is held down, Input.GetButton should be used instead of Input.GetButtonDown because Input.GetButton is true every frame the button is held down and is made for things like auto fire.
A simple timer with Time.time should also be used to determine the rate to play the sound then play the sound with the PlayOneShot function.
This is what that should look like:
public float playRate = 1;
private float nextPlayTime = 0;
public AudioSource shootSound;
public AudioClip shoot;
void Update()
{
if (Input.GetButton("Fire1") && (Time.time > nextPlayTime))
{
Debug.Log("Played");
nextPlayTime = Time.time + playRate;
shootSound.PlayOneShot(shoot);
}
}
The playRate variable is set to 1 which means 1 sound per-sec. You can use this variable to control the play rate. Lower it to play many sounds. The value of 0.1f seems to be fine but it depends on the sound.
I solved it, I used an empty GameObject with an AudioSource, and instantiated a copy of it in each Shoot method:
GameObject gunObj = Instantiate(gunObject);
Destroy(gunObj, 1f);
Works perfectly now!

Unity How to play a particle system effect if when the parent get's disabled?

How to play a particle system effect if when the parent get's disabled?
I want to play a particle system effect in the position of my obstacle. The problem is that my particle if the child of my object and when i disable the parent(object) the particle system get's disabled with it and does'nt play the affect
How can i play the effect in the same position of the obstacle and when the obstacle get's disabled/ Destroyed.
Create GameObject called ParticlesHolder. Attach the script below to it then make sure to change the size from the Editor to 2. Put the two Particles to each slot. The idea is that the particle won't be disabled.
public class ParticleHolder : MonoBehaviour
{
public ParticleSystem[] effects;
public void playParticle(int particleNumber, Vector3 particlePos)
{
if (effects != null && effects[particleNumber] != null)
{
if (effects[particleNumber].isPlaying)
effects[particleNumber].Stop();
ParticleSystem tempPart = Instantiate(effects[particleNumber], particlePos, new Quaternion()) as ParticleSystem;
tempPart.Play();
}
}
}
Now, add the code below to the code in your Example script:
ParticlesContainer particle;
In your Start() function:
particle = GameObject.Find("ParticlesHolder").GetComponent<ParticlesContainer>();
In your OnCollisionEnter() function:
particle.playParticle(0, transform.position);
In this example, the first particle in the array would play.
If there are two particles, 0 and 1 are both valid values to pass in. If there are 3 particles then 0,1,2 are the three values to pass in.
Just like you have public void SetDamage(int a_damage) function, you can add public void SetParticle(int particleId) function to set which particle to play.

Categories