【第10日目】UnityとPUN2とHoudiniでカードゲームのマナトークンを生成する

 

今日はマナトークンを作ろうと思います。

マナトークンって何??って思う方もいらっしゃるかもしれないので、一応説明しておきます。

ある種のカードゲームではカードを使うときにコストとしてマナを支払う必要があるのです。

そのマナを可視化したものがマナトークンです。

 

今日はそのマナトークンを0から作成して、皿に盛り、そこからマナトークンを取り出すと、

マナトークンが落ちてくるというのを実装しようと思います。

 

それでは、まずモデリングから始めたいと思います。

HoudiniとUnityでマナトークンを作成する

マナトークンなので、エネルギー源というイメージでモワモワっとトークンの中でエネルギーが渦巻いている物を作成しようと思います。

まずはFBXの作成から参りましょう。

HoudiniでのトークンモデリングとUV展開

モデリングと言っても大したことはしていません、ジオメトリを作成し、ダイブして、Primitive>PlatonicSolidを選びます。

すると、色々な幾何学的形状を選べるので、Icosahedronを選ぶだけです。

そして、いつものように、UV展開をしてあげるという事になります。これについては以前の記事で述べているので、ご参考まで。

 

関連記事

 

Houdiniでのお皿モデリングとUV展開

次にお皿のモデリングです。お皿と言っても平らなプレートのようなものにしようと思いました。

まずはチューブを作り、お皿の形に引き延ばします。円周は36分割程度ならきれいに見えるかと思いました。

EndCapにチェックをいれトップとボトムのメッシュを作成します。

ただし、このままでは、キャップしたメッシュが三角形に割れていないので、作り直す必要があるのは注意です。

その前に、ポリベベルでエッジを丸めてしまいます。

この時に全てのエッジがセレクトされてしまうので、ExclusionのIgnoreFlatEdgesにチェックを入れ、角度によってエッジをセレクトしないようにします。

適当な角度で縦のエッジを省くことができました。

次に、トップとボトムのメッシュをBlastで取り除いて、Polyfillで三角メッシュを使って埋めてあげます。

これをやっておかないと、Unityでの表示がおかしくなります。FillModeはTriangleFanにします。

 

あとは、依然と同様にアンラップしてUVを作ってあげます。

これで、Unityに取り込む準備が出来ました!

UnityとAmplifyShaderでの動的マテリアル作成

今回の肝はこのモヤモヤエネルギーをどう表現するかでした。

参考にしたのは以下のYoutubeチャンネルです。炎のエフェクトを使用しています。

AmplifyShaderでは、Texture CoordinatesをPannerにSpeedを突っ込んでMainTexのUVに繋ぐことでメインのアルベドを動かしてあげています。

AmplifyShaderの基本的な使い方は以前述べたのでご参考まで。

関連記事

VertexTangentをつかって面によって色のバリエーションを増やしてあげています。

それから屈折(Refraction)にも値を入れていますが、これはあまり見た目に影響していない気もします。

今回やったのはそれくらいです。

このシェーダーを使ってマテリアルを作成しました。

メインのアルベドにいれているのは、石のテクスチャを改造したものです。

これが動いて、モヤモヤを作成するようになっています。

ついでにお皿にも石のマテリアルを付けてあげました。

UnityとC#とPHOTONでマナトークンを生成する

まずは先ほど作ったトークンのFBXをフォルダに格納し、ヒエラルキービューにドラッグアンドドロップして画面上に表示させます。

とりあえず7個ずつ、同様に配置したお皿の上においてみます。

そのままでは、モヤモヤが同じ方向に動いて気持ち悪いので、ローテーションをランダムで適当にいじってバラバラにしました。

このままではタダ置いてある飾りになってしまうので、インタラクションをスクリプトでつけてあげることにします。

UnityとC#とPhotonでマナトークンプレファブの作成と格納

インタラクションを付ける上で、トークンもカードと同様に動かせるようにしたいので以前にカードにつけたMouseDrag.csをアタッチします。

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

public class MouseDrag : MonoBehaviour
{
    public AudioClip audioClip1;
    AudioSource audioSource;


    void OnMouseDrag()
    {
        //cardの位置をワールド座標からスクリーン座標に変換して、objectPointに格納
        Vector3 objectPoint = Camera.main.WorldToScreenPoint(transform.position);

        //cardの現在位置(マウス位置)を、pointScreenに格納
        Vector3 pointScreen
             = new Vector3(Input.mousePosition.x,
                           Input.mousePosition.y,
                           objectPoint.z);

        //cardの現在位置を、スクリーン座標からワールド座標に変換して、pointWorldに格納
        Vector3 pointWorld = Camera.main.ScreenToWorldPoint(pointScreen);
        //pointWorld.z = transform.position.z;
        pointWorld.y = 4.4117f;

        //cardの位置を、pointWorldにする
        transform.position = pointWorld;
    }
    private void OnMouseDown()
    {
        audioSource = gameObject.GetComponent<AudioSource>();
        audioSource.clip = audioClip1;
        audioSource.Play();
    }
    private void OnMouseUp()
    {
        audioSource = gameObject.GetComponent<AudioSource>();
        audioSource.clip = audioClip1;
        audioSource.Play();
    }
}

 

もちろん、RigidBody、BoxCollider、PhotonView、PhotonTransformViewもつけてあげます。

それからマナトークンを触った時に音を出したいので、AudioSourceもつけておきます。

 

MouseDragのAudioClipにオーディオソースをドラッグアンドドロップするのをお忘れなく。

 

この効果音は魔王魂というウェブサイトからダウンロードしました。

クレジット表記が必要ですが、センスの良い無料音源が沢山あるので重宝しています。

 

一通りスクリプトを付け終わったら、PhotonのResourceフォルダにヒエラルキービューからトークンをドラッグアンドドロップして、プレファブ化します。

名前はManaという名前にしておいて、後々スクリプトから呼べるようにしたいと思います。

UnityとC#とPhotonでマナトークンのOnTriggerExitでの衝突判定

お皿から、トークンを取ったら、山札の上にトークンがインスタンス化されるというのを実装したいと思います。

トークンを取り除いたら呼ばれるメソッドでOnTriggerExitというものを使おうと思います。

 

お皿をコピーして上図のようにSphereコライダーを付けてIsTriggerにチェックを入れておきます。

メッシュはダブってしまうので非表示にしておき、下のManaPicker.csを付けました。

 

これによって、トークンがSphereから出た時に、新たなトークンをライブラリの上に生み出すようになります。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;

public class ManaPicker : MonoBehaviour
{
    [SerializeField] Transform manaSpawnPoint;
    // Start is called before the first frame update
    private void OnTriggerExit(Collider other)
    {
        Debug.Log("collision");

        if (other.gameObject.tag == "Mana")
        {
            GameObject library = (GameObject)PhotonNetwork.Instantiate("Mana", manaSpawnPoint.position, manaSpawnPoint.rotation, 0);
        }
    }
}

ちょっとわかりにくいですが、お皿からマナトークンを取り出すと、ライブラリ(山札)の上にトークンが発生したのが確認できます。

おわりに

今日はマナトークンの作成とインタラクションを付けました。

これからの展開としては、トークンを資源としてカードを使用するという事になります。

 

それから、発生したトークンがドローの際に相手のマナトークンとして取得されるというのも実装したいと思います。

かなり複雑なので大変になりそうですが、頑張っていきたいと思います。

 

それでは、また!

 

おすすめの記事