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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

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

Q&A

解決済

1回答

754閲覧

Unityでオーディオの周波数に合わせて分解したポリゴンを動かす

satoshi5555

総合スコア18

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

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

0グッド

1クリップ

投稿2018/10/07 14:02

編集2018/10/08 00:43

http://baba-s.hatenablog.com/entry/2017/12/30/230200を使わせていただき、
上記のページにあるスクリプト(下記)は、音に合わせてy軸にスケールが上がりますが、
音に合わせて分解したポリゴンを広げたいと思ってます。

using UnityEngine; public class Example : MonoBehaviour { public AudioSpectrum spectrum; public Transform[] cubes; public float scale; private void Update() { for ( int i = 0; i < cubes.Length; i++ ) { var cube = cubes[ i ]; var localScale = cube.localScale; localScale.y = spectrum.Levels[ i ] * scale; cube.localScale = localScale; } } } ```分解したポリゴン(下記シェーダ)_PositionFactorのパラメーターをスクリプトで弄れるようにし(上記)のスクリプトを参考に音に合わせてポリゴンを広げたいと色々調べ試していたのですが分からず詰まってしまい、わかる方がいましたら返信くださると嬉しいです。 何卒よろしくお願いいたします。 ```ここに言語名を入力 Shader "Unlit/NewUnlitShader" { Properties { _MainTex ("Texture", 2D) = "white" {} _PositionFactor("Position Factor", Range(0.0, 1.0)) = 0.2 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Cull off Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma geometry geom #include "UnityCG.cginc" struct v2g { float4 vertex : POSITION; float3 normal : NORMAL; float2 uv : TEXCOORD0; }; struct g2f { float2 uv : TEXCOORD0; float4 pos : SV_POSITION; fixed4 col : COLOR; }; sampler2D _MainTex; float4 _MainTex_ST; v2g vert (appdata_base v) { v2g o; o.vertex = v.vertex; o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); o.normal = v.normal; return o; } float _PositionFactor; [maxvertexcount(3)] void geom(triangle v2g input[3], inout TriangleStream<g2f> tristream) { g2f o; float3 edgeA = input[1].vertex - input[0].vertex; float3 edgeB = input[2].vertex - input[0].vertex; float3 normalFace = normalize(cross(edgeA, edgeB)); for (int i = 0; i < 3; i++) { o.pos = UnityObjectToClipPos(input[i].vertex + float4(normalFace, 0) * _PositionFactor); o.uv = input[i].uv; o.col = fixed4(0, 0, 0, 1.); tristream.Append(o); } tristream.RestartStrip(); } fixed4 frag (g2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); return col; } ENDCG } } }

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

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

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

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

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

Bongo

2018/10/07 16:29

面白そうでしたので試してみましたが、Unity 2018.2.11f1でやってみたところ、unity-audio-spectrumにもご質問者さんご提示のシェーダーコードにも異常はなさそうでした。どのような点がうまくいかないのか、より詳細にご説明いただけますとアドバイスが容易になるかと思います。
satoshi5555

2018/10/08 00:40

返信ありがとうございます。言葉足らずですいません、修正しました。まだ言葉不足かもしれませんがよろしくお願いします。
guest

回答1

0

ベストアンサー

マテリアルの_PositionFactorをどうやって書き換えればいいか分からないということでしょうかね?
プロパティに情報を与えるには、MaterialのSet系メソッド...今回はSetFloatを使うのがいいでしょう。
teratail内の類似ケースとしまして...

などがご参考になりそうです。

また、プロパティに頻繁にアクセスする場合は、Shader.PropertyToIDを使ってあらかじめアクセス用のIDを求めておくのが効率的かと思います。

参考:シェーダプロパティアクセスが2.5倍早くなるPropertyToID関数 - 渋谷ほととぎす通信

C#

1using System.Linq; 2using UnityEngine; 3 4public class Example : MonoBehaviour 5{ 6 public Transform[] cubes; 7 public float scale; 8 public AudioSpectrum spectrum; 9 10 // 効率化のため、あらかじめ操作対象のマテリアルは配列化し、 11 // プロパティアクセス用の識別番号も取得しておくことにしました 12 private Material[] materials; 13 private static readonly int PositionFactor = Shader.PropertyToID("_PositionFactor"); 14 15 private void Start() 16 { 17 if (this.cubes == null) 18 { 19 return; 20 } 21 22 this.materials = this.cubes 23 .Where(o => o != null) 24 .Select(o => o.GetComponent<Renderer>()) 25 .Where(r => r != null) 26 .Select(r => r.material) 27 .ToArray(); 28 } 29 30 private void Update() 31 { 32 for (var i = 0; i < this.materials.Length; i++) 33 { 34 this.materials[i].SetFloat(PositionFactor, this.spectrum.Levels[i] * this.scale); 35 } 36 } 37}

プレビュー

投稿2018/10/08 03:36

Bongo

総合スコア10807

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

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

satoshi5555

2018/10/08 10:16

細かく教えていただき本当ありがとうございます。コードを入れたら自分が実現したいことが出来ました!!しかし、Unityを触り始めて日が浅くLINQ勉強不足のため private void Start()の所が何をやっているのかも、まだ分っていないところです。やはりここはLINQを使うのがベストなんでしょうか?
Bongo

2018/10/08 10:35

いえいえ、見やすいかと思ってLINQを選びましたが、逆効果だったかもしれません...すみません。 やっているのは、ただcubesにセットされたTransform経由でRendererをとってきて、そのmaterialを取り出して配列にしているだけですので、LINQを使わなくともかまいません。 LINQなしにして、ついでにご自身で確実にオブジェクトをセットできているのでしたらnullチェックも省略してしまい... var cubeCount = this.cubes.Length; this.materials = new Material[cubeCount]; for (var i = 0; i < cubeCount; i++) { this.materials[i] = this.cubes[i].GetComponent<Renderer>().material; } こんな形でも問題ないと思います。
satoshi5555

2018/10/08 12:20

回答ありがとうございます! やはり、まだまだ勉強不足なところが多く理解しきれてない所がありますが、LINQを使うパターンと使わないパターンまで教えていただき、とても勉強になりました。 詳しく教えていただき大変ありがとうございました!
satoshi5555

2018/10/09 15:55

あれからBongoさんの回答のスクリプトを見て色々調べて考えていたのですが、やはりどうしても分からないでいます。なにを勉強していけば理解できるようになるでしょうか?初歩的な質問ですいません。
Bongo

2018/10/09 19:40

わからない...といいますと、どの部分のことでしょうか?LINQ部分か、あるいは「MaterialにSetFloatで値を渡す」ということについてでしょうか。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問