kedzkiestの日記

普段の発見や開発の進捗について書いていきます。

Unityでキャラクターにトレイル上を移動させる

トレイルの上を走るユニティちゃん。

はじめに

3Dのゲームで、プレイヤーに思う存分フィールドを動き回ってもらうのではなく、決められたルートの上だけを動いてほしい場合があります。

例えばスーパーマリオブラザーズシリーズのステージ選択画面や、ヘブンバーンズレッドの散策フェーズでは、プレイヤーはあらかじめ決められた道(トレイル)の上だけを好きに移動できます。
youtu.be
youtu.be

今回はUnityを使って、トレイル上でのみプレイヤーが移動できるシステムを実装してみました。

完成したもの

github.com
youtu.be
シーンビューとゲームビューを同時に見せているため、キャラクターがトレイル上を移動している様子が分かりやすいと思います。カメラの挙動はヘブバンをちょっと意識しました。

動画の途中でトレイルをループさせる設定に切り替えましたが、始点と終点が同じであっても上手く動作しています。強いて言えば経路点(waypoint)のつなぎ目でキャラクターがカクついているかもしれません。

どのように実現したか

CinemachineのDolly Track with Cartを使用しました。Dolly Trackでルートを指定するとCartがその上を移動できるようになりますが、キャラクターにCartを追従させることで、キャラクターがトレイル上を動いているように見えます。基本的な方針はこちらの記事で紹介されていますので、ぜひご覧ください。
tsubakit1.hateblo.jp
上の記事と異なる点として、今回はプレイヤーがキャラクターを操作することを想定しているため、TimelineではなくC#スクリプトを使用しています。また、トレイル上を移動させたいキャラクターをCartの子オブジェクトにしていません。

使用したC#スクリプト

using UnityEngine;
using Cinemachine;

public class PlayerController : MonoBehaviour
{
    [SerializeField] private CinemachinePath path;
    [SerializeField] private CinemachineDollyCart cart;

    [SerializeField] private float moveSpeed;
    [SerializeField] private float rotateSpeed;
    [SerializeField] private float howCloseCanReachPathEnd;
    private Animator anim;

    void Start()
    {
        anim = GetComponent<Animator>();
    }

    void LateUpdate()
    {
        if (Input.GetKey(KeyCode.LeftArrow) && Input.GetKey(KeyCode.RightArrow))
        {
            anim.SetBool("isRunning", false);
            return;
        }

        Rotate();
        Move();
    }

    [HideInInspector]
    public Quaternion rot;

    private void Rotate()
    {
        // active character rotation using keyinput
        if (Input.GetKey(KeyCode.RightArrow))
        {
            rot = Quaternion.Euler(0, cart.transform.rotation.eulerAngles.y, 0);
            transform.rotation = Quaternion.Slerp(transform.rotation, rot, rotateSpeed * Time.deltaTime);
        }

        if (Input.GetKey(KeyCode.LeftArrow))
        {
            rot = Quaternion.Euler(0, cart.transform.rotation.eulerAngles.y, 0) * Quaternion.Euler(0, 180, 0);
            transform.rotation = Quaternion.Slerp(transform.rotation, rot, rotateSpeed * Time.deltaTime);
        }
    }

    private void Move()
    {
        // passive character moving along the path(cart)
        transform.position = cart.transform.position;

        // active character moving using keyinput
        if (Input.GetKey(KeyCode.RightArrow))
        {
            if (!path.m_Looped && Mathf.Abs(path.PathLength - cart.m_Position) < howCloseCanReachPathEnd)
            {
                anim.SetBool("isRunning", false);
                return;
            }

            cart.m_Position += moveSpeed * Time.deltaTime;
            anim.SetBool("isRunning", true);
            return;
        }

        if (Input.GetKey(KeyCode.LeftArrow))
        {
            if (!path.m_Looped && Mathf.Abs(cart.m_Position) < howCloseCanReachPathEnd)
            {
                anim.SetBool("isRunning", false);
                return;
            }

            cart.m_Position -= moveSpeed * Time.deltaTime;
            anim.SetBool("isRunning", true);
            return;
        }

        anim.SetBool("isRunning", false);
    }
}

色々書いてありますが、アニメーションの制御やキャラクターの回転のための記述も含まれているだけで、特に大事なのはMove関数の中のこの部分です。

// このスクリプトがアタッチされているキャラクターにCartを追従させる
transform.position = cart.transform.position;
// Cartの位置を更新する
cart.m_Position += moveSpeed * Time.deltaTime;

キャラクターをCartの子オブジェクトにしている場合は一行目が不要です。cart.m_PositionはDolly Trackによって指定されたパスのどの位置にCartがあるかを示しており、0からパスの長さの間で変動します。キー入力によってCartがパス上を動く->キャラクターがそれを追従する->キャラクターがパス上を動いているように見える、というような仕組みです。

おわりに

トレイル上を動くキャラクターの挙動を実現できました。当初の方針としてはシーン上にwaypointとなるゲームオブジェクトを配置し、それらを配列に格納してインデックスを更新しながらそれらを経由していくことを考えていましたが、Cinemachineに便利な機能があって良かったです。

ライセンス表記
© Unity Technologies Japan/UCL


おまけ:ユニティちゃん軍団

youtu.be
(ちゃんと隊列みたいに移動するのも再現してみたい)

2022/11/30 追記

Unity 2022.1からはSpline機能が公式パッケージになります。
youtu.be
そこで、Dolly Cartよりも簡単にキャラクターにトレイル上を移動させられそうだったので試してみたのですが、Dolly CartにおけるCartのようにパス上の特定の点を示すものがないので、パスに沿ってキャラクターをインタラクティブに動かすことが出来ませんでした。プレイヤーが操作する必要がないなら(例えば経路上を移動するNPC)、上の動画で紹介されている「スプラインに沿ったアニメーション」を使うことで実現できそうです。

せっかくなので以前作ったシーンに少しだけ手を加えてみました。
youtu.be
Unityのバージョンは2022.1.23f1です。

実際にキャラクターが移動する経路はCinemachineのDolly Cartで作成されていますが、CinemachinePathに限りなく近い経路をスプラインでも作成し、スプラインに沿って石のオブジェクトを配置した後、周囲の環境を全く描画しないことで、石を渡ってキャラクターが空中を移動しているように見せています。浮いている石はプレイヤーが近くに来ると少し沈むようにC#コードを書きました。

Spline機能はまだ登場したばかりでドキュメントもあまり充実していないようなので、「Dolly CartにおけるCartのようにパス上の特定の点を示すものがない」と書きましたが、後からそれが間違いだったと分かり、プレイヤー操作によるトレイル上の移動もSplineを使って実現できるようになるかもしれません。今後に期待ですね!

CAPCOMオープンカンファレンス RE:2022に参加してきました!

大阪府梅田クリスタルホールにて2022年9月30日に、CAPCOMの開催するオープンカンファレンスに参加してきたため、忘れないうちに感想を残しておきます。

はじめに

今回のイベントでは全部で21個のコンテンツがあり、どの順番で見ていこうか迷ってしまいました。どんなコンテンツがあるのかは公式サイトからご確認下さい。

感染防止対策で2時間ごとに参加者が入れ替わるため、時間内にちょうど回りきれるか心配でしたが、イベントが終わってみると意外とちょうどいい時間だと感じました。いくつかの体験型コンテンツには参加できませんでしたが、横から見ているだけでも楽しいですし、コンセプトも理解できました。

21個すべてのコンテンツに対する感想を書いていると長くなってしまうので、個人的に面白い・勉強になると感じたトップ3のコンテンツに絞って紹介したいと思います。

見た目と違う?当たり判定だけの世界

会場ポスター

このコンテンツでは当たり判定という奥の深いテーマのもと、バイオハザード ヴィレッジを例に当たり判定のパターンや、ゲームを成立させるための工夫が紹介されていました。

抽象的な当たり判定のパターンをいくつか用意し、個別の事例にそのどれかをあてはめるというのは、今まで私が思いつかなかった新たなアイデアでした。この考え方を採用することにより、元となるスクリプトがあれば以降はパラメータを調節するだけでよくなります。

私が普段ゲーム開発に使用しているUnityでは、当たり判定を実現したいときは基本的にコライダーと呼ばれるコンポーネントを使用しますが、球やカプセル、メッシュといったように基本的な形状はすでに用意されていますから、抽象的な当たり判定のパターンがある程度存在しているとも言えます。しかし、このコンテンツで紹介されているような目的ごとに分けられた当たり判定というのは、単に形状による抽象化よりもレベルが高いと感じました。

また、このコンテンツの名前にもなっている「見た目と違う?」という部分に関してですが、快適なゲーム体験のためにはいつでも見た目通りに判定を作るのではなく、時には見た目通りではない・誇張した判定も作られているということでした。プレイヤーに納得してもらうために、なるべく見た目通りの判定を作るべきだと考えていた私にとっては、それが有効な場面もあるのか、と考えさせられるコンテンツでした。

ゲーム体験とホラー体験を両立する敵AI製作

会場ポスター

このコンテンツではバイオハザード ヴィレッジを例に、「怖いけど簡単なゲーム」をどのように実現したのかが紹介されていました。

ポスターを見ていて驚いたのは、プログラマひとりでゲーム体験とホラー体験の両立を構想から担当したことです。もちろんゲームデザイナーなど他にも欠かせないメンバーがあったことと思いますが、それでも自分がプログラマの立場だったら、ただコードを書くだけでなくゲームロジックの分解など、ある種企画のようなこともこなせるのか疑問に感じました。

また、視覚表現だけに頼らず、振る舞いによってもホラーを演出するというのは、アーティストの手を借りずにホラー体験を深められるという意味で、メンバーの負担を分散できる良い手段であると思います。チーム開発において自分がプログラマーをしているとき、「それはアーティストとかサウンドの仕事だから」と割り切ることをせず、自分にもできることがないか考えるきっかけとなりました。

敵の意思決定のためのシステムとして何が使われているのかは分かりませんでしたが(例えばFSM、ビヘイビアツリーなど)、ゲームの難易度や集団でいるかによって思考を切り替え、時にパラメータだけでなく選択可能な行動に制約を加えて全体の難度調節を行うというアイデアは個人製作でも活かせそうです。

あらゆる設定をカスタマイズ!チェックプレイのための「DIP」機能

会場ポスター

このコンテンツではモンスターハンターライズ:サンブレイクを例に、ゲームを起動しながらパラメータの調整や仕様変更ができる、デバッグ機能の体験ができました。

この機能のすごいところは、何かを調整・修正するときに高速に試行が繰り返せることです。ゲーム開発経験者ならこのありがたみが分かるはず・・!

ゲームを起動しながらパラメータを変更したりフラグのON・OFFを切り替えたいシチュエーションは多々あり、Unityでやる場合はSerializeFieldを使ってインスペクターから変更するか、ボタンやスライダーのようなUIを使用してゲーム画面から変更するなどの選択肢があります。今回体験したようにゲーム内UIでデバッグできるようにする場合は、画面を作るために最初だけコストがかかりますが、その後の開発は快適に行えるようになると思います。

このように包括的なデバッグ機能を体験してみて想像以上に便利に感じたため、今後ある程度規模の大きいプロジェクトを作ったり参加するときには似たような機能を導入してみようと思います。ゲームの中身に貢献するだけでなく、開発のプロセスの方にも貢献できるプログラマーでありたいですね。

おわりに

あっという間に終わってしまいましたが、楽しくて勉強にもなる最高のイベントでした!参加者は学生さんが多い印象でしたが、私が参加した時間帯が9時~11時ということもあり、ちょうどいい時間だったのかもしれません。私の大学では10月4日から3学期が始まるため、夏休み最後の良い思い出になりました。


余談

私は大阪の梅田クリスタルホールで開催される方に当選したため、福島県から2年ぶりくらいに飛行機に乗って現地に向かいました。前日の29日の14時ごろに伊丹空港に着き、30日の17時ごろに帰りの飛行機が出発するため、イベントを除いた空き時間で梅田を観光できました。人生初の大阪を存分に満喫してきました!(普段出不精の私はSweatcoinの歩数表示が1000歩以下のことがよくあるのですが、大阪にいた2日間はどちらも2万歩越え!当然筋肉痛になりました。)

お好み焼き。エビとイカと豚肉入り。
甘味処で頂いたあんみつ。つきたての餅を偶然いただけた。
居酒屋の串揚げとたこ焼き。ウーロン茶を添えて。

また、イベント会場のオープンを待っている間に新しい友だちができました!1つ年下の地元の方で、私と同じく普段からゲームを制作されているようです。彼のおかげで待ち時間を楽しく過ごせましたし、イベントを一緒に回って知見を共有できました。さらに、イベント終了後は梅田の街を案内していただきました!

現地でできた友達との昼食。

偶然のめぐり合わせに感謝するとともに、参加を申し込んでよかったと思わせてくれた彼にお礼をお伝えします。ありがとうございました!

NavMeshObstacleを使って部分的にNavMeshをリベイクしたような効果を得る

はじめに

Unityを使って制作していたゲームでNavMesh上の障害物がシーンから消えるたびにNavMeshをリベイクしていたのですが、そのたびに更新が必要ないところまで再計算されてしまい、計算負荷がかかって画面がカクついていました。そこでNavMeshObstacleを導入することで実行速度が改善されたため、備忘録として記事を書きました。

環境

Unity 2021.3.7f1

ゲームのコンセプト

一人称視点のゲームです。平面上にグリッド状の迷路がランダムに生成され、迷路のどこかにプレイヤー、敵、ゴールが生成されます。

迷路の大きさを7*7で設定すると、あるときはこんな初期配置。

敵は迷路内を巡回しており、プレイヤーを見つけると追いかけてきます。プレイヤーの目的は敵に捕まらないようにゴールを目指すことです。

また、プレイヤーの特殊能力として、一定時間ごとにパワーがチャージされ、外周を除く迷路内の好きな壁を壊すことができます。壁を壊した後のスペースは通行可能です。

敵が迷路内を巡回するしくみ

UnityではNavMeshAgentコンポーネントをゲームオブジェクトにアタッチすることで、NavMesh上を動くエージェント(AI)が作れます。同じことを今回の敵にも行っています。エージェントはNavMeshがないと動けないため、迷路が生成されたタイミングで一度NavMeshをベイクしています。

迷路を上から見ている状態。青い部分がNavMeshで、エージェントが動ける領域。

どこで問題が起こったか

前述したようにプレイヤーが迷路内の壁を破壊できる仕様のため、壁を破壊した後は敵エージェントが動ける領域もそれに合わせて変化する必要があります。しかしNavMeshのベイクは迷路の生成が終わった後一度しか行っていないため、破壊前の壁があった場所にはNavMeshが張られていません。

壁を破壊してもエージェントにとっては同じ地形。

そこでNavMeshSurfaceを導入しました。NavMeshSurface.BuildNavMeshメソッドによりゲーム実行中にNavMeshのベイクができます。これを使い、壁を破壊した後すぐにNavMeshをベイクすれば敵が新しい地形を認識できると考えました。
そこで実行してみると・・
youtu.be
壁を破壊する瞬間だけ画面がカクつくのが分かると思います。これは、BuildNavMeshメソッドによってシーン内すべてのNavMeshが再計算されることで計算負荷がかかるからだと思われます。動的にNavMeshを更新できるようにしたはいいものの、これでは快適にプレイできません。

どのように解決したか

迷路の壁となるゲームオブジェクトにNavMeshObstacleコンポーネントをアタッチし、Carveのオプションをオンにしました。
実行結果をご覧ください。
youtu.be
NavMeshObstacleを使うことで、ゲーム中にNavMeshの動的な変更が効率よく行えました。

おわりに

NavMeshObstacleを使うのはこれが初めてではなく、以前にゲームAIを学んでいたときに学習記録も残しています。
youtu.be
そのせいか、NavMeshObstacleは動いている障害物に使うものだという先入観を持っていましたが、今回の一件があったことで今後、より柔軟な使い方を検討できそうです。

Svelteで作ったアプリをGitHub Pagesでホスティングするまで

はじめに

新し目のフレームワークを使ってWebアプリを作る体験がしてみたいと思い、作ったはいいもののそれをGitHub Pagesでホスティングするのに詰まったので、解決までの手順を備忘録として残しておきます。

作ったもの

あなたと親族の関係性」というWebアプリです。"深さ2:あなた->父->母"のように関係性の深さと対象を選択し、最後に「結果を見る」ボタンを押すと、あなたと対象の家系図上の続柄が分かります。

何に詰まったか

.svelteファイルを編集し終え、アプリのルートディレクトリでnpm run buildして、生成されたファイル群をデプロイ用のブランチに置いたのですが、生成されたURLを辿っても空白のページになってしまう(リソースが正しく読み込まれていない)か、CSSとJSの抜け落ちた生のhtmlが表示されている状態でした。

解決までの手順

まず、Svelteの公式ページに載っている手順でプロジェクトの初期化を行いました。

npm create vite@latest myapp -- --template svelte
cd myapp
npm install
npm run dev

初めのnpm createを叩いた段階で、テンプレートプロジェクトを3種類のうちから選ぶよう聞かれますが、デフォルトで選択されているCounter付きのものを選択しました。
その後は自分の好きなようにApp.svelteファイルを編集した後、このブログのdeploy it in Github pages以降を参考に

npm install --save-dev gh-pages

を打ち、vite.config.jsファイルを

import { defineConfig } from "vite";
import { svelte } from "@sveltejs/vite-plugin-svelte";

export default defineConfig({
base: "/my-app/",
plugins: [svelte()],
});

のように編集し(my-appの部分は公開したいリポジトリ名)、最後にpackage.jsonファイルを

"scripts": {
  "dev": "vite",
  "build": "vite build",
  "preview": "vite preview",
  "deploy": "npx gh-pages -d dist"
},

のように編集しました。
あとはプロジェクトに変更を加えるたびに

npm run build
npm run deploy

を走らせれば、指定したリポジトリでデプロイ用のブランチが生成(更新)され、Webアプリとして利用できるようになりました。

Webページの音声読み上げ機能でクイズを作る

はじめに

Ctrl + Shift + UでWebページの音声読み上げができることを発見したので、2つの使い方を考えてみました。

基本

適当なWebページを開き、Ctrl + Shift + Uを同時押しすると上からメニューが出てきて、同時に読み上げが開始されます。
例としてWikipediaのバナナ(日本語版)のページを使ってみました。
Wikipedia記事へのリンクはこちらです。
バナナ - Wikipedia
youtu.be
右上の音声オプションから読み上げのスピードや読み手(言語や国籍)を変更することができます。上の例では読み手が日本人なので、基本的に日本語が読まれますがところどころ英語も読んでくれるようです。ときおり読み方がおかしいところがありますが、そういった箇所はWebページ側で読み仮名の設定をしてあげれば、視覚障害を持つ方にもフレンドリーなページになりそうです。無料でそれを実現するのは厳しいかもしれませんが・・。

では次から、私が思いついた音声読み上げ機能の使い方を紹介していきます。

①何のWebページを読み上げているかを当てるクイズ

リスニングクイズ形式のため、音声のみとなっています。察しの良い方なら最初の10秒くらいで答えが分かるかもしれません。
答えはこのWebページです。

②英語リスニングクイズ

前置きがなく、いきなり本文から始まるので注意して下さい。

(1)リンゴの原産地はどこ?
(2)リンゴを北米に持ち込んだのは誰?
(3)種から育てたリンゴの特徴2つは何?

①の変種ですが、高校までにやったような英語リスニングとなっています。


問題点

・スムーズに読まれない時がある
①と②の使い方両方に影響することです。音声が詰まっているような瞬間があり、いつでもスムーズに聞き取ることは出来ません。

・読まれる箇所がコントロールしにくい
これも①と②の両方に影響することですが、読み上げる順番は必ずしも見た目での上から下ではありません(例えばWikipediaでは最初にタイトルを読んだ後、前文を読む前に右側の要約枠に移る)。そのため、意図しない順番で情報が公開されることがあります。

また、画面上に表示されている文字すべてが読み上げられるわけではありません。実際にいくつか試してみると分かりますが、日本語のページ・日本語の読み手でも、見た目上表示されていながらも読まれない文字があります。

さらに、サイト名のネタバレ・個人情報の流出についても気をつける必要があります。私が当初予定していた、親しい間柄での時間つぶし程度なら問題ないかもしれませんが、一般に公開する場合には、読んでほしくないところがうっかり読まれないように注意して下さい。

・読み仮名の設定が適切に行われていないサイトでは正しく読まれない
読み仮名という概念のある言語の読み上げをする時に発生する問題で、今回なら①に影響します。本当の読み方とのズレを頭の中で補正しながら考察するのもひとつの面白さではありますが、やはりいつでも正しく読んで欲しいところです。

おわりに

Webページ音声読み上げ機能の紹介でした。冒頭ではCtrl + Shift + Uでのショートカットからの利用だけを書いていましたが、三点リーダー(ミートボールメニュー)からも利用できますね。

流行りのAIによる画像生成を試してみた

はじめに

近頃はDALL-EだったりMidjourneyのような自動画像生成ツールが流行っていますね。
絵師がいらなくなるかもなんて声もありますが、生成された画像を見てみると確かにそう思えるようなものもありました。

というわけで流行りに乗るべく、今回はDreamStudioというベータ版のツールを利用して画像生成を体験してきました!

環境設定

今回生成した画像はすべて下の設定を適用しています
Width: 512
Height: 512
Cfg Scale: 7
Steps: 50
Number of Images: 1
Sampler: k_lms
Seed: Random Seed


テーマ「Banana」

生成された画像

一瞬見てすぐにバナナだと分かりますね。ちょっと長いのが気になりますがそれも面白いところです。端の方だけ見たらズッキーニみたいにも見えますね。

テーマ「バナナ」

生成された画像

日本語入力でも大丈夫なのか試してみましたが、ダメそうです。
参考のためにバナナの花の画像も載せておきます。生成された画像とは似ても似つかないことが分かりますね。

バナナの花。画像は「バナナ」のWikipediaより。

テーマ「Harry Potter and the Chamber of Secrets」

生成された画像

テーマは日本語で「ハリー・ポッターと秘密の部屋」。画像はまんまハリーですが、別に秘密の部屋でなくともいいように感じます。ハリポタに詳しい人なら、この画像から秘密の部屋要素を見つけられるのでしょうか・・?

テーマ「Charlie and the Chocolate Factory

生成された画像

テーマは日本語で「チャーリーとチョコレート工場」。こちらもそれっぽいですね。

テーマ「Charlie Potter and the Chamber of Chocolate」

生成された画像

テーマは日本語で「チャーリー・ポッターとチョコレートの部屋」。上2つの名前を適当にかけ合わせたため、恐らく実在しない作品です。画像だけ見るとチャーリー側が優勢に見えます。

テーマ「The Most Beautiful Woman on Earth」

生成された画像

テーマは日本語で「この世で最も美しい女性」。どこか不気味というか、人間でないような雰囲気を感じます。

テーマ「What I fear most

生成された画像

テーマは日本語で「私が最も恐れているもの」。しょうがないことなのかもしれませんが、抽象的なお題を設定した時に、こんな感じの文章が大部分を占める画像が返ってくるのはちょっとつまらないですね。いつでもハリーのような鮮明な画像でお願いしたいところです。

テーマ「Curry in a lunchbox」

生成された画像

テーマは日本語で「お弁当箱の中にカレー」。パッと見て弁当箱にカレーが入っていることがわかります。

テーマ「The almighty god」

生成された画像

テーマは日本語で「全能神」。全能神の割には弱そうです。

テーマ「Panacea」

生成された画像

テーマは日本語で「万能薬」。カードゲームのカードのように見えます。

テーマ「The abyss」

生成された画像

テーマは日本語で「奈落」。同じ1単語でもTheを付けると映画っぽくなる・・?

テーマ「A flash of light in the dark night」

生成された画像

テーマは日本語で「闇夜を照らす閃光」。まさに、という感じの画像です。

テーマ「Monster Hunter」

生成された画像

テーマは日本語で「モンスターハンター」。ただのモンスター退治になりそうな予感もありましたが、防具を着てる感じやフォントなどから、しっかりゲームタイトルの方で認識しているようです。

テーマ「Resident Evil

生成された画像

テーマは日本語で「バイオハザード」。途中出てきたこの世で最も美しい女性より、こちらのほうがたくましくて好みかもしれません・・。

テーマ「Four-dimensional box」

生成された画像

テーマは日本語で「4次元の箱」。仮にこの箱が4次元物体だとしても、私達はそれを知覚出来ないので結局3次元物体にしか見えません。

テーマ「Sweet, spicy, bitter, sour」

生成された画像

テーマは日本語で「甘くて辛くて苦くて酸っぱい」。明太子(唐辛子?)ともやし、とうもろこしの粒のようなものが見えます。

テーマ「Potato PC」

生成された画像

テーマは日本語で「ポテトPC」。potate PCとは海外のスラングで、「じゃがいもに電極を刺して動いているパソコン(性能の悪いパソコン)」という意味の煽り文句のようなフレーズです。実際に生成された画像は、低スペックとは無縁のすばらしいゲーミングPCに見えます。

テーマ「The flow of time」

生成された画像

テーマは日本語で「時の流れ」。割と安直というか、すぐに想像できるような画像が生成されました。

テーマ「Counterclockwise」

生成された画像

テーマは日本語で「左回り」。時計が出ると思っていましたが、図書室を上から見下ろしたような画像が出来ました。


さいごに

DreamStudioを使って自動画像生成を思う存分楽しみました!
生成される画像のクオリティにはとても驚かされました、将来的には人間の描いた絵とAIが描いた絵に区別がつかなくなる日も来るのでしょうか。

このツールのすごいところは、他のツールにありがちな生成回数の上限がないことです。あなたの創造力を活かして、どんなアイデアでも形にしてみましょう!

TOEICで900点越えを達成したので今までにやってきたことを振り返ってみる

大学内で行われたTOEIC IPテストにて905点を取ることが出来たので、嬉しくなるとともに今までの英語学習を振り返ってみようという気持ちになりました。

高校生以前

特に英語が得意というわけでもなく、5段階評定で3か4くらいの成績だったと思います。

高校1年生

高校生の初めの方は学習内容的に中学校と同じところがあるため、特に勉強しなくとも授業にはついていけていました。

しかし、11月くらいの模試でひどい点数を取りました。それまではテストで60~70点ほど取っていたので「勉強しなきゃな」とは思いながらも実際に行動には移せていませんでした。

これを境に英語学習意欲に火がついたことを考えると、当時の私にとってはかなりの衝撃だったのだと思います。

私が取り組み始めたこととして、高校から配布された英単語帳をちゃんと覚えるということがあります。

結局のところ、単語が分からなくてはどうしようもないです。入学当初に英語の先生から言われたはずのことですが、ここでようやくその重要性を実感できました。

とはいえ、単語帳にあるすべての単語を覚えられる気はしませんでした。実際、悪い点を取った模試以前にも単語帳は眺めていましたが、一週間経たずに内容を忘れていたと思います。

そのため、どうすれば効率よく記憶できるか試行錯誤しました。初めは単語帳にある単語を端からすべてノートに書いていくことをしていました。

ノートに書き写した単語帳の一部。今思うとかなり非効率的・・

1単語ずつ単語帳からノートに写していき、意味と発音を確認しながら何度も書いていく作業を1000単語分行ったところで、効率が悪いと感じました(笑)。

しかしながら、効率が悪くとも確実に単語は覚えられているようでした。英語の授業の初めに生徒全員が起立し、単語帳からランダムに英単語が選ばれ、挙手して意味を答えられたら自分の席の縦か横のラインの人を着席させられ、全員が着席したら終了するゲームがあったのですが、そこで毎回一番に手を上げて答え、隣の人の疲れを減らしていました。

今まですぐに忘れていたはずの単語を時間が経っても覚えている自分が誇らしくなり、もっと多くの単語や表現を知りたい気持ちが出てきました。

高校2年生

英語学習の方法は大きく変えていませんでしたが、英単語帳の覚え方は改善したいと思っていました。

というのも、2年生になった途端高校からもう一冊英単語帳が配布され、これも覚える必要が出てきたからです。

そこでこれまでの書いて覚えるやり方を変え、読んで覚えるやり方を試してみました。

やり方としては
①英単語を発音して、その日本語訳を読む。
②単語帳の左側のページにある単語すべてに対し、①を3回行う。
③単語帳の左側のページを赤いシートで隠し、日本語訳を見ずに意味を答える。
④右側のページに関しても同様に進めていき、単語帳の最後に到達したらまた最初に戻る。
といった具合です。

書いて覚えるやり方に比べるとそれぞれの単語を忘れやすくはなりますが、その分反復回数を増やせるので、総合的に見るとこちらのほうが私には合っているように感じました。

高校3年生

この頃にはもう英語は得意教科と言ってもいいくらいで、放課後に友達に英語を教えることもよくありました。英検2級を取ることをクラス担任の先生から勧められ、受けてみたらあっさり合格しました。

しかし、3年生の初めの方で鼻っ柱を折られるような出来事がありました。

ある日の休日、私がレインボーシックスシージをプレイしているとき、アメリカ人の方からボイスチャットで話しかけられ、なんだかんだで彼のスクワッドに参加することになりました。参加した先では彼以外に3人のアメリカ人がおり、そのままマッチが始まったのですが、何を言っているのか全く聞き取れず、非常に悔しい思いをしました。

自分の周りだけを見て慢心していたことに気付き、さらなる英語力を手に入れるため、英検準1級の勉強を始めました。(目指すべき英語力とは方向性が違う気もしますが)
そして3年生の2月に英検準1級の試験を受け、合格できました。

この時期の少し前から私の高校では会津大学2次試験対策なるものが開かれており、推薦で合格した私は初め参加しないつもりでしたが、小学生からの付き合いである友人が何人かその講座に参加していたため、応援したい気持ちで私も一緒に講座を受けることにしました。

そこでは会津大学の2次試験に必要な数学と英語を勉強するのですが、英語に関してはそれまでにやってきたことを存分に発揮し、講座外の時間に友人の質問に答えたりしていました。

卒業間近の時期には、実践的なフレーズの習得やリスニング力を鍛えたいと感じ、サウスパークという海外のアニメを見始めました。

初手から下ネタ・ブラックジョーク満載でしたが、とにかく知らない単語や表現が高速で流れていくので、英語字幕をオンにして頻繁に動画を止めながらノートを取っていました。

学校教育では触れたことのない(触れちゃいけない)英語を学習し、教科書的な英語から実践的な英語に少しずつ学びをシフトしていきました。

大学1年生

大学に入学してから初めてTOEICテストの存在を知りました。会津大学では1年生の8月に全員がTOEICを受けることになるのですが、その時の点数は895点でした。

今まで英検だけを受けてきたため、正直自分の現在位置を正確に掴めていない状況でしたが、点数で結果が出ることでそれが分かりやすくなりました。

しかしここでTOEICを頑張りたくなったわけではなく、TOEICが990点満点であることを考えると、1回目で895点取ったからもう受けなくてもいいかな、という気持ちでした。

大学ではそもそも授業内容が難しいのと、新しいことをやってみたい気持ちが強く(最終的にゲーム制作に落ち着きました)、英語学習は大学入学前までバリバリやっていたのが嘘のように止まりました。

しかし英語力が衰えたわけではなく、大学の英語の授業ではいつでもよい成績をとっていましたし、そのことがあって、研究室の手伝いをお願いされることもありました。

8月に初めてのTOEICを受け、その2週間後くらいに塾講師のアルバイトを始めました。そこでは小学4年生から高校3年生までを対象に数学と英語を教えています。

これまでの英語学習のノウハウを伝えることはもちろん、生徒さんの英検対策や英語の面接を実施する大学の試験対策などを行っていました。

大学2年生

この頃になると、大学入学後からほとんど英語学習をしていないことがたたって、日に日に自分の英語力が落ちていくことを感じていました。

しかし、これまでは英検合格やゲームでのコミュニケーションを取りたいといった目標があったのに対し、この時は英語を勉強するための強い動機がありませんでした。

少しでも英語力をキープしようとYouTubeで英語の動画を見たり、携帯やゲームの言語設定を英語にしてみたりと、色々工夫してみました。

その結果分かったことは、意外とこれらの努力が実を成しているということです。

高校3年生の終わりに教科書英語から実践英語へのシフトを決めたわけですが、YouTube上やゲームの英語はリアルにあふれていて、本来私が獲得したかった英語力を埋めてくれる気がしました。

また、この頃からDeepLを頻繁に使い始めました。大学1年生までは翻訳アプリは英語ができない人が使うものと決めつけていましたが、単に文法的に正しいだけでなくニュアンスまでもその場のノリに合った文章を出力してくれるため、非常に気に入りました。

また、自分自身でも英語を勉強してきたおかげで翻訳アプリのミスに気付くことができ、翻訳しやすいように文章の区切り方や構成を変えてあげるといったテクニックも覚えました。

大学3年生(現在)

大学3年生になった途端、大学の英語科目を受ける際に、最後に必ずTOEICを受けなければ単位取得できないという新たなルールが追加されました。

もうTOEICを受けることはないだろうと思っていた私にとっては、単位取得のために受けるしかないというマイナスの気持ちと、大学1年の8月の自分に比べてどれほど英語力が落ちたのか(あるいは上がったのか)を知りたいというプラスの気持ちの両方がありました。

会津大学は4学期制で、私は大学3年の1学期と2学期に英語科目を取っていたため、それぞれの学期の期末試験期間にTOEIC IPテストを受ける必要がありました。(この記事は2学期が終わった後の夏休み中に書きました)

1学期の最後に受けたTOEIC IPテストの点数は870点で、意外と保ったほうだな、という印象でした。

2学期の最後にもTOEICを受けることになりますが、そのために時間を割くよりも他にやりたいことがあったので、結局特に対策をしないままでした。

2学期の最後に受けたTOEIC IPテストの点数は905点で、この記事を書くきっかけとなった点数です。初めに嬉しいと書きましたが、もしかしたら心のどこかでは900点を越えたいと思っていたのかもしれません。

対策をしなかったのに点数が上がった理由としては、英語科目の最後に受けたこの2回分はオンラインでの受験だったことが考えられます。

1回目の受験では操作に少し戸惑っていた部分もありましたが、2回目の受験では問題を解くことに集中できたからこそ、高得点が取れたと思います。

今度こそ、これ以上TOEICを受けることはないと思っていますが、今までやってきたことが無駄じゃなかったと感じられました。