見出し画像

【Unity】「ゆっくりツんでいってね!!!」を作ってみた

この度、某ツ〇ツ〇風ゲーム「ゆっくりツんでいってね!!!」をUnityで製作し、各所にアップロードいたしましたので、備忘録を記します。
ゲームはシンプルで1回1分強で終わりますので、良ければ遊んでください。

↓ゲームアツマール版

↓unityroom版

↓BOOTH版

↓GooglePlay版

参考にした教材

上記のスタジオしまづさんの講座を参考にいたしました。Udemy版とYouTube版がありますが、Udemy版だと買い切りで、YouTube版は無料ですが、メンバーシップ登録しないと見れないチャプターがあるという違いがあります。私は月額が発生するようなモノは苦手なので、Udemy版で受講しました。

講座の内容をざっくり説明

詳細はもちろん講座を受けて頂きたいのですが、やっていることはシンプルです。

1.ボール状のオブジェクトを大量にInstantiateする。
2.Physics2D.Raycastスクリプトを使用し、クリックした場所にあるボールの種類を判定する。
3.ドラッグした状態で、2と同じ種類かつ2から近い距離にあるボールを触った場合、Listに追加する。
4.Listが3以上のときにクリックをやめると、Listに入っているボールをDestroyし、Scoreを加算する。
5.4でDestroyした数だけ、再度ボールをInstantiateする。
以上の1~5をタイムオーバーまで繰り返します。

↓講師のしまづさんが作ったゲーム

参考になった点・ScriptableObjectをどこからでも参照可能にしてパラメータを管理

上記の記事の方法を使用すると、調整したいパラメータを一つのインスペクターにまとめることができます。プログラミング知識がない人でもパラメータ調整ができるので、チームで開発する時に便利だと、講座の中ではおっしゃっていましたが、テストプレイ中にあちこち開かなくていいので、個人開発でも充分役立ちます。

    //今回の製作でScriptableObjectに実装した変数
    [Header("初期のボールの数")]public int initBallCount;
    [Header("ボールを消したときの得点")]public int scorePoint;
    [Header("ボールの判定距離")]public float ballDistance;
    [Header("リストに追加したボールの表示をどれくらい大きくするか")]public float ballExpansion;
    [Header("ボムの有効範囲")][Range(1,10)]public float bombDistance;
    [Header("制限時間の初期値")] public int initialTime;

参考になった点・Updateはシンプルにする

今まではUpdateにごちゃごちゃ書いてたので、反省しました。
始めのほうにreturnを記載することで、後の処理をスキップできるのもいいと思いました。

   void Update()
    {
        //ゲームオーバー時はドラッグでの処理を行わない
        if (gameOver) {
            return;
        }
        //右クリックを押し込んだ時
        if (Input.GetMouseButtonDown(0)) {
            OnDragBegin();
        }
        //右クリックを上げた時
        else if (Input.GetMouseButtonUp(0)) {
            OnDragEnd();
        }
        else if (isDragging) {
            OnDragging();
        } 
    }

自分で追加した点・ゲーム開始時にステージがランダムで選ばれるようにした

東方projectの2次創作ゲームなので、キャラクターを活かしたゲームを作りたいところです。
今回「ゆっくり」として霊夢・魔理沙・アリス・パチュリー・妖夢・橙を採用したので、彼女たちのステージを用意してみます。

int charaNumber; //0=霊夢、1=魔理沙、2=アリス、3=パチュリー、4=妖夢、5=橙

[Header("背景。0霊、1魔、2ア、3パ、4妖、5橙 ")] public Sprite[] backGrounds;//Imageと勘違い。画像を配列に入れる場合はSprite    
[Header("ステージ名。0霊、1魔、2ア、3パ、4妖、5橙 ")] public String[] stageNames;//Textと勘違い。自分で打ち込むのはString    
[Header("曲名。0霊、1魔、2ア、3パ、4妖、5橙 ")] public String[] musicNames;//同上   
[Header("BGM。0霊、1魔、2ア、3パ、4妖、5橙 ")] public AudioClip[] musics;
[Header("ボイス「ゆ」。0霊、1魔、2ア、3パ、4妖、5橙 ")] public AudioClip[] yuVoices;
///////////////中略/////////////////
    private void Awake() {
        charaNumber = UnityEngine.Random.Range(0, 6); //この引数で0~5 https://pandoraxssscan-929.hatenablog.com/entry/2020/10/12/224414
        //ステージ名
        stageName.text = "Stage:"+ stageNames[charaNumber];
        //BGM名
        musicName.text = "♪" + musicNames[charaNumber];
        // 背景名
        backGround.sprite = backGrounds[charaNumber];
        //BGM差し替え
        bgmAudioSource.clip = musics[charaNumber];//BGMの再生はオーディオソースのclipを差し替える→オーディオソースを再生の流れ。
/////////////中略///////////////
    
//終わりの時のボイス再生
seAudioSource.PlayOneShot(owariVoices[charaNumber]);

キャラクターに対応した数字をUnityEngine.Random.Rangeでランダムに1つ設定し、同じ順番で配列にいれたBGM、ボイス、背景、テキストを使用します。UnityEngine.Random.Rangeはintで使用する場合は、第1引数から第2引数-1の間の数字しか選ばれないので、注意してください。
結果は以下のとおりです。

パチュリーステージ
霊夢ステージ
アリスステージ

自分で追加した点・ゆっくりをかき混ぜる(スピン)機能をつけた

本家のツ〇ツ〇にはステージをシェイクして、ツ〇ツ〇の位置を変える機能があるみたいなので、自分も導入してみようと思い、DoTweenでゆっくりの受け皿を振動させてみました。

が、駄目っ…!
ゆっくりが全て落下していった…。おしょらっ
原因はRigidbody2D周りではないかと、以下の記事から考えたのですが、
とうとう修正できませんでした。

なのでシェイクは諦めて、ボタンを押すと、画面中央で透明のバーがSetActive(true)になり、一回転するという方式にしました。

using System;
using DG.Tweening;

public class Spin : MonoBehaviour
{
    public GameObject spinBar;
    bool canPushButton = true;
    public AudioClip spinSE;
    public AudioSource audioSource;

    public void SpinStart()
    {
        if (canPushButton) {
            canPushButton = false;
            audioSource.PlayOneShot(spinSE);
            spinBar.SetActive(true);
            spinBar.transform.DORotate(new Vector3(0, 0, 360), 2, RotateMode.WorldAxisAdd);  //ワールド軸に対して
            Invoke("Vanish", 2.0f);
        }
    }

    void Vanish() {
        spinBar.SetActive(false);
        canPushButton = true;
    }
}

また、かき混ぜた時にゆっくりが受け皿の外に飛び出さないように蓋を設置しました。方法は下からだけ貫通する床をひっくり返して配置するだけです。

自分で追加した点・ゆっくりを繋げて消した長さによって残り時間が追加されるようにし、何秒追加されたかも表示されるようにした

講座のやり方そのままでは、ゆっくりをいくら長く繋げて消しても、
「消したゆっくり×100点」の得点が入るだけなので、得点計算はそのままで、残り時間を追加することにしました。
「 2(消したゆっくり-3)-1秒」です。
ただし、3つ消したときは1秒マイナスされてしまうので、以下の通りにします。

 int addTime = 2 * (removeCount - 3) - 1; //4つ以上連結させると残り時間ボーナス。4つで1秒、5つで3秒、6つで5秒…と増える
 if (addTime > 0) {
 timeCount += addTime;
 SpawnTimeEffect(removeBalls[removeBalls.Count - 1].transform.position,addTime);
 }
//SpawnPointEffectの第二引数をaddtimeに変更しただけ。
void SpawnTimeEffect(Vector2 position, int addtime) {        
GameObject effectObj = Instantiate(timeEffectPrefab, position, Quaternion.identity);        
PointEffect pointEffect = effectObj.GetComponent<PointEffect>();        
pointEffect.Show(addtime);    
}
public class PointEffect : MonoBehaviour
{
    [SerializeField] Text text = default;
    public void Show(int score) {
        if (score >= 300) {  //スコアは最低が300点なので、300以上ならスコア
            text.text = score.ToString() + "点";
        } else {
            text.text = "+" + score.ToString() + "秒";
        }
//////////////////以下略///////////////////

SpawnPointEffectにより600点が表示され、SpawnTimeEffectにより+5秒が表示されてます。SpawnTimeEffectはY座標を少し下げ、フォントと色も変えています。

自分で追加した点・ゆっくりがInstantiateされるフォルダを指定した

「ゆっくり」は沢山Instantiateされるので、そのままだとヒエラルキーが大変なことになります。
上記記事を参照して、あらかじめBallsフォルダを作成しておき、その中にInstantiateされるようにしましょう。
Ballsフォルダ(親オブジェクト)のスケールを変更することで、生成されるInstanceのスケールも変更されるので、ゆっくりの大きさを調整するのにも便利でした。

自分で追加した点・すべての形態でオンラインランキングを実装した

今回からゲームアツマールでもスコアランキングを導入することにしましたが、以下の記事を参照すれば簡単でした。

その他、unityroom、BOOTH、GooglePlayは以下の方法でオンラインランキングを導入することが可能です。一度unityroomのゲームジャムで導入したことはあるのですが、WebGL以外でも使用できるのは今回初めて知りました。
気を付ける事は、オンラインランキングにデータを送信する前にPlayerPrefs.Saveを行わないと、PlayerPrefsには記録されないということです。オンラインランキングの送信画面は別シーン扱いのようです。
なので、他の記録方法でも同じだと思います。

        
timerText.text = "TIME:0";       
resultScoreText.text = score+"点";
Buttons.SetActive(false);
gameOver = true;        
resultPanel.SetActive(true);

//スコアがハイスコアを超えたら        
if (score > highScore) {            
highScoreHyoji.SetActive(true);//highScoreが更新されていたら表示            
PlayerPrefs.SetInt("HighScore", score);//scoreをPrefsにセーブ           
PlayerPrefs.Save();//https://futabazemi.net/unity/high_score/

//atsumaruにチェックが入っていたら            
if (atsumaru) {                
PlayerPrefsAtsumaru.SetInt("HighScore", score);//scoreをPrefsにセーブ                
PlayerPrefsAtsumaru.Save();//                
Atsumaru.scoreboards.setRecord("1", score.ToString());//スコア送信                
Atsumaru.scoreboards.display("1");//https://goma980.blogspot.com/2021/03/webGLpg.html

//OnlineRankingにチェックが入っていたら           
} else if(onlineRanking){                
// Type == Number の場合                
naichilab.RankingLoader.Instance.SendScoreAndShowRanking(score);                
// Type == Time の場合                
var millsec = 123456;                
var timeScore = new System.TimeSpan(0, 0, 0, 0, millsec);                
naichilab.RankingLoader.Instance.SendScoreAndShowRanking(timeScore);       
   }        
}

わざわざAtsumaruとonlineRankingのbool値を付けたのは、後でアップデートを行いやすいようにするためです。
この記事を書いているときにバグに気付いたので、有効活用できそうです。

詰まった点・GooglePlayアップロード時のエラー2点

Android用にビルドする際に「Package Name has not been set up correctly …」のメッセージが表示される

Package Name has not been set up correctly

Please set the Package Name in the Player Settings.
The value must follow the convention
'com.YourCompanyName.YourProductName' and can contain alphanumeric characters and underscore.
Each segment must not start with a numeric character or underscore.

Edit > Project Settings > Player > Other Settings > Identification > Package Nameをcom.+企業名+プロダクト名に変えることで解決しました。

英語ワカリマセーン

GoogleConsoleにアップロードする際に「デバッグ可能な APK または Android App Bundle をアップロードしました」と表示される

解決方法は以下の通りです。AndroidManifest.xmlなんて、いじってないのに…。

この記事が気に入ったらサポートをしてみませんか?