LoginSignup
2
3

More than 5 years have passed since last update.

【Unity】残像を残しながらオブジェクトを拡大・縮小する

Posted at

はじめに

タイトルの通りです。
アントマン&ワスプの大きさが変わるラボ(https://youtu.be/8_rTIAOohas の30秒あたり)に衝撃を受けたので再現してみました。

できたもの

縮小

5a28b8d38073102f667c200d164f3ae4 (1).gif
これでゴーストに襲撃されても安心

拡大

be976b87425f23119b10b77ee202ef23.gif
うーん(微妙)

方針

  • 拡大・縮小したいオブジェクトのPrefabを作る
  • 残像分(5個くらい)配列を作り、少しずつサイズとアルファ値を変化させる
  • Updateにぶっこむと処理が速すぎて残像が残らないので、コルーチンを使って遅延させる

コード

C#

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

public class Shrink : MonoBehaviour
{
    public GameObject objPrefab;
    GameObject[] obj = new GameObject[5];
    //float TimeCount = 0;
    bool small = false;
    bool big = false;
    int count = 4;
    float a = 0.6f;
    float size;
    private Material material;

    void Start()
    {
        obj[0] = Instantiate(objPrefab) as GameObject;
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            small = true;
        }

            if (small == true)
        {
            Coroutine coroutine = StartCoroutine("SizeGenerator", 0.05f);
            small = false;
        }

        if (Input.GetMouseButtonDown(1))
        {
            big = true;
        }

        if (big == true)
        {
            Coroutine coroutine = StartCoroutine("SizeGenerator", 0.05f);
            big = false;
        }
    }

    private IEnumerator SizeGenerator(float waitTime)
    {
        if (small == true)
        {
          size = 0.5f;
        }

        if (big == true)
        {
            size = 2.0f;
        }

        for (int i = 1; i <= count; i++)
        {
            for (int j = i; j >= 0; j--)
            {
                if (i == j)
                {
                    obj[i] = Instantiate(objPrefab) as GameObject;
                    float alpha = Mathf.Pow(a, j);
                    obj[j].GetComponent<Renderer>().material.SetFloat("_Alpha", alpha);
                }
                else
                {
                    obj[j].transform.localScale = obj[j].transform.localScale * size;
                }    
            }
            yield return new WaitForSeconds(waitTime);
        }

        //destroyする用
        for(int k=0; k<8; k++)
        {
            //配列回すようループ
            for (int l = obj.Length-1; l > 0; l--)
            {
                float alpha = Mathf.Pow(a, l)* Mathf.Pow(a, k);
                if (obj[l] != null)
                {
                    obj[l].GetComponent<Renderer>().material.SetFloat("_Alpha", alpha/2);
                }
                if (alpha < 0.05)
                {
                    Destroy(obj[l]);
                }
            }
            yield return new WaitForSeconds(waitTime);
        }
    }
}

左クリックで縮小、右クリックで拡大

シェーダ

Shader "Custom/Custom"
{
    Properties{
    _MainTex("Water Texture", 2D) = "white" {}
    _Alpha("Alpha", Range(0,1)) = 1.0
    }

    SubShader{
        Tags { "Queue" = "Transparent" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Standard alpha:fade 
        #pragma target 3.0

        struct Input {
            float2 uv_MainTex;
        };

    half _Alpha;
    sampler2D _MainTex;

        void surf(Input IN, inout SurfaceOutputStandard o) {
            fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
            o.Alpha = _Alpha;
        }
        ENDCG
    }
        FallBack "Diffuse"
}

テクスチャとアルファ値のみのsurfaceシェーダ

注意

  • 残像処理を行うために複製したオブジェクト同士の衝突判定を無くす必要あり
  • 拡大の場合、オブジェクトのRigidbody→is Kinematicにチェックを入れないとオブジェクトがふっ飛ぶ(なぜ...?)

参考

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3