Unity:少し特殊なストップウォッチアプリ制作日記_4:タッチエフェクト作成

スクリーンショット 2021-07-28a

・そうだエフェクト作ろう

 前回までで、一旦時間を計測してフレーム単位を切り替えるところまで完成した。次はラップタイム集計の機能に挑戦しようと考えていたが、その前に画面をクリックした時に出るエフェクトを作ることにした。
 本物のストップウォッチと違い画面上のボタンを押すことになるのでクリック感はどうしても無い。インタラクションを少し増やしておこうと思った。簡単に作れそうだったのもある。

 エフェクトを出すスクリプトは、時間を計るメインの処理とは別なのでスクリプトは分けることにした。こういう判断が適切なのかはズブの素人なので判らない。

スクリーンショット 2021-07-28 214523

 ここでやるべき処理は、クリックされた瞬間に「クリックされた場所」に「エフェクトを発生」させて「時間で消す」になる。

・実装

 表示するエフェクトは輪っかの絵を差し込んだだけのUIのImage1枚。この画像のオブジェクトにAnimationControllerとAnimationを1つ追加する。Animationは輪っかが拡大しながらアルファ値で薄くなっていく総尺15/60フレーム(=0.25秒)の簡単なものだ。
 完成したら、このImageをprefabにしておく。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ClickEffectSpawn : MonoBehaviour
{
   //発生させるprefab
   public GameObject clickEffectPrefab;

   //instantiateしたエフェクトをcanvasの子にするためにcanvasのTransformを取得する
   public Transform parentObject;

   //ゲーム中にinstantiateされて発生したエフェクトオブジェクトを、個別管理して消すために取得する
   private GameObject clickEffectObject;

   //消滅までの時間。アニメーションの尺に合わせて手入力
   public float killTimer;

   // Start is called before the first frame update
   void Start()
   {
       
   }

   // Update is called once per frame
   void Update()
   {
       if (Input.GetMouseButtonUp(0))
       {
           clickEffectObject = Instantiate(clickEffectPrefab, Input.mousePosition, transform.rotation, parentObject);

           //生まれた瞬間から死が約束されている
           Destroy(clickEffectObject, killTimer);
       }
   }
}

 コードは上の通り。UIのImageはcamvasの階層下に存在しないと表示されないというルールがあるので、ボタンや画面表示類が入っているcanvasの中に生成されるようにインスペクターで取得する。Transformというコンポーネントをわざわざ取得しているのは、どうもこいつは単に座標だけではなくてHierarchyの階層まで含めた”位置情報”を持ってるコンポーネントらしく、Instantiateの4つ目のパラメータで生成される階層を指定できる。

 普通に考えればどのオブジェクトもTransformを取得して位置、回転、スケールを操作させるべきなのだがHierarchy(=ゲームの画面上)に置かれているモノは絶対確実にTransformが存在するので、面倒だしGameObjectから直に扱えるようにしとくか。……というのが普段我々が触っている、チュートリアル等でもおなじみのtransform.positionとからしい。でも親子指定のためにはTransformをわざわざ取得しなきゃいけない。わからん。よくわからん。

 あとはInstantiateで生成したエフェクトをGameObjectとして確保して、生まれた瞬間に殺すための処理を放り込む。可哀そう。
 スクリプトのスキルがある人なら、prefabが持ってるアニメーションの長さを取得して自動で消えるまでの時間を設定するとかできそうなんだけど、今の私にはまぁ無理。

・問題発生!

 これでエフェクトは完成。そう思っていたら問題が起きた。エフェクトを出すと、わずかな間再クリックが出来なくなってしまった! 普通に秒単位で計測して使う分には問題ない。が「タタン!」と間髪入れずにダブルクリックした際にストップウォッチを止められない状況が絶対に起きるようになってしまった。
 「まさか処理落ちか~~? いくらなんでも無いだろ~~?」とか思いながら、見方も良くわからないなりにprofilerを見てみると通常の状態で2ms、instanciateで重くなる瞬間でも4msで処理は終わっている。どう考えても処理落ちとかではない。
 まるでエフェクトが出ているせいでボタンが押せないような……というところまで考えて、はい解決。

スクリーンショット 2021-07-29 035702

 エフェクトのイメージにRaycastTargetのチェックが入っていたせいでエフェクトの下にあるボタンを押せなくなっていたわけですね。
私「押したで」
エフェクト「上におるワイが優先で押されたな。何もせぇへんけど」
ボタン「ほーん、そんならワイは押されとらんな。何もせんどこ」
 チェック外したら解決した。

Unityの落とし穴、ハマってみないとわかんねぇ😂

・いつかの課題

 他に「エフェクトにパーティクルを加える(=レンダーピクチャーを追加する)」「クリックされた時に音を出す(ボタン音とかも)」「もしいつかスマホ版とかあったらクリック時に振動させる」なんかは挑戦したいね。

この記事が気に入ったらサポートをしてみませんか?