ダメージの文字をだす。(Unity6)

開発Tips

敵を攻撃したときにダメージがでるようにしたいと思います。

今回はダメージを出すのが目的でダメージ計算はしません。とりあえず、ランダム値で出していきます。

Canvasを作成し、TextMeshProを置く

Hierarchyに右クリックを押し
UI > Text – TextMeshPro
を選択、自動でCanvasが作られその子にText – TextMeshProが作成されます。
Canvas置いてその子にText – TextMeshProを置いても同じです。

今回は、ダメージは敵に攻撃が当たったら、敵の頭上に出したいと思います。
なのでCanvasのRender Modeを「World Space」にします。

スクリーンの位置ではなく、3D座標の位置・回転(Rect Transform)で指定することができるようになります。

見えるとこまで移動してみます。

だいぶデカいですね。位置やサイズを調整します。

まだ大きい気もしますが、このくらいですかね。変更したところです。細かい説明は割愛します。

Prefab化する

ProjectのAssetsの中にPrefabsフォルダを作成してそこにドラッグ&ドロップで移動する。文字が青くなればOKです。

ダメージを表示するスクリプトの作成

DamagePopupGeneratorという名前でファイルを作成します。

using TMPro;
using UnityEngine;

public class DamagePopupGenerator : MonoBehaviour
{
    public static DamagePopupGenerator current;
    public GameObject prefab;

    private void Awake() {
        current = this;
    }

    public void CreatePopup(Vector3 pos, string text)
    {
        //インスタンス作成
        var popup = Instantiate(prefab, pos, Quaternion.identity);
        
        //テキストを設定
        var temp = popup.transform.GetChild(0).GetComponent<TextMeshProUGUI>();
        temp.text = text;

        //削除タイマー(1秒で消える)
        Destroy(popup, 1f);
    }

}

シングルトン(currentのとこ)にすることでどのオブジェクトからもGetComponentなしで参照することができるようになります。他のオブジェクトから呼ぶときはDamagePopupGenerator.current.CreatePopupで呼べます。

Hierarchyにオブジェクトを作成し、スクリプトをセットします。

Prefabもセットしておきます。

武器が敵にヒットしてダメージ判定を行うところに記述します。

private void OnTriggerEnter(Collider other) {
    
    //現在のAnimation情報を取得
    AnimatorStateInfo currentBaseState = animator.GetCurrentAnimatorStateInfo(0);
    if (currentBaseState.tagHash != AttackTag) return;

    //EnemyだけHitする
    if (other.tag != "Enemy") return;

    Debug.Log("OnTriggerEnter!:" + other.name);

    //当たった位置を取得する
    Vector3 hitPos = other.ClosestPointOnBounds(this.transform.position);

    //ここにパーティクルを生成
    Instantiate(hitParticle, hitPos, Quaternion.identity);

    //ダメージ表示
    DamagePopupGenerator.current.CreatePopup(other.transform.position + Vector3.up * 1.5f, UnityEngine.Random.Range(0, 1000).ToString());
}

アニメーションする

アニメーションさせるためにPrefab化したオブジェクトにスクリプトを追加します。
Overrideを忘れずに

DamagePopUpAnimationというスクリプトを作成しました。

using TMPro;
using UnityEngine;

public class DamagePopUpAnimation : MonoBehaviour
{
    public AnimationCurve opacityCurve;         //透過処理用
    public AnimationCurve scaleCurve;           //サイズ変更用
    public AnimationCurve heightCurve;          //高さ変更用
    
    private TextMeshProUGUI textMesh;                
    private float time = 0;
    private Vector3 origin;

    private void Awake()
    {
        textMesh = transform.GetChild(0).GetComponent<TextMeshProUGUI>();    //テキストの取得
        origin = transform.position;                                    //基準となる初期位置の取得
    }

    private void Update()
    {
        textMesh.color = new Color(1, 1, 1, opacityCurve.Evaluate(time));        //透過処理
        transform.localScale = Vector3.one * scaleCurve.Evaluate(time);     //スケール(サイズ)の処理
        transform.position = origin + new Vector3(0, 1 + heightCurve.Evaluate(time), 0);    //高さの処理
        time += Time.deltaTime;     //時間管理
    }
}

カーブはそれぞれ以下のように設定しました。点を右クリックし、Edit Keyで設定します。Both TangentsをLinearにすることでカーブをなくし直線になります。

横軸が時間、縦軸が値になっています。

いいかんじではないでしょうか。もし表示時に一瞬スケール調整前の文字が出てしまう場合は、文字の色でAlphaを0にしておくとよいと思います。

テキストをこちらに向ける

ダメージは薄い板に表示しているようなものなので、角度を変えると

このように斜めになってしまう。対策としてはカメラのほうに常にむく、Billboardingと呼ぶみたいです。スクリプト(UIBillboarding)を新しく作成します。

ちなみにDamagePopUpAnimation に入れてもいいのですが、他にも使いまわしたいということもあって分けます。

using UnityEngine;

public class UIBillboarding : MonoBehaviour
{
    private Camera cam;

    private void Awake()
    {
        cam = Camera.main;
    }

    private void Update()
    {
        //カメラのほうを向く
        transform.forward = cam.transform.forward;
    }
}

これをPrefab化したオブジェクトに追加します。overrideを忘れずに!

他のオブジェクトに重なっても見えるようにする

ここまでは、敵キャラクターの上に数字を出していました。できればキャラクターのとこに出したいので、OnTriggerEnterの関数内で以下のように変更しました。

//ダメージ表示
DamagePopupGenerator.current.CreatePopup(other.transform.position, UnityEngine.Random.Range(0, 1000).ToString());

すると・・・。

文字が重なって見えなくなってしまいました。これを修正するにはShaderを変更します。

ただし、Fontのマテリアルのシェーダーを変更するので同じフォントを使いまわす場合は注意が必要です。
ダメージ用フォントとして分けたほうがいいです。フォントをコピーして使います。

フォントをコピーしてOverlayってつけました。Shaderを変更します。

変更したシェーダーをテキストに適用します。

確認します。

OKかと思います。

コメント

タイトルとURLをコピーしました