[Unity] ブロック崩しをあのアプリ風にする #13 演出の強化

ブロック崩しをあのアプリ風にする #4でTouchScriptを紹介しましたがその中にこんな素敵なサンプルがありました。


爆発とか三國無双とか、何を吹っ飛ばしたり散らかしたりというのは見ていて気持ちいいものがあります。

...


|ω・`)ジィ
            [sample]


|(・ω・ = ・ω・)
            [sample]


|彡サッ!
            [           ]

ブロックを破壊した時に砕ける演出


箱オブジェクトのインスペクタをのぞいてみたところ名前からしてこいつが怪しいです。


これをこねくり回して爆発エフェクトとして実装します。

Brake(分裂)スクリプト


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

public class Break : MonoBehaviour {

    public float Power = 5.0f;
//破片オブジェクト
    public GameObject little;

//Bloke_lifeが呼び出す
    public void Division(){
        Vector3[] directions = {
            new Vector3 (1, -1, 1),
            new Vector3 (-1, -1, 1),
            new Vector3 (-1, -1, -1),
            new Vector3 (1, -1, -1),
            new Vector3 (1, 1, 1),
            new Vector3 (-1, 1, 1),
            new Vector3 (-1, 1, -1),
            new Vector3 (1, 1, -1)
        };
//破片を8つ生み出す
        for (int i = 0; i < 8; i++) {
            var obj = Instantiate (little) as GameObject;
            var cube = obj.transform;
            cube.localScale = 0.35f * transform.localScale;
            cube.position = transform.TransformPoint (directions [i] / 4);
            cube.GetComponent<Rigidbody> ().AddForce (Power * Random.insideUnitSphere, ForceMode.Impulse);
            obj.AddComponent<FadeOut> ();
        }
    }
}

破壊されるブロックにアタッチして利用します。
オリジナルではアタッチされたオブジェクトを縮小して再利用していますが、それをやってしまうとCanvasやらTextやらが付いてくるので、新しくlittleというCubeを作って紐づけています。Rigidbodyと適当なマテリアルをつけてRendering ModeをFadeTransparentにします。この二つ以外は透明度を設定できません。



サイズや位置を決めた後にAddForce()でランダムに力を加えます。Random.insideUnitSphereは半径1の中でランダムな位置を取得できます。
最後にAddComponent<>()FadeOutというスクリプトを追加しています。あらかじめlittleにアタッチしてしまうとゲームが開始した瞬間にFadeOutが開始されてしまうので(そう書きました↓)動的に追加してます。

FadeOut(フェードアウト)スクリプト



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

public class FadeOut : MonoBehaviour {

 void Start () {
        StartCoroutine ("Fade");
 }
//透明化開始
    IEnumerator Fade(){
        Renderer ren = GetComponent<Renderer> ();
        float a = 1f;
        while (a > 0) {
            ren.material.color = new Color (0,0,0,a);;
            a -= 0.02f;
            yield return null;
        }
        Destroy (gameObject);
    }
}

コルーチンで透明化しています。 Color (0,0,0,a)の第4引数が透明度です。0 ~ 1fで指定し、0に近づくほど透明になります。ループの中でaの値を減らし0になったら抜けて自身を消去します。

既に作成済みのWaveに一つ一つアタッチするのは面倒なのでヒエラルキーから複数選択して一気に紐付けます。


Applyを忘れずに。


動かしてみる。




え、なにこれめっちゃ楽しい。


でも撃ってる最中なのにブロックが移動しちゃってますね。


多重判定の修正


これは一つのボールで下の壁と複数回ヒット判定しているからと思われます。今回の実装とはあまり関係ないですが見つけた以上修正します。
変えるのはBallManagerです。

IEnumerator shoot(Vector3 vec){
    foreach (GameObject obj in balls) {
//タグと物理判定を与える
        obj.tag = "Ball";
        obj.GetComponent<Rigidbody>().isKinematic = false;
        Rigidbody rig = obj.GetComponent<Rigidbody> ();
        rig.velocity = vec * speed;
        obj.GetComponent<Ball_Script>().SetSpeed(speed);
        yield return new WaitForSeconds (0.1f);
    }
}
//〜中略〜

public void BottomTouch(GameObject ball){
    ball.GetComponent<Rigidbody>().velocity = Vector3.zero;
//物理影響を無効化 念のためタグを変える
    ball.GetComponent<Rigidbody> ().isKinematic = true;
    ball.tag = "Ghost";
//最初に帰ってきたボールなら
    if (returnBall == 0) {
        Vector3 vec = ballBornPoint.position;
        vec.x = ball.transform.position.x;
        ballBornPoint.position = vec;
        ball.transform.position = ballBornPoint.position;
    } 
//〜中略〜

集合移動中に壁と衝突があって再び動き出すケースがあるのでRigidbodyのisKinematicを入れ、そもそも衝突を起こさないようにタグを変えます。余談ですがRigidbodyは非アクティブ化のチェックがないんですね。
Edit > Project Settings > Tags And Layers から+タブを選び"Ghost"を追加します。その後Layersに追加します。


衝突判定も設定します。
Edit > Project Settings > Physics からPhysicsManagerウィンドウを開きます。


これで事なきを得ると思います。

コメント