- 投稿日:2020-11-29T21:55:38+09:00
UnityのMecanimアニメで、ムービープレーヤーのスライダーのような制御がしたい
やりたいこと
- ムービープレーヤーのスライダーのような制御がしたい
- アニメ全長の任意の位置へジャンプしたいです。
- アニメの任意のフレームを再生したい
- シーケンシャルな再生でなく、任意のフレームに対してランダムにアクセスして、スクリプト制御で正逆任意の速度で再生したいです。
検証環境
- Unity 2019.4.x (LTS)
方法
Animator.Play (int stateNameHash, int layer, float normalizedTime)
を使います。
stateNameHash
に0
を渡すと現在のステートになります。layer
に-1
を渡すと最初に一致したステートになります。normalizedTime
には、正規化された再生位置を渡します。
- ループするアニメの場合は、
0f
と1f
で同じフレームが表示されます。
- その場合は、
0.9999999f
とかにすれば最終フレームになります。- なお…
具体例
以下のコードでは、対象のスライダーとアニメーターが、コードがアタッチされたオブジェクトの子孫の何処かに存在することを前提にしています。
AnimeSlider.csusing UnityEngine; using UnityEngine.UI; public class AnimeSlider : MonoBehaviour { private Slider slider; private Animator animator; /// <summary>初期化</summary> void Start () { slider = GetComponentInChildren<Slider> (); slider.onValueChanged.AddListener (OnChangeSlider); animator = GetComponentInChildren<Animator> (); animator.speed = 0; // 再生をポーズ } /// <summary>スライダが変化</summary> public void OnChangeSlider (float _) { animator.Play (0, -1, slider.normalizedValue); } }
- これによって、スライダーの位置に応じた任意のフレームが再生されます。
- ループするアニメの場合は、スライダの左端と右端で同じフレームが表示されます。
- 同じにしたくない場合は、
slider.normalizedValue * 0.9999999f
とかにします。- ポーズを解除する場合は、
animator.speed = 1;
します。蛇足
複数の同じアニメを時間差で表示
AnimeSlider.csusing UnityEngine; using UnityEngine.UI; public class AnimeSlider : MonoBehaviour { private Slider slider; private Animator [] animators; /// <summary>初期化</summary> void Start () { slider = GetComponentInChildren<Slider> (); slider.onValueChanged.AddListener (OnChangeSlider); animators = GetComponentsInChildren<Animator> (); foreach (var animator in animators) { animator.speed = 0; // 再生をポーズ } } /// <summary>スライダが変化</summary> public void OnChangeSlider (float _) { for (var i = 0; i < animators.Length; i++) { var time = slider.normalizedValue - ((float) i / animators.Length); if (time < 0f) { time += 1f; } animators [i].Play (0, -1, time); } } }
- 投稿日:2020-11-29T20:28:07+09:00
外部スクリプトの変数を取得する方法
途中だけどごめんねー
この記事でできること
- 外部のスクリプトにある変数を取得できるようになる。
参考例
- Sceneにはplaneとcubeを設置して、それぞれにPublicの変数を設ける。
- planeオブジェクト
- testA.cs
- 変数intTestAは10
- cubeオブジェクト
- testB.cs
- 変数intTestBは20
using UnityEngine; public class testA : MonoBehaviour { public int intTestA = 10; }using UnityEngine; public class testB : MonoBehaviour { public int intTestB = 20; testA script; void Start() { script = GameObject.Find("Plane").GetComponent<testA>(); Debug.Log(script.intTestA); } }
- 投稿日:2020-11-29T17:30:34+09:00
【Unity / ARFoundation】 AR空間の変形のつなぎ目を滑らかにする
1. はじめに
以前、ARKit3を使ってAR空間上のカメラ映像の一部分を変形させるという記事を書きました。
カメラ映像をテクスチャにするやつやっとできた#arkit3 #ARFoundation pic.twitter.com/gRDyynsN6O
— koyo arai (@koyoarai_) April 26, 2020この記事を書いた時点ではあまり気にならなかったですが、よく見てみると変形のつなぎ目が目立ってしまい、あまり空間に溶け込んでいません。
そこで、今回 AR空間の変形のつなぎ目を滑らかにするようにシェーダーを書き換えてみたので、そのテクニックを紹介します。
2. 準備
基本準備は、ARKit3を使ってAR空間上のカメラ映像の一部分を変形させるに記載しているので、そちらをご覧ください。
3. 実装
変形処理のつなぎ目を滑らかにするため、シェーダー (CameraPlane.shader)を書き換えます。
Planeの中心から遠ざかるにつれ、パラメタを小さくし、つなぎ目では変形させないようにします。
そこで、tex2Dlodを使って、テクスチャ情報から頂点をいじる処理を追加します。
下記の画像をインポートし、_ScopeTexとして利用します。また、Thresholdによって変形のパラメータを調整できるようにします。
追加する処理はこのような感じです。float4 deform = tex2Dlod (_ScopeTex, float4(IN.uv.xy,0,0)); float ratio = _Threshold * deform; float4 _vertex = IN.vertex; float ampX = 0.1f * sin(_Time * 100 + IN.vertex.x) * ratio; float ampZ = 0.1f * sin(_Time * 100 + IN.vertex.z) * ratio; _vertex.xyz = float3(IN.vertex.x + ampX, IN.vertex.y, IN.vertex.z + ampZ);全文はこちら
CameraPlane.shaderShader "Custom/CameraPlane" { Properties { _MainTex ("Albedo (RGB)", 2D) = "white" {} // _ScopeTexと_Thresholdを追加 _ScopeTex ("Texture", 2D) = "white" {} _Threshold("Threshold", Range(0,10))= 0.0 } SubShader { Pass { CGPROGRAM #pragma target 3.0 #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata_t { float4 vertex : POSITION; float4 color : COLOR; float2 uv : TEXCOORD0; }; struct v2f { float4 vertex : POSITION; float4 color : COLOR; float2 uv : TEXCOORD0; float2 screenpos : TEXCOORD1; }; sampler2D _MainTex; sampler2D _ScopeTex; float _Threshold; v2f vert(appdata_t IN) { v2f OUT; // --------- : 追加 float4 deform = tex2Dlod (_ScopeTex, float4(IN.uv.xy,0,0)); float ratio = _Threshold * deform; float4 _vertex = IN.vertex; float ampX = 0.1f * sin(_Time * 100 + IN.vertex.x) * ratio; float ampZ = 0.1f * sin(_Time * 100 + IN.vertex.z) * ratio; // --------- _vertex.xyz = float3(IN.vertex.x + ampX, IN.vertex.y, IN.vertex.z + ampZ); OUT.vertex = UnityObjectToClipPos(_vertex); OUT.uv = IN.uv; OUT.color = IN.color; float4 objectToClipPos = UnityObjectToClipPos(IN.vertex); float4 spreenPos = ComputeScreenPos(objectToClipPos); float2 uv = spreenPos.xy/spreenPos.w; OUT.screenpos = uv; return OUT; } fixed4 frag(v2f IN) : COLOR { float2 xy = IN.screenpos.xy; half4 c = tex2D(_MainTex, xy); return c; } ENDCG } } FallBack "Diffuse" }4. 実行結果
処理を入れる前
処理を入れた後
5. おわりに
今回はARFoundation向けのシェーダーを紹介しましたが、その他のプラットフォームでも適用できそうなテクニックの紹介でした?
おまけ
変形処理をちょっと変えたやつです。
AR空間の変形のつなぎ目を滑らかにする#ARKit #ARFoundation pic.twitter.com/i8FTS5U9vO
— koyo arai (@koyoarai_) November 29, 2020参考