6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[Unity] カメラに被った建物を半透明化する

Last updated at Posted at 2023-06-27

はじめに

プレイヤーとカメラの間に存在する建物を半透明にする方法について解説をします。

Game Idea-34.jpg image.png](

処理内容

カメラとプレイヤーの間にRayを飛ばし、特定のGameObject.tagを持つオブジェクトと衝突した場合、そのオブジェクトをリストに格納して半透明にします。次のフレームでは、前フレーム時に格納したリストを別のリストにコピーし、その後で現在のフレームとの差分を取り、今回衝突していないオブジェクトを不透明に戻します。

↓具体的な実装手順について↓

step1-1: カメラとプレイヤーの間にRayを飛ばす

[SerializeField] private Transform player;
void Update()
{
    //二つのオブジェクト間のベクトルを得ます
    Vector3 _difference = (player.transform.position - this.transform.position);
    //.normalizedベクトルの正規化を行う
    Vector3 _direction = _difference.normalized;
    // Ray(開始地点,進む方向)
    Ray _ray = new Ray(this.transform.position, _direction);
}

step1-2: Rayが衝突した全てのゲームオブジェクトの情報を取得する

void Updata()
{
    // Rayが衝突した全てのコライダーの情報を得る
    RaycastHit[] rayCastHits = Physics.RaycastAll(_ray);
}

step1-3 取得したゲームオブジェクトを全て半透明にする

    // 前フレームで遮蔽物として扱われていたゲームオブジェクトが格納されます。
    public GameObject[] prevRaycast;
    public List<GameObject> raycastHitsList_ = new List<GameObject>();

    void Update()
    {
        Vector3 _difference = (player.transform.position - this.transform.position);
        Vector3 _direction = _difference.normalized;
        Ray _ray = new Ray(this.transform.position, _direction);
        // 今回のフレームでRayが衝突した全てのコライダーの情報を得る
        RaycastHit[] rayCastHits = Physics.RaycastAll(_ray);
        // 前フレームで遮蔽物であった全てのGameObjectを保持
        prevRaycast = raycastHitsList_.ToArray();
        raycastHitsList_.Clear();

        foreach (RaycastHit hit in rayCastHits)
        {
            SampleMaterial sampleMaterial = hit.collider.GetComponent<SampleMaterial>();
            if (hit.collider.tag == "<半透明にしたいゲームオブジェクトタグ>")
            {
                //ClearMaterialInvoke()はstep2で解説
                sampleMaterial.ClearMaterialInvoke();
                //次のフレームで使いたいため、不透明にしたオブジェクトを追加する
                raycastHitsList_.Add(hit.collider.gameObject);
            }
        }

step1-4 ヒットしたGameObjectの差分を求めて、今回衝突しなかったオブジェクトを不透明に戻す

        foreach (GameObject _gameObject in prevRaycast.Except<GameObject>(raycastHitsList_))
        {
            SampleMaterial noSampleMaterial = _gameObject.GetComponent<SampleMaterial>();
            // 遮蔽物でなくなったGameObjectを不透明に戻す
            if (_gameObject != null)
            {
                noSampleMaterial.NotClearMaterialInvoke();
            }
        }

このforeach文はExceptメソッドを使って、prevRaycastからraycastHitsList_の要素を除外した結果を走査します。

step1のソースコード全体

public class RayCamera : MonoBehaviour
{
    [SerializeField] private Transform player;
    [SerializeField] private GameManager gameManager;

    [SerializeField] private EatObjectScript eatObject;

    public GameObject[] prevRaycast;
    public List<GameObject> raycastHitsList_ = new List<GameObject>();

    void Update()
    {
        Vector3 _difference = (player.transform.position - this.transform.position);
        Vector3 _direction = _difference.normalized;
        Ray _ray = new Ray(this.transform.position, _direction);
        RaycastHit[] rayCastHits = Physics.RaycastAll(_ray);

        prevRaycast = raycastHitsList_.ToArray();
        raycastHitsList_.Clear();

        foreach (RaycastHit hit in rayCastHits)
        {
            SampleMaterial sampleMaterial = hit.collider.GetComponent<SampleMaterial>();

            if (
            hit.collider.tag == "10p" && gameManager.point < eatObject.obj10p || hit.collider.tag == "12p" && gameManager.point < eatObject.obj12p ||
            hit.collider.tag == "15p" && gameManager.point < eatObject.obj15p || hit.collider.tag == "20p" && gameManager.point < eatObject.obj20p ||
            hit.collider.tag == "30p" || hit.collider.tag == "50p")
            {
                sampleMaterial.ClearMaterialInvoke();
                raycastHitsList_.Add(hit.collider.gameObject);//hitしたgameobjectを追加する
            }
        }
        foreach (GameObject _gameObject in prevRaycast.Except<GameObject>(raycastHitsList_))
        {
            SampleMaterial noSampleMaterial = _gameObject.GetComponent<SampleMaterial>();
            if (_gameObject != null)
            {
                noSampleMaterial.NotClearMaterialInvoke();
            }

        }
    }
}

step2 オブジェクトを透明化する

オブジェクトの透明化については、以下の記事で詳しく解説しています。

GitHub

6
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
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?