ゲーム制作勉強中!あこがれだったプログラマーに今からなろう!

昔、あこがれていたプログラマー。今からでも勉強してみようと思い立ち、チャレンジ開始! 勉強メモや、悪戦苦闘な日々の記録です。

1Wジャム:Clash!Plate!

スタジオしまづさんの1Wゲームジャムへ作品を出展しました😆

unityroom.com

皿割りシューティングです。
今まで学んできた要素を詰め込めるだけ詰め込んでみました。
InputSystem でキーボードでもマウスでもコントローラーでも遊べるようにできました。
ちょっと操作しづらいけどスマホでも遊べちゃいます。

皿を割った時に出る時の得点表示は、最後まで苦労したところ。
何せ、今まで3DでUIを使ったことがなくて、座標をどういうふうにしたら良いのか分からない。
nekojara.city
を参考にやってみたけれど、なぜかUIの座標が桁違いな値になってしまう。
ちょうど、今週の水曜が、しまづさんのオンライン講義だったので、教えを請い、なんとか完成させました😁

仕組みは、こんな感じです。
まず、皿のスクリプトに皿が割れた時のメソッドBrokenPlateを用意して、そこでスコア表示のUIを作成しています。

public class PlateManager : MonoBehaviour
{
    public void BrokenPlate()
    {
        int angle =Random.Range(0,240); 

            //割れた皿のオブジェクトを生成。
            //このとき、回転と破裂力をランダムにして、割れ方の違いを演出しています。

            Transform brokenPlate = Instantiate(brokenPrefab,transform.position,Quaternion.Euler(new Vector3(angle,270,90)));
            brokenPlate.localScale=transform.localScale;
            foreach (Rigidbody rigi in brokenPlate.GetComponentsInChildren<Rigidbody>())
            {
               int force=Random.Range(30,120);

               rigi.AddExplosionForce(force,transform.position,3f);
            }

            GameManager.Instance.AddScore(score);
            GameManager.Instance.Clash();

            //ここで皿のワールド座標をスクリーン座標に変換。
            var targetScreenPos=Camera.main.WorldToScreenPoint(transform.position);
       
            //スクリーン座標にスコア表示用のUIを仮作成  
            GameObject ui=Instantiate(uiPrefab,targetScreenPos, 
                                        Quaternion.identity, 
                                        _Canvas.transform);

            //スクリーン座標をUI座標?に変換。
            RectTransformUtility.ScreenPointToLocalPointInRectangle(
                                _Canvas.GetComponent<RectTransform>(),
                                targetScreenPos,
                                Camera.main,
                                out var uilocalPos);

            //その位置に仮作成しておいたUIの座標を変更
            ui.transform.localPosition=uilocalPos;

            //皿の色を取得
            var co=transform.GetComponent<Renderer>().material.color;

            //皿の設定メソッドに皿の得点と色を引数で渡してやる。
            ui.GetComponent<PointUI>().SetParam(co,score);

            //皿を消す
            Destroy(gameObject);    
    }
}

ポイントはCanvasのレンダーモード。
自分の場合は「スクリーンスペース-カメラ」ですが、ここが変わる場合、先ほどのRectTransformUtilityの引数が変わる感じです。

僕はこれが理解できずに延々と悩みました😅


UI側のスクリプトはこんな感じです。

using UnityEngine;
using UnityEngine.UI;

public class PointUI : MonoBehaviour
{
   private float _displaytime = 0.7f; //消えるまでの時間です。
    private float _timer;
    private Text _txt;
    private Vector3 pos;
    private void Awake()
    {
        _txt = GetComponent<Text>();
        pos = transform.position;
    }
    void Update()
    {
        _timer += Time.deltaTime;
        if (_timer > _displaytime)
            Destroy(gameObject);  //時間以上になったら消す
        transform.localScale=new Vector3(_timer*5f,_timer*5f,_timer*5f);// pos.y += 2f*Time.deltaTime;
  //時間まで毎フレーム、localscaleをあげてます。
    }

    public void SetParam(Vector4 _color,int value)
    {
        _txt.color = new Color(_color.x, _color.y, _color.z, _color.w);
        _txt.text = value.ToString();
    }

}

こんな感じです〜😁