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

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

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

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

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

Q&A

解決済

1回答

5964閲覧

Unityのpost processing stack v2で、スクリプトから動的に値を変更したい!

Lovedelic_VR

総合スコア24

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

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

0グッド

0クリップ

投稿2020/10/13 07:56

編集2020/10/13 09:08

ppsv2,Unity2017.4.28f1で動的に値を変更したいのですが
https://indie-du.com/entry/2019/03/06/190000
以上サイトを参考にppsv2の中のGrainのintensityを変更しようとしたところ、動きません。

エラーメッセージは出ず、シーン上でもエフェクトはかかりますし
対象オブジェクトであるppsのインスペクターのPost Process Volumeにアクセスは出来ているのですが、
シーンを再生するとその項目が、逆に画面にかからなくなります。
インスペクターの値も特に書き換わった様子はありません。
(下の場合は、Grainを設定して再生を押すとGrainだけがかかりません)

また、参考先のサイトそのままのコードでも同じ現象が起きました。
(DepthOfFieldだけが、再生ボタンを押すとかからなくなる)

何かご存知の方がいらっしゃいましたら情報頂けますと幸いです。

追記:
Update()内で書いたことで、上書きするような処理が重ねて走っているのではと考え、
Start()内に書いてみましたが、状態は変わりませんでした。指定した項目のみがむこうとなってしまいます。
また、完全なnew sceneで行った場合も同じ症状となりました。

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.Rendering.PostProcessing; 5 6public class Enemypps : MonoBehaviour { 7 8 [SerializeField] 9 private GameObject pps; 10 [SerializeField] 11 private GameObject player; 12 [SerializeField] 13 private float distance; 14 15 16 // Use this for initialization 17 void Start () { 18 19 pps = GameObject.Find("pps"); 20 player = GameObject.Find("FirstPersonCharacter"); 21 22 foreach (Transform childTransform in pps.transform) 23 { 24 if (childTransform.gameObject.layer == LayerMask.NameToLayer("PPS")) 25 { 26 if (childTransform.gameObject.activeSelf) 27 { 28 pps = childTransform.gameObject; 29 } 30 } 31 } 32 33 } 34 35 // Update is called once per frame 36 void Update () { 37 distance = Vector3.Distance(this.transform.position,player.transform.position); 38 39 //ppsの変更部分です 40 var grain = ScriptableObject.CreateInstance<Grain>(); 41 grain.intensity.Override(1); 42 PostProcessManager.instance.QuickVolume(pps.layer, 1, grain); 43 } 44} 45

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

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

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

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

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

guest

回答1

0

ベストアンサー

Post Processing Stack V2の効果をスクリプトから動的に変更する - いんでぃーづの記事内で言及されているManipulating the Stack · Unity-Technologies/PostProcessing Wiki · GitHubでは、エフェクト設定のenabledtrueにしています。これにならって...

C#

1 // Update is called once per frame 2 void Update () { 3 distance = Vector3.Distance(this.transform.position,player.transform.position); 4 5 //ppsの変更部分です 6 var grain = ScriptableObject.CreateInstance<Grain>(); 7 grain.enabled.Override(true); 8 grain.intensity.Override(1); 9 PostProcessManager.instance.QuickVolume(pps.layer, 1, grain); 10 }

としてみてはいかがでしょうか。

なおPostProcessEffectSettingsの変更履歴を見てみますと、設定を新規作成した時のenabledについて、従来は「valuefalseoverrideStateはデフォルトのまま(つまりfalse)」だったのを「valuefalseoverrideStatetrue」に変更したようです。
いんでぃーづさんの記事だとenabledには手を付けていないようですが、おそらくいんでぃーづさんが実験された当時はこの変更が加わっていなかったんじゃないかと思います。ですのでenabledはオーバーライドされず、元々のプロファイルの設定が引き継がれてオンのままとなり、エフェクトがちゃんと表示されたのだと説明できそうです。
一方、現行バージョンでは最初からoverrideStatetrueになっており、かつvaluefalseに設定されていますので、デフォルトではenabledがオフの状態でオーバーライドされてしまうようです。ですので明示的にenabledをオンにするか、あるいはオーバーライドをオフにするかしないとエフェクトが消えてしまうみたいですね。

余談ですが、GrainPostProcessVolumeを毎フレーム新規生成する必要はないように思います。ですので...

C#

1using System; 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5using UnityEngine.Rendering.PostProcessing; 6 7public class Enemypps : MonoBehaviour { 8 9 [SerializeField] 10 private GameObject pps; 11 [SerializeField] 12 private GameObject player; 13 [SerializeField] 14 private float distance; 15 16 private Grain grain; 17 private PostProcessVolume postProcessVolume; 18 19 // Use this for initialization 20 void Start () { 21 22 pps = GameObject.Find("pps"); 23 player = GameObject.Find("FirstPersonCharacter"); 24 25 foreach (Transform childTransform in pps.transform) 26 { 27 if (childTransform.gameObject.layer == LayerMask.NameToLayer("PPS")) 28 { 29 if (childTransform.gameObject.activeSelf) 30 { 31 pps = childTransform.gameObject; 32 } 33 } 34 } 35 36 // StartのタイミングでGrainとPostProcessVolumeを作っておく 37 grain = ScriptableObject.CreateInstance<Grain>(); 38 grain.enabled.Override(true); 39 grain.intensity.Override(1); 40 postProcessVolume = PostProcessManager.instance.QuickVolume(pps.layer, 1, grain); 41 } 42 43 // Manipulating the Stackのサンプルコードにならって 44 // 不要になったPostProcessVolumeを削除するようにしました 45 // マニュアルにもわざわざ大きい文字で 46 // 47 // Important: Don't forget to destroy the volume and the attached profile 48 // when you don't need them anymore! 49 // 50 // なんて書いてありますので、削除はきっちりやっておいた方がよさそうですね 51 private void OnDestroy() 52 { 53 RuntimeUtilities.DestroyVolume(this.postProcessVolume, true, true); 54 } 55 56 // Update is called once per frame 57 void Update () { 58 distance = Vector3.Distance(this.transform.position,player.transform.position); 59 60 // distanceが大きいほどGrainの強度が高くなるようにしてみました 61 // 距離1mで強度1だときつすぎるように感じたので、0.2倍して穏やかにしています 62 grain.intensity.value = this.distance * 0.2f; 63 } 64}

とでもした方が効率的な気がします。

また「インスペクターの値も特に書き換わった様子はありません」とおっしゃっていますが、QuickVolumeはボリュームを新規作成する機能のようで、既存のボリュームには手を付けないものと思われます。ですので、もともと設置しておいたボリュームの設定値が変化していないのは正常な挙動でしょうね。
既存の設定値を書き換える場合、マニュアルのProfile Editingの節で解説されている手順に従うのがよさそうです。

C#

1using System; 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5using UnityEngine.Rendering.PostProcessing; 6 7public class Enemypps : MonoBehaviour { 8 9 [SerializeField] 10 private GameObject pps; 11 [SerializeField] 12 private GameObject player; 13 [SerializeField] 14 private float distance; 15 16 private Grain grain; 17 private PostProcessProfile postProcessProfile; 18 19 // Use this for initialization 20 void Start () { 21 22 pps = GameObject.Find("pps"); 23 player = GameObject.Find("FirstPersonCharacter"); 24 25 foreach (Transform childTransform in pps.transform) 26 { 27 if (childTransform.gameObject.layer == LayerMask.NameToLayer("PPS")) 28 { 29 if (childTransform.gameObject.activeSelf) 30 { 31 pps = childTransform.gameObject; 32 } 33 } 34 } 35 36 // ppsから既存のPostProcessVolumeを取得し... 37 var postProcessVolume = pps.GetComponent<PostProcessVolume>(); 38 39 // そこからプロファイルを取得する 40 // ここで「sharedProfile」を使うとボリュームが参照しているプロファイル自体が取得されるのに対し、 41 // 「profile」を使うと必要に応じてプロファイルが複製されるので、もし他のボリュームが同じプロファイルを 42 // 共有していたとしても、影響が波及しなくなるようです 43 // また「sharedProfile」に対して変更を加えると、その内容がプロファイルアセットに保存されるため 44 // プレイモードを終了しても変更した設定は元に戻らないそうです 45 // ここは「profile」の方を使うのが妥当かな...と思いますが、マニュアルのOwned profile editingの手順には 46 // 47 // It is your responsibility to destroy the profile when you don't need it anymore 48 // 49 // とありますので、注意書き通りこの複製プロファイルが不要になったら削除してやるべきでしょう 50 postProcessProfile = postProcessVolume.profile; 51 52 // プロファイルからGrain設定を取得する 53 // すでにインスペクター上でGrainは追加済みだと思いますが、もしなければ追加するようにしました 54 if (!postProcessProfile.TryGetSettings(out grain)) 55 { 56 grain = postProcessProfile.AddSettings<Grain>(); 57 } 58 grain.enabled.Override(true); 59 grain.intensity.overrideState = true; 60 } 61 62 private void OnDestroy() 63 { 64 // 複製されたプロファイルはOnDestroy時に削除する 65 // DestroyProfileの第2引数をtrueにすると、プロファイル中の設定オブジェクトも全部処分してくれるようです 66 // それら設定オブジェクトも、プロファイルが複製された時に新しく作られた複製品ですので 67 // 削除してしまうべきでしょう 68 RuntimeUtilities.DestroyProfile(postProcessProfile, true); 69 } 70 71 // Update is called once per frame 72 void Update () 73 { 74 distance = Vector3.Distance(transform.position, player.transform.position); 75 grain.intensity.value = distance * 0.2f; 76 } 77}

投稿2020/10/14 03:06

Bongo

総合スコア10807

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

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

Lovedelic_VR

2020/10/14 04:34

問題の解決方法だけではなく、情報ソースやリンク・意図を組んだ実装までご丁寧にありがとうございました!疑問は払拭され完璧に解決しましたのでベストアンサーとさせていただきます。
Lovedelic_VR

2020/10/14 08:36

※distanceに関してのみ、今の実装だと遠ければ遠いほど強まるので近ければ近いほどかかる処理に変更し実装することが出来ました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問