質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

15292閲覧

パーティクルを一瞬だけ表示させたい。

退会済みユーザー

退会済みユーザー

総合スコア0

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2016/09/27 13:42

編集2016/09/30 16:12

###前提・実現したいこと
キー入力とUpdateとLateUpdateを利用して、パーティクルを一瞬だけ表示したいと考えています。

仕様:
Fキーを押した瞬間だけ、指定した再生位置でパーティクルを表示する。それ以外の時はパーティクルは非表示。

###試したこと

以下のようなコードを組んでゲームを実行してみましたが、意図通りの結果になりません。

C#

1 void Start(){ 2 pObject = GameObject.Find ("Particle System"); 3 particle = pObject.GetComponent<ParticleSystem> (); 4 5 particle.Simulate(0.0f,true,true); 6 particle.Stop (); 7 } 8 9 void Update(){ 10 if (Input.GetKeyDown (KeyCode.F)) { 11 if (particle.isStopped || particle.isPaused) { 12 particle.Simulate(3.0f,true,true); 13 particle.Play (); 14 Debug.Log ("A"); 15 } 16 } 17 } 18 19 void LateUpdate(){ 20 if (particle.isPlaying) { 21 particle.Stop (); 22 Debug.Log ("B"); 23 } 24 }

###発生している問題・エラーメッセージ

最初にFキーを押すとパーティクルは表示されて消えるが、その後、何度かFキーを押してみると、
パーティクルが表示される時と表示されない時がある。
また、パーティクルが表示されても、一瞬だけ表示しているようには見えず、表示されている時間が少し長い気がする。

また、コードでログを取ってみると、パーティクルが表示されていないときでも、「B」の出力が出続けます。
それならば、同じif文内の「particle.Stop();」が効いて、次のLateUpdateでは「if(particle.isPlaying)」の
if文に引っ掛からないはずなのに、何故か、そのif文に引っ掛かって「B」が連続して出力されます。
この辺りの挙動がわからないです。

キー入力でパーティクルを一瞬だけ表示する方法ならば、他にも方法があるのかもしれないですが、現状から、次の2点に関して教えていただきたいです。

・今回のソースコードでうまくいかない原因。 特に、「if(particle.isPlaying)」のif文に引っかかり続けているにも関わらず 「particle.Stop();」が効かない理由。 ・UpdateとLateUpdateを利用して、キー入力でパーティクルを一瞬表示させる方法。 (今回のコードの修正方法。)

しかし、UpdateとLateUpdateを使う仕様自体がbad codeであるのならば、代替の方法を教えて頂きたいです。

ご教授のほどよろしくお願いします。

###追記①
ご回答ありがとうございます。追記しました。

C#

1 //ここでパーティクルが停止される時間を指定 2 float particleDelayTime = .2f; 3 4 void Awake() 5 { 6 pObject = GameObject.Find ("Particle System"); 7 particle = pObject.GetComponent<ParticleSystem> (); 8 particle.gameObject.SetActive(false); 9 } 10 11 void Update() 12 { 13 if (Input.GetKeyDown ("f") && particle.isStopped) { 14 particle.gameObject.SetActive (true); 15 particle.Simulate (4.0f, true, true); //追記。 16 particle.Play (); //追記。 17 StartCoroutine (delay (particleDelayTime, () => { 18 particle.gameObject.SetActive (false); 19 })); 20 //for Debug 21 Debug.Log ("A"); 22 } 23 } 24 25 IEnumerator delay(float waitTime, UnityAction action) 26 { 27 yield return new WaitForSeconds(waitTime); 28 action(); 29 }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

[追記]ご指摘いただきました「指定した再生位置でパーティクルを表示する」という内容を踏まえてソースを少し修正しました。

Fキーを押した瞬間だけ、パーティクルを表示する。それ以外の時はパーティクルは非表示。

それだけでよければ以下コードでいけます。適当なオブジェクトに以下コードをアタッチしてインスペクタ上から該当パーティクルを指定してください。

※パーティクルが設定されたオブジェクトに以下スクリプトをアタッチしても動かないと思うので、パーティクルが指定されたオブジェクト以外にアタッチしてください。

###実装のポイント
パーティクルシステムをplay / stopしなくても、オブジェクトを非表示にすると勝手に止まります。その状態で再表示すると勝手に始まります。それを利用した実装になります。

C#

1using UnityEngine; 2using System.Collections; 3using UnityEngine.Events; 4 5public class particleForFkey : MonoBehaviour { 6 7 //他で使うかもしれないのでParticleSystemを指定してますが以下コードで問題なければGameObjectに書き直してもいいです。 8 [SerializeField] 9 ParticleSystem pObject; 10 11 //ここでパーティクルが停止される時間を指定 12 float particleDelayTime = .2f; 13 14 void Awake() 15 { 16 pObject.gameObject.SetActive(false); 17 } 18 19 void Update() 20 { 21 if (Input.GetKeyDown(KeyCode.F) && pObject.isStopped){ 22 pObject.gameObject.SetActive(true); 23 pObject.Simulate(4.0f, true, false); //追記 24 pObject.Play(); //追記 25 StartCoroutine(delay(particleDelayTime,()=>{ 26 pObject.gameObject.SetActive(false); 27 })); 28 //for Debug 29 Debug.Log ("A"); 30 } 31 } 32 33 IEnumerator delay(float waitTime,UnityAction action) 34 { 35 yield return new WaitForSeconds(waitTime); 36 action(); 37 } 38}

投稿2016/09/27 15:42

編集2016/09/28 17:00
IShix

総合スコア1724

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/09/28 12:54 編集

ご回答ありがとうございます。説明不足ですみません、パーティクルの表示は指定した再生位置で表示したいと思っています。追記したコードで合っているかご確認いただけますか? (SetActive(true)後に、再生位置を指定して再生という流れで良いですか?)
IShix

2016/09/28 17:11

すみません。ちゃんと質問読んでなかったようです。合わせてコードも修正しました。 あと、追記で記入しているコードで問題ないと思いますが、僕が書いたコードが(Input.GetKeyDown ("f")になっていたので元のInput.GetKeyDown(KeyCode.F)でいいと思います。そして、 pObject = GameObject.Find ("Particle System"); particle = pObject.GetComponent<ParticleSystem> (); 数が少なければ問題ないですが、Find()は結構遅いです。スクリプトからオブジェクトを取得したい場合はタグをつけてFindGameObjectWithTagで取得するのが最速です。今はFindでいいと思いますが後々アプリ立ちあげ時のMonoのCPU使用率が大きくなるようでしたら修正を検討してみてください。
退会済みユーザー

退会済みユーザー

2016/09/29 15:56 編集

ご回答ありがとうございます。ご指摘ありがとうございます。 早速、FindGameObjectWithTagを使ってみました。 さらに質問で恐縮ですが、これの応用として、パーティクルの連射表示みたいなことをしたいと思っています。 Fキーを押した瞬間だけの表示をやめて、Fキーを押しっぱなしにしている間、パーティクルの一瞬表示が、連続的に起こるものです(particleDelayTimeを短めにして、パーティクルを高速点滅させるイメージです)。 これは、コードを「Input.GetKeyDown」から「Input.GetKey」に変えるだけの修正で大丈夫ですか? 追記②に詳細を書きました。 今は安定していますが、最初に何回かテストしたところ、パソコンの性能のせいなのか、 particleDelayTimeが.01fなど短めだと、Fキー押しっぱなしの間、周期的に点滅が止まる挙動がありました。(しかし、今テストしてる限り、同じコードなのにそれが解消されてきました。) それとも、他にもコードで修正すべき点がありますか? また、パーティクルはいつも同じ再生位置から表示したいと思っているので、その場合は Simulateの第3引数をtrueにすれば大丈夫ですか?
IShix

2016/09/30 13:44

お手数ですが、内容が変わってきているので一度こちらを閉じて再質問していただいても良いですか?あと、しばらく触れなそうなので返答遅れます。
退会済みユーザー

退会済みユーザー

2016/09/30 13:47

ご回答ありがとうございます。いろいろ質問してしまってすみません。 ご教授くださりありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問