Need to disable Particle System as soon as it stops playing - unity3d

I am trying to implement a Flame Thrower. I have setup the Particle System for flame. It is pooled object. It is not the child of the Flame Thrower. When I press the Fire button the particle system starts and when the button is up it stops. But a problem arised that when player is moving the particle system doesn't move . this was solved by adding the below line
particles.transform.position = transform.GetChild(0).position;
But the I discovered another problem that when rotating the player(This is a 2D sidescroller game) the particles are rotated with it instantly. So when the player changes the direction current particles are stopped and a new particle is activated and played. But now the problem is whenever I change the direction while pressing Fire buttons new objects are created.
The code of my flame thrower is
using UnityEngine;
public class FlameThrower : Gun
{
private ParticleSystem particles;
private int direction = 0;
private bool isFiring = false;
public override void Update()
{
if(shoot)
{
InitShoot();
}
else
{
StopFire();
}
}
public override void InitShoot()
{
if(!isFiring)
{
SelectDirection();
Fire();
}
//Check direction has changed
if(direction != playerManager.direction)
{
StopFire();
}
if(particles != null)
{
particles.transform.position = transform.GetChild(0).position;
}
}
public override void Fire()
{
isFiring = true;
direction = playerManager.direction;
InstantiateParticles(weapon.bulletName, transform.GetChild(0).position, rotation);
}
public override void SelectDirection()
{
if (playerManager.direction == 1)
{
rotation = Quaternion.Euler(transform.rotation.x, transform.rotation.y, -90);
}
else if (playerManager.direction == -1)
{
rotation = Quaternion.Euler(transform.rotation.x, transform.rotation.y, 90);
}
}
public override void InstantiateParticles(string name, Vector3 position, Quaternion rotation)
{
GameObject bullet = ObjectPooler.instance.GetObject(name);
while (bullet == null)
{
ObjectPooler.instance.CreateObject(name);
bullet = ObjectPooler.instance.GetObject(name);
}
if (bullet != null)
{
particles = bullet.GetComponent<ParticleSystem>();
//Set Position and rotation
bullet.transform.position = position;
bullet.transform.rotation = rotation;
bullet.SetActive(true);
particles.Play();
}
}
private void StopFire()
{
if (particles != null)
{
isFiring = false;
particles.Stop();
if(!particles.isPlaying)
{
particles.gameObject.SetActive(false);
particles = null;
}
}
}
}
The problem is that in the function StopFire() it checks whether particle is playing or not. If it is not playing it will disable the Gameobject. But it that part doesn't execute since it is checked soon after particles is stopped and it will still be playing. I want this particle system to be disabled as soon as it stops playing

It seems that the particle system is rendering in local space, that's why it rotates with the object.
Change the Simulation Space to World.
For the other issue, if you disable the game object then particles which are already emitted will disappear. And if you deactivates them with a delay (using Invoke or similar) then within that delay new particles can be emitted.
The best way to handle this is to stop the emission, not deactivating the game object. You can do this in inspector or via code. myParticles.emission.enabled

using UnityEngine;
public class ParticleSystemControllerWindow : MonoBehaviour
{
ParticleSystem system
{
get
{
if (_CachedSystem == null)
_CachedSystem = GetComponent<ParticleSystem>();
return _CachedSystem;
}
}
private ParticleSystem _CachedSystem;
public Rect windowRect = new Rect(0, 0, 300, 120);
public bool includeChildren = true;
void OnGUI()
{
windowRect = GUI.Window("ParticleController".GetHashCode(), windowRect, DrawWindowContents, system.name);
}
void DrawWindowContents(int windowId)
{
if (system)
{
GUILayout.BeginHorizontal();
GUILayout.Toggle(system.isPlaying, "Playing");
GUILayout.Toggle(system.isEmitting, "Emitting");
GUILayout.Toggle(system.isPaused, "Paused");
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if (GUILayout.Button("Play"))
system.Play(includeChildren);
if (GUILayout.Button("Pause"))
system.Pause(includeChildren);
if (GUILayout.Button("Stop Emitting"))
system.Stop(includeChildren, ParticleSystemStopBehavior.StopEmitting);
if (GUILayout.Button("Stop & Clear"))
system.Stop(includeChildren, ParticleSystemStopBehavior.StopEmittingAndClear);
GUILayout.EndHorizontal();
includeChildren = GUILayout.Toggle(includeChildren, "Include Children");
GUILayout.BeginHorizontal();
GUILayout.Label("Time(" + system.time + ")");
GUILayout.Label("Particle Count(" + system.particleCount + ")");
GUILayout.EndHorizontal();
}
else
GUILayout.Label("No particle system found");
GUI.DragWindow();
}
}
This might help you in playing,pausing and fully stopping your particle system from emitting particles.
Hope i helped.

Related

Difficulties flipping a collider in Unity when attacking

I am working on a small game for a school project, in which my player needs to attack enemies in a level. My plan is to have a collider that is enabled in an attached script, and then disabled when the attack is done. My current problem is that that the collider does not flip the way it is supposed to, it seems to flip directly on the overall x axis instead of flipping in the x axis related to the player. It is a child of the player so I am clueless as to why it is doing this. Any solutions or other approaches would be greatly appreciated. I will attach the current script that controls the collider below.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class VerticalSword : MonoBehaviour
{
//Variables use to active the colliders
Collider2D AttackColliderVertical;
//Variables for the location of the collider
Vector2 attackOffset;
private void Start()
{
AttackColliderVertical = GetComponent<Collider2D>();
attackOffset = transform.position;
AttackColliderVertical.enabled = false;
}
public void FixedUpdate()
{
attackOffset = transform.position;
}
public void AttackUp()
{
AttackColliderVertical.enabled = true;
if (attackOffset.y > 0)
{
transform.position = attackOffset;
}
else if (attackOffset.y < 0)
{
transform.position = new Vector2(attackOffset.x, (attackOffset.y * -1)); //I think the problem is somewhere in this if and else if statement
}
print("Attack up successful"); //Error checking (This works when run)
}
public void AttackDown()
{
AttackColliderVertical.enabled = true;
if (attackOffset.y > 0)
{
transform.position = new Vector2(attackOffset.x, (attackOffset.y * -1));
}
else if (attackOffset.y < 0)
{
transform.position = attackOffset; //I think the problem is somewhere in this if and else if statement
}
print("Attack down successful"); //Error checking (This works when run)
}
public void StopAttack()
{
AttackColliderVertical.enabled = false;
}
}
Use transform.localPosition, not transform.position (that's its world space position). You need to change it everywhere in this script; the Start() function and the two attack functions

I want set 30 rpm in Wheel Collider

I have a robot with a wheel to which I have applied a script to rotate the wheel and a "wheel collider" component with these values:
I would like to know what values ​​I have to modify to get the robot wheel to rotate at 30 rpm, since it is going to move around an office and it is seen to rotate very fast.
Finally, since it was a simple wheel and I just wanted it to give the effect of simple movement, what I did was this script.
public class WheelRotateAroundCylinder : MonoBehaviour
{
private Transform wheel;
private bool rotate = false;
private void Awake()
{
wheel = transform;
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if(rotate)
{
wheel.Rotate(0, -2, 0);
}
else
{
wheel.Rotate(0, 0, 0);
}
}
public void isRotate(bool hasRotate)
{
if(hasRotate)
{
this.rotate = true;
}
else
{
this.rotate = false;
}
}
}

Problem with Colliders and their rotation in the Unity Game

The problem is that I what to create an openable door. This door should open when the player enter the Box Collider which is connected to the door. But the problem is when the door begins to open and to rotate, Collider starts to rotate too which brings me a lot of problems with usind such an idea. I try to create EmptyObject with its Collider but I can't connect this Collider with script and OnTriggerEnter function itself. Maybe I don't understand something, who knows, I'm just a begginer. How knows how to help, please write an answer.
My code if somebody needs it:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class openDoor : MonoBehaviour {
public Vector3 Rotation_;
private int i;
public float speed;
bool opentheDoor;
bool closetheDoor;
// Use this for initialization
void Start () {
opentheDoor = false;
closetheDoor = false;
}
// Update is called once per frame
void Update () {
if (opentheDoor == true) {
this.transform.Rotate (Rotation_ * Time.deltaTime * speed);
i += 1;
if (i == 70) {
opentheDoor = false;
i = 0;
}
}
if (closetheDoor == true) {
this.transform.Rotate (-Rotation_ * Time.deltaTime * speed);
i += 1;
if (i == 70) {
closetheDoor = false;
i = 0;
}
}
}
void OnTriggerEnter (Collider other) {
if (other.gameObject.tag == "Player") { {
opentheDoor = true;
}
}
}
void OnTriggerExit (Collider other) {
if (other.gameObject.tag == "Player") {
closetheDoor = true;
}
}
}
This is how i would handle the scenerio
Take
DoorHandler.cs
public class DoorHandler : MonoBehaviour {
public Door door;
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
door.OpenDoor();
}
}
}
This should be attached to Parent of the door.
Next Take
Door.cs
public class Door : MonoBehaviour {
public bool isOpened = false;
public void OpenDoor()
{
if (!isOpened)
{
isOpened = true;
Debug.Log("OPEN");
//OPEN DOOR CODE!
}
}
}
Attach this to the Door GameObject
NOTE
The hierarchy would be like DoorHandler->Door->DoorModel (where Door is just an empty gameobject pivot of the Door)
In DoorHandler GameObject attach BoxCollider and Check Mark IsTrigger.
Also Player SHOULD HAVE A RIGIDBODY (preferably Kinametic) and obviously a collider
So When Player enters the DoorHandler's Collider -> The DoorHandler's OnTriggerEnter will be triggered and finally Call the Door to OpenDoor()
Add another check in OnTriggerEnter that checks if the door is currently opening or not.
void OnTriggerEnter (Collider other) {
if (other.gameObject.tag == "Player" && !opentheDoor) {
opentheDoor = true;
}
}
attach the door to an empty object. put the trigger on the empty object. then make the ontrigger entry rotate the door, not the paent object, and the collider will remain in place.
Parent
-child(door)
-child(collider)

want to get screen point on render texture camera unity3d

I am making sniper game, I have 2 cameras, one is rendering whole environment, and second one is in scope of the gun, which has high zoom quality.
I am able to show, enemy point on screen through main camera. and it shows proper on main camera, but in scope camera(2nd camera), it not showing properly. I want to show these points exactly same as enemy is.
here is my script to show point so far. I am attaching screen shots, first one is for scope camera and does not showing proper place, and 2nd one is for main camera, showing at proper place (Red circle is pointing)
using UnityEngine;
using UnityEngine.UI;
public class identity_shower : MonoBehaviour {
public Texture tex;
public GameObject helt;
public bool target_is_high =false;
private int counter_for_high = -1;
private int counter_for_low = -1;
private int counter_value = 50;
private bool bool_for_high = false;
private bool bool_for_low = false;
private Camera scope_cam_active;
private RectTransform rectTransform;
private Vector2 uiOFFset;
// Update is called once per frame
void OnGUI()
{
GameObject[] objs = GameObject.FindGameObjectsWithTag("enemy_soldier");
if( objs.Length<=0 )
{
return;
}
if (bool_for_high)
{
Vector2 pos_to_display = Camera.main.WorldToScreenPoint (this.transform.position);
GUI.DrawTexture (new Rect(pos_to_display.x-10.0f,(Screen.height- pos_to_display.y)-40.0f,15,15),tex);
}
}
public void show_your_identity()
{
if (target_is_high) {
if (counter_for_high >= counter_value)
{
return;
}
counter_for_high = counter_for_high + 1;
if (counter_for_high >= counter_value)
{
bool_for_high = true;
}
} else if(!target_is_high)
{
if (counter_for_low >= counter_value)
{
return;
}
counter_for_low = counter_for_low + 1;
if (counter_for_low >= counter_value)
{
bool_for_low = true;
}
}
}
}

Physics.CheckSphere always give false (Unity3D)

I'm trying to create objects that mark the cell that I can visit. I mark them with red square:
My code for creating objects:
using UnityEngine;
using System.Collections;
using System;
public class SpawnCheck : MonoBehaviour {
public GameObject checkObject;
public bool canSpawnCheck = true;
Vector2 boxSize;
public GameObject spawnedObject;
// Use this for initialization
void Start () {
Debug.Log("Into spawn check");
}
void OnTriggerEnter2D(Collider2D other) {
Debug.Log("Enter trigger collision");
canSpawnCheck = false;
if (other.gameObject.tag == "Target") {
Debug.Log ("Found Target");
}
if (other.gameObject.tag == "Wall") {
canSpawnCheck = false;
}
if (other.gameObject.tag == "Check") {
canSpawnCheck = false;
}
}
void OnTriggerExit2D(Collider2D other) {
Debug.Log("Exit trigger collision");
canSpawnCheck = true;
}
// Update is called once per frame
void Update () {
Debug.Log ("canSpawnCheck " + canSpawnCheck);
if (canSpawnCheck == true) {
Vector3 currentPosition = this.gameObject.transform.position;
Vector3 spawnPos = new Vector3 (Mathf.Round (currentPosition.x), Mathf.Round (currentPosition.y),0);
Debug.Log ("Physics.CheckSphere " + Physics.CheckSphere (spawnPos, 5));
if (!Physics.CheckSphere(spawnPos,5)) {
spawnedObject = (GameObject)Instantiate (checkObject, spawnPos, Quaternion.identity);
this.gameObject.GetComponentInParent<AILerp> ().possibleTargets.Add (spawnedObject);
}
}
}
}
My problem: as Physics.CheckSphere(spawnPos,5) always return false my code spawns too many red squares and spawn them upon each other. I want red squares to be created only once and never created on walls (white squares).
Your Check(Clone) GameObject has Box Collider 2D attached to it. Therefore every physics function you must use should be Physics2D.something not Physics.something. Notice the keyword there "2D".
If you use just Box Collider without the 2D in it, then you can use Physics.something. So, Physics.CheckSphere cannot be used with a 2D collider.
Check(Clone) is a SpriteRenderer, 2D Collider is appropriate. You just need to use one of the Physics2D overlap functions such Physics2D.OverlapBox, Physics2D.OverlapArea or Physics2D.OverlapCircle. Which ever one you prefer.