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

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

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

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

Q&A

解決済

1回答

2055閲覧

【Unity】コンポーネントの全ての値を保持する方法について

Y0241-N

総合スコア1066

Unity

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

0グッド

0クリップ

投稿2021/06/07 09:18

編集2021/06/08 01:51

前提・実現したいこと

実際にやりたい事としては、まず初めにParticleのすべての値を保持し、TimelineでClip再生中にParticleに変更を加え、Clipの再生が終了したタイミングで最初に保持した値に戻す。(例:再生前 startLifeTime = 1. 再生中 10, 再生後 1)
ということが実現したい事となります。

startLifeTimeだけ保持するのでなく、まるっとコンポーネントの値を保持したい理由はClipごとにどのような変化を行うは想定していないためです。

要はEditor上でCopy Componentすることをスクリプト上でやりたいのですが、Copy ComponentはEitorに依存しているので、仮にスクリプト上でCopy Componentが出来ても、出力後では使えなくなると思います。

なので、とりあえず最初にデフォルト値として保持しておきたいParticle Systemコンポーネントを別変数で複製し、そのあとにコピー元のParticle Systemの値を変更し、コピーした物を再度受け渡せば出来るんじゃないか。と思ったのですが、コピー元を変更するとコピーした方も値が変更されてしまっていてダメでした。

なにかコピー元に変更を加えてもコピー先も値が変更しないように保持する方法はありますでしょうか?

該当のソースコード

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Playables; using UnityEngine.Timeline; // A behaviour that is attached to a playable public class ControllParticleBehaviour : PlayableBehaviour { public GameObject particleObject{get; set;} public ParticleSystem particle; public ParticleSystem copyPV; public Transform playPos; public bool isPlayOfPlayback; public PostPlaybackEnum PostPlayback; public enum PostPlaybackEnum { Active, //クリップを抜けた後もアクティブにする NonActive, //クリップを抜けた後は非アクティブにする Delete, //クリップを抜けた後は対称を破棄する Revert //クリップを抜けた後は元の値に戻す } // クリップに入った時に走らせる処理 public override void OnBehaviourPlay(Playable playable, FrameData info) { if(particle != null) { copyPV = particle; Debug.Log(copyPV.main.startLifetime.constant); //particle の startLifetime が 「1」 だとして、ここでは copyPV の startLifetime はまだ 1 if(playPos != null) { particleObject.transform.position = playPos.position; } Debug.Log("Start"); particleObject.SetActive(true); ParticleSystem.MainModule par = particle.main; par.startLifetime = 10; Debug.Log(copyPV.main.startLifetime.constant + " / 2"); // ここですでに copyPV の startLifetime は 10 になっている particle.Play(); } } // クリップを抜ける際に走らせる処理 public override void OnBehaviourPause(Playable playable, FrameData info) { if(particle.isPlaying && PostPlayback == PostPlaybackEnum.Revert && copyPV != null) { Debug.Log("!"); particle = copyPV; //ここで particle の値を再生前の値に戻したい Debug.Log(copyPV.main.startLifetime.constant + " / 3"); } if(particle.isPlaying && PostPlayback == PostPlaybackEnum.NonActive) { Debug.Log("Stop"); particle.Clear(); particleObject.SetActive(false); } } }

#追記 2021/6/8 10:40
sakura_hana様のアドバイスに従ってInstantiateでparticleObjectを複製し、別物としてParticle Systemを保持し、これを後に変更した複製元に適用する。という方法を試したのですが、参照先に変更が適用されず、変数上で保持しているparticleには変更が適用されているという状態になってしまいます。

particleはparticleObjectにアタッチされているParticle Systemを参照しているのですが、なぜ変更が適用されないのか分からず困っています。

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Playables; using UnityEngine.Timeline; public class ControllParticleBehaviour : PlayableBehaviour { public GameObject particleObject; public GameObject copyOB; public ParticleSystem particle; public ParticleSystem copyPV; public Transform playPos; public bool isPlayOfPlayback; public PostPlaybackEnum PostPlayback; public enum PostPlaybackEnum { Active, //クリップを抜けた後もアクティブにする NonActive, //クリップを抜けた後は非アクティブにする Delete, //クリップを抜けた後は対称を破棄する Revert //クリップを抜けた後は元の値に戻す } // クリップに入った時に走らせる処理 public override void OnBehaviourPlay(Playable playable, FrameData info) { if(particle != null) { Debug.Log("Start"); switch(PostPlayback) { case PostPlaybackEnum.Active: break; case PostPlaybackEnum.NonActive: break; case PostPlaybackEnum.Revert: copyOB = Object.Instantiate(particleObject); //別オブジェクトとして複製 copyPV = copyOB.GetComponent<ParticleSystem>(); //再生前の Particle System として保持 copyOB.SetActive(false); break; case PostPlaybackEnum.Delete: break; default: break; } if(playPos != null) { particleObject.transform.position = playPos.position; } particleObject.SetActive(true); ParticleSystem.MainModule par = particle.main; par.startLifetime = 10; Debug.Log(copyPV.main.startLifetime.constant + " / 2"); // copyPV の startLifetime は再生前の値(例として値は「1」とする)を保っている particle.Play(); } } // クリップを抜ける際に走らせる処理 public override void OnBehaviourPause(Playable playable, FrameData info) { if(particle.isPlaying && PostPlayback == PostPlaybackEnum.Revert && copyPV != null) { Debug.Log("!"); particle = copyPV; //ここで particleObject にアタッチされている Particle System の値を再生前の値に戻したい Debug.Log(copyPV.main.startLifetime.constant + " / Copy"); // 1 Debug.Log(particle.main.startLifetime.constant + " / Default"); // 1 Debug.Log(particleObject.GetComponent<ParticleSystem>().main.startLifetime.constant); // 10 ← particleObject の Particle System は paritcle とイコールなはずなのに、変更が適用されていない Object.Destroy(copyOB); } if(particle.isPlaying && PostPlayback == PostPlaybackEnum.NonActive) { Debug.Log("Stop"); particle.Clear(); particleObject.SetActive(false); } } }

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

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

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

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

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

sakura_hana

2021/06/08 00:42

InstantiateでGameObjectごと複製する方法ではいけませんか?
Y0241-N

2021/06/08 01:03

試してみようとしましたが、PlayableBehaviourを継承するクラスではInstantiateが使えないみたいです... 複数継承もできないようなので、どのようにしたらInstantiateが使えるようになりそうでしょうか。
Y0241-N

2021/06/08 01:19

頭にObjectを付ければInstantiate使えました、お騒がせしました。 この方法でいけそうなので試してみます。
Y0241-N

2021/06/08 01:35

Instantiateを試し、複製は上手くいきましたが、今度は上書きの部分で問題が出ました。 particleの値は上書きできているのですが、particleの取得元であるparticleObjectに付いているパーティクルシステムの値は変更出来ていませんでした。 質問の方を追記しますので、よろしければお力をお貸しください。
sakura_hana

2021/06/08 07:58 編集

Unityの仕様上、クラスは参照渡しです。 なので「particle = copyPV;」この部分ですが、 「particleが指しているParticleSystemをcopyPVで上書きする(置き換える)」ではなく 「particleが指しているParticleSystemをcopyPVにする(指している先を変更する)」という意味です。 よってこのような結果になるのは正しいです。 そもそもコピー元を書き換えてから元に戻すのではなく、コピーしてパラメータを書き換えて使用して不要になったら破棄、という形の方がわかりやすいのではと思います。(これなら2回目以降もコピー元は当然最初の値のままになる)
Y0241-N

2021/06/08 08:38

> Unityの仕様上、クラスは参照渡しです。 おっしゃる通りのようですね、自分でも色々確認してみて納得いきました。 書いた通りの挙動をしているにすぎませんでした。 > そもそもコピー元を書き換えてから元に戻すのではなく... 確かにその通りですね、よく考えてみると後で元に戻すということは、変更は複製した物に適用して必要な間だけ使い、不要になったら破棄すれば実質的には元通りになっていると同じですね。 ありがとうございます、そのようにしようと思います。
guest

回答1

0

自己解決

sakura_hana様のアドバイスに従ってInstantiateでparticleObjectを複製し、変更は複製した物に適用して必要な間だけ使い、不要になったら破棄する。という方法で対処しようと思います。

投稿2021/06/09 06:31

Y0241-N

総合スコア1066

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問