(4-008)
(れいむ)この動画シリーズは、非公式ですが、2025年春 まで放送された「東京パソコンクラブ 〜プログラミング女子のゼロからゲーム作り〜」に関する内容でお送りしています。
今回は房総半島で夏休み、普段ナレーターの佐藤璃果さんがゲストで、ナレーターは小川彩(おがわあや)さんが代理となった第50回から第52回の3回連続の放送回の内容ですね。
公式では2023年6月30日から7月14日までの放送回です。まあ、まとめて「思い出カードゲーム作り」ですね。
1枚だけめくるアニメを作る
第50回21分6秒からスタート
前回は3Dだったので、今回はまた2Dに戻す・・・・あれ?
Basic (Built-in)の2D用が無い!
この場合は新たにプロジェクトを作成するしかないです。
次の画像はCopilotに解決方法を聞いてみた時のものです。

その後、非推奨のパッケージが見つかったという警告がでて、削ってよさそうだったので削った(Remove)して解決した。
以下は、はじめるにあたってあらかじめ用意しておく画像です。(ヨコ218ピクセル、タテ268ピクセルで統一させました。ファイル名は自由です。jpg形式で作成しました。この他に完成用の絵柄も必要です。)Assetsフォルダに放り込んでおきます。

第50回21分53秒で、Canvasの下にCard、その下にOmoteとUraというオブジェクトがあるのが見えるので、それに従う。
なお、Canvasの下に作るのは、Imageからの作成なのが注意だ。
これはCanvasのUI空間に従わせて、座標をRectTransformで入手するため
(空のオブジェクトから作ってしまうと座標はTransformとなり、後々座標を利用できなくなるので困る)うp主はそのあたりを理解していなかったので、時々Transformが見えるかもしれないが、これはRectTransformであるとみなさんは脳内変換して観てください。
第50回22分3秒から
アニメーションというコンポーネントは過去の盆場マンでもとりあげたものでしたが、
でも・・・あれ?Y軸0度の状態と90度と180度の3枚だけで、間のフレームが計算で埋めてくれる・・・って言うのは?
(1)イベントをそれぞれ設定する。AddKey
(2)録画するセッティング
Cardでクリックするとその対象について録画ボタンが押せるようになる。
(3)録画中に変更した内容が、前のイベントと異なる部分が、自動的にアニメーションになる。
第50回25分6秒
そして、ここからはクリックしてアニメが動くということですが・・・実行する際にすでに自動で動く?!
(4)本編ではあまり紹介されていない事項で、Idleの設定について。
実行する際にすでに自動で動くことから、クリックして動かすにはIdleを自動で動くようにして、条件が成立(マウスをクリックする)があると、カードを開くアニメにする
ところが!
バージョンが古いことが判明。ただし、4~5というのはAIの解釈としてあやしい(昔は2022とか)
Animationはレガシー→ Animatorにする。
Card.csの作成
関数を拾うタグ?から関数をうけられれば、マウスが反応する!
第50回まとめ
第50回28分18秒
・アニメーションでRotation(回転)を使ってカードをめくる動き
・Play(“Open”)=開くプログラミング
以下は、50回の時点でのCard.csです。

カードを複製して、判定まで作る
第51回19分31秒から
C#スクリプトを“Game Manager”にすると、なぜか歯車になります。「歯車った!」
うp主のは・・・はぐるまない!
まあ・・・あんまり気にするところではなさそうだ
しくみを説明すると
このGame Managerに「開いたカード」を登録する。もう1枚登録して2枚になったら同じかどうかを見て
同じだったら そのままか少し色を暗くする
違ったらカードを戻す
判定を終えたら2枚登録したカードを登録から外す
第51回19分57秒
GameManager.csの中で、まずは1行入力。
public static List<Card> selected = new List<Card>();
第51回20分39秒
説明が前後しますが、アニメーションのイベントの設定を行う。
Card.csの中で、OnCardOpen()の変数の公式宣言をしておく。
Card.cs
using UnityEngine;
using UnityEngine.UI;
public class Card : MonoBehaviour
{
public Animation anim;
public Image omoteImage;
public void OnmouseClick()
{
Anim.Play(“Open”);
}
public void OnCardOpen()
{
//ここはまだ何も書かない
}
}
次に、Openのアニメで、開き終わったタイミングでイベントを追加(AddEvent)
そこのイベントで、OnCardOpen()を選択
ちょっと、ここは手間取った箇所です。
大事なのは、Cardを選択してアニメを再生できるようにしてから、Function1項目のみで表示されているときに関数選択できること。これが第51回20分35秒で弓木さんの顔のアップで関数を選んでいるシーンで関数の選択を行っています。
第51回21分6秒
「同じだったら」のプログラム
void Update()
{
if(selected.Count == 2)
{
if(selected[0].omoteImage.sprite == selected[1].omoteImage.sprite)
}
}
判定だけ書いて、後程完成させる
第51回21分31秒
「違ったら」のプログラム
else以下で入力
else
{
selected[0].anim.Play(“Close”);
selected[1].anim.Play(“Close”);
}
さりげなくCloseとか登場していますが、ここでOpenのアニメの中でClose、つまりOpenと逆の動作のアニメをつくっておく必要があります。何気にしんどい!
第51回22分15秒
同じだったら グレー(灰色)の色をつける
void Update()
{
if(selected.Count == 2)
{
if(selected[0].omoteImage.sprite == selected[1].omoteImage.sprite)
{
selected[0].omoteImage.color = Color.gray;
selected[1].omoteImage.color = Color.gray;
}
else
{
selected[0].anim.Play(“Close”);
selected[1].anim.Play(“Close”);
}
selected.Clear();
}
}
第51回22分16秒
どちらにしても、2枚目だったらカードを元に戻す(2枚登録したカードを登録から外すして次は1枚目のカードの登録の状態にする)
第51回22分37秒からは、カードを7枚3段にduplicateなどで増やします。
これまで動画を観て下さったかたなら、「プレハブだ!」と思う人もいるかもしれません。
うp主も一瞬思いました。
でも、カードの表が違うなど、細かい違いがでてくるので、ここは素直にduplicateで増やしていきましょう。
第51回23分47秒
7枚×3段だったら、2枚ずつの偶数にならないので、最下段だけ6枚にする
第51回24分23秒
HierarchyにCreate Emptyを作り「Game Manager」と名前を作る
第51回24分27秒
Assetsにある「Game Manager」をInspectorにドラッグ&ドロップ
ここうp主はGameManagerのオブジェクトを作り忘れて、動作しないので苦労したところがありました。必ず、忘れずにここにGameManagerを設定してGameManager.csが起動するように設定しましょう!
第51回24分34秒
カードの表を裏返しにする!
正確には、「表を無効にして裏が見えるようにする!」という動作です。
横スクロールアクションゲームの時のチェックポイントの様に、
カードの表をチェックではずしてオフの様にしておき、カードが同じだったら命令文でオン(true)にして表示する、という方法を行う。
omoteと検索して、
一番上のomoteを選んで
Shiftを押しながら、一番下のomoteを選ぶと一括で選択となる。この状態でチェックボックスを外すと、表が消えて、裏が表示される。これが表を裏返した状態に見える、という錯覚のようなテクニックです。
さっきも説明しましたがもう一度・・・今の段階で、Close・・・・このelse文で使っていますよね。だからCloseのアニメをつくらなければならないのです!
ここでまたさらにまぎわらしい展開が。
第51回24分38秒で弓木さんの顔が見えるInspectorのAnimationの項目、これはアニメーションファイルを複数使用できるコンポーネントだそうです。Animationのコンポーネントがありますが、古い方法らしいです。
OpenのAnimationウインドウでCleate New Clip を選んでCloseを新たに作成。
第51回25分02秒
カードを判定するプログラムを追加
以下はCard.csです。
using UnityEngine;
using UnityEngine.UI;
public class Card : MonoBehaviour
{
public Animation anim;
public Image omoteImage;
public void OnmouseClick()
{
Anim.Play(“Open”);
}
public void OnCardOpen()
{
GameManager.selected.Add(this);
}
}
カードの裏を無効にして動作の確認をする。
カード表が白→全10枚2組の数字→最終的はオリジナルの絵に差し替えの作業を行います。ここで第51回の内容が終了。
第51回のまとめ
・ゲーム全体を管理する仕組みを作る
・カードの絵柄を判別する
・カードを複製する
・カードを裏返しにする
シャッフルのしくみを作る~完成
第52回18分8秒
この第52回、このコーナーで完成です。あと残る作業は、「最初にゲームがスタートしたらランダムに並ぶようになって」「仕上げに思い出の絵を加えて完成」ということです。
第52回18分24秒
「最初にGameManagerに全部のカードを登録したい」と小林先生がおっしゃっていました。
続いて「これはシャッフルするために必要な手順」と言っていて、
public static List<Card> selected = new List<Card>();
の下に
publicCard[] cards;
を追加。
Card[]が配列 配列がわからない人は、
BASIC入門第7回「ジャンプ」で配列を詳しく扱っているので、これを参考にして下さい。
BASICじゃん!基本的なプログラミングの話はUnityでもBASICでも同じ。いろいろ脳内変換して参考にして下さい。まあ、配列なのでハコのような変数のグループというところです。
第52回18分40秒
Unityに戻ると、Gamemagerのところにcardsという配列の項目が表れます。
cardsの配列変数の宣言をしたからですね。
それで、登録です
さっきの様に登録したいカードの一番上をクリックして、Shiftを押しながら20番目の最後のCard(19)をクリックすると全部を選択。これをcardsにアタッチする。ドラッグ&ドロップする。
第52回19分01秒
cardsにアタッチして全登録が済んだ様子です。
第52回19分18秒
登録が済んだので、あとはランダム、カードをシャッフルする命令を加えていきます。
Index(さくいん)という意味で、ここでは変数としてidxという名前で使用します。
この変数は「複数のデータから特定のものを呼び出す通し番号」として使います
第52回19分52秒
GameManager.csでは、20枚のカードの中からランダムに1枚呼び出す という意味で追加
public static List<Card> selected = new List<Card>();
public Card[] cards;
void Start()
{
}
void Swap(int idx)
{
int rnd = Random.Renge(0, cards.Length);
}
void Update()
{
if(selected.Count == 2)
{
if(selected[0].omoteImage.sprite == selected[1].omoteImage.sprite)
{
selected[0].omoteImage.color = Color.gray;
・・・・・・・・・・・・・・・・・・・・
第52回20分30秒
これから行おうとする作業はシャッフルなので、カードの位置情報RectTransform
を取り換える、ということをしようとしています。
具体的には変数idxでの通し番号と、今、ランダムに1枚呼び出した変数rndを使って位置情報を交換します。シャッフルしているんですね。
GameManager.csでは、
public static List<Card> selected = new List<Card>();
public Card[] cards;
void Start()
{
}
void Swap(int idx)
{
int rnd = Random.Range(0, cards.Length);
RectTransform rtf1 = cards[idx].gameObject.GetCompornent< RectTransform >();
RectTransform rtf2 = cards[rnd].gameObject.GetCompornent< RectTransform >();
}
void Update()
{
if(selected.Count == 2)
{
if(selected[0].omoteImage.sprite == selected[1].omoteImage.sprite)
{
selected[0].omoteImage.color = Color.gray;
・・・・・・・・・・・・・・・・・・・・
第52回20分54秒
プログラムのポイント
このまま数値を上書きすると、上書きされた方は消えてしまうので、Tempとして、一時保管場所にコピーして交換作業を行います。
GameManager.csでは、
public static List<Card> selected = new List<Card>();
public Card[] cards;
void Start()
{
}
void Swap(int idx)
{
int rnd = Random.Range(0, cards.Length);
RectTransform rtf1 = cards[idx].gameObject.GetCompornent< RectTransform >();
RectTransform rtf2 = cards[rnd].gameObject.GetCompornent< RectTransform >();
Vector3 temp = rtf1.position;
rtf1.position = rtf2.position
rtf2.position = temp;
}
void Update()
{
if(selected.Count == 2)
{
if(selected[0].omoteImage.sprite == selected[1].omoteImage.sprite)
{
selected[0].omoteImage.color = Color.gray;
・・・・・・・・・・・・・・・・・・・・
第52回21分35秒
最後にfor文で20枚、i=0から配列の数20、card.Lengthまで達しない0から19までの繰り返しの初期設定をすることを忘れないように、ですね。
GameManager.csです。
public static List<Card> selected = new List<Card>();
public Card[] cards;
void Start()
{
for(int i=0; i<cards.Length;i++)
{
Swap(i);
}
}
void Swap(int idx)
{
int rnd = Random.Range(0, cards.Length);
RectTransform rtf1 = cards[idx].gameObject.GetCompornent< RectTransform >();
RectTransform rtf2 = cards[rnd].gameObject.GetCompornent< RectTransform >();
Vector3 temp = rtf1.position;
rtf1.position = rtf2.position
rtf2.position = temp;
}
void Update()
{
if(selected.Count == 2)
{
if(selected[0].omoteImage.sprite == selected[1].omoteImage.sprite)
{
selected[0].omoteImage.color = Color.gray;
・・・・・・・・・・・・・・・・・・・・
実行してみる。
絵を差し替える。
完成!
第52回23分34秒の点数表示はテレビ放送用の演出ですね。今回のゲームでは点数の表示についてはさらに命令を追加する必要があります。この動画ではそこまで行う予定はありません。まあ、カードの通し番号は解かるので、そこからカードごとの点数を表示することは可能だと思います。カードの点数のための配列変数を新たに設ける必要があると思います。
完成時のソースとインスペクター
GameManager.cs

GameManagerのインスペクター

MainCameraのインスペクター

Card.cs

代表的なCardのインスペクター(上下2枚の画像)




コメント