yikegaya’s blog

yikegayaのブログ

自作ゲーム作ってUnity Playで公開してみた

駄作でもいいから一回自分で仕様考えてゲーム作ってwebで公開してみたい。。と思ったんでUnityChan(フリーで使えるUnityの公式キャラ)の3Dモデルを操作して敵キャラと雪玉をぶつけあう3Dゲームを作ってUnity Playで公開してみた。

公開はUnityで作ったものをWebGLにbuildしてmacでコマンド叩いてzipにしてUnity Playにドラッグアンドドロップでアップしたらそれで終わった。よくできている。。

  • 作ったもの

play.unity.com

github.com

なんかゲームっぽくはなったけど遊んでて楽しくはないかな。難しい

とりあえず素振り的にもう何本か作りつつ3Dモデル、イラスト作成ツール使って簡単でも自分で素材作れるようにしつつちゃんと面白いもの作れるようになりたいな。

2Dシューティングゲームを開発するオンライン講座受講した

ノンフィールドRPG、ゾンビ系FPSの開発講座に続いて2Dシューティングゲームを開発する講座受講してみた。

www.udemy.com

Unity公式のチュートリアルを元に作った講座らしい。使ってる素材は同じだけど成果物は違うっぽい。

github.com

できたもの

vimeo.com

ECS接続用のシェルスクリプトを書いた

ECSで動かしてるFageteにECS Execで入りたい場面がちょくちょくあるんだけど毎回クラスタ名とタスクID、コンテナ名を貼り付けてコマンドを作るのが面倒だった

aws ecs execute-command \
    --cluster <クラスタ名> \
    --task <タスクID> \
    --container <コンテナ名>\
    --interactive \
    --command "/bin/bash"

例えばRailsのサービスを2つ運用していてそれぞれのサービスの構成が

  • クラスタ4つ(production環境、development環境、demo環境、test環境)
  • クラスタ1つの中にサービス2つ(アプリケーション本体とバッチ用サービス)
  • さらにアプリケーション本体のタスクにはRailsのコンテナとNginxのコンテナが入っている。。

みたいな状況だと結構面倒。タスクIDは管理画面に確認しにいくか別途コマンド叩いて調べないといけないし。

なのでシェルスクリプトで接続先のクラスタ、サービス、コンテナを選択できるシェルスクリプトを作ってみた。

aws-cliコマンドでクラスタ、サービス、タスクID、コンテナの情報を引っ張ってきて後はjqやawssedで必要な部分地道に切り取ってく感じ

#!/bin/bash
echo ECSコンテナに接続します。クラスタ、サービス、コンテナ名を選択してください。
echo
echo ? クラスタを選択してください
echo
CLUSTER_NAMES=`aws ecs list-clusters --output text \
              | awk -F'/' '{print $2}'`
select CLUSTER_NAME in $CLUSTER_NAMES exit
do
  if [ "$CLUSTER_NAME" = "exit" ]; then
    echo 処理を中断します
      exit 0
  fi
    break
done
echo
echo $CLUSTER_NAMEが選択されました
echo
  echo ? コンテナを選択してください
fi
echo
SERVICE_NAMES=`aws ecs list-services --cluster $CLUSTER_NAME --output text \
              | awk -F'/' '{print $3}'`
select SERVICE_NAME in $SERVICE_NAMES exit
do
  if [ "$SERVICE_NAME" = "exit" ]; then
      echo 処理を中断します
      exit 0
  fi
    break
done
echo
echo $SERVICE_NAMEが選択されました
echo
TASKID=`aws ecs list-tasks \
    --cluster $CLUSTER_NAME \
    --service-name $SERVICE_NAME --output text \
    | awk -F'/' '{print $3}' | head -1`

CONTAINER_NAMES=`aws ecs describe-tasks --cluster $CLUSTER_NAME \
                  --tasks $TASKID \
                  | jq '.tasks[0].containers[].name' \
                  | sed 's/"//g'`

echo ? コンテナを選択してください

echo
select CONTAINER_NAME in $CONTAINER_NAMES exit
do
  if [ "$CONTAINER_NAME" = "exit" ]; then
      echo 処理を中断します
      exit 0
  fi
    break
done

echo
echo $CONTAINER_NAMEが選択されました
echo $CONTAINER_NAMEに接続します
echo

if [ `echo $CONTAINER_NAME | grep 'nginx'` ] ; then
  SHELL_PATH="/bin/sh"
elif [ `echo $CONTAINER_NAME | grep 'demoa_service'` ] ; then
  SHELL_PATH="/bin/ash"
elif [ `echo $CONTAINER_NAME | grep 'demob_service'` ] ; then
  SHELL_PATH="/bin/bash"
else
  echo "error unexpected container"
  exit 1
fi

aws ecs execute-command \
    --cluster $CLUSTER_NAME \
    --task $TASKID \
    --container $CONTAINER_NAME \
    --interactive \
    --command $SHELL_PATH

こんな感じで動く。実行サーバはaws-cliのver2が入っているEC2でbashで呼び出す想定。

bash ecs_connection.sh
ECSコンテナに接続します。クラスタ、サービス、コンテナ名を選択してください。

? クラスタを選択してください

1) demoa-service-production    3) demoa-service-development     5) demoa-service-development
2) demoa-service-demo        4) demoa-service-production  6) exit
#? 3

demoa-service-developmentが選択されました

? コンテナを選択してください

1) demoa-service-development-app  3) exit
2) demoa-service-development-batch
#? 2

demoa-service-development-appが選択されました

? コンテナを選択してください

1) demoa_service_development_app
2) demoa_service_development_nginx
3) exit
#? 2

demoa_service_development_appが選択されました
demoa_service_development_appに接続します

ゾンビ系FPSを作成するオンライン講座を受講してみた

UdemyでUnityを使ってバイオハザードみたいなゾンビ系FPSを作成する講座を受講してみた。

www.udemy.com

ノンフィールドRPGに続けてUnityの講座を受講するのは2つ目。

ノンフィールドRPGを作成するオンライン講座を受講してみた - yikegaya’s blog

できたもの

こんなの

vimeo.com

今回もセールで買ったんで1400円くらいで7時間の講座の割には結構それっぽいものできたし学びにもなって満足。

学んだこと

  • 3Dモデルの動かし方、アニメーション実装
  • アニメーションエディタの使い方
  • FPSゲームの視点の実装
  • ゾンビの行動の実装方法(歩く、プレイヤーを追いかけて走る、攻撃、倒れる)
  • フィールド上のゾンビの自動生成(スポーン)
  • 人型の3Dモデルに銃を持たせて発砲⇨弾のゾンビへの衝突判定実装
  • ダメージ、弾薬の管理と画面表示
  • HP、弾薬回復アイテムの実装
  • ゲームオーバ実装
  • ゲームクリア実装
  • 地形の作り方
  • SE(Sound Effect)とBGMの導入
  • 自分のHPによって視界を暗くしていく方法(ポストプロセス)
  • タイトル画面からの遷移

使った素材

3Dモデルは「Mixamo」、地形のテクスチャは「TextureHaven」、サウンドは「SONNISS」というサイトで無料配布されている素材を使った。

Mixamo

Textures • Poly Haven

GameaudioGDC – SONNISS

3Dゲーム開発の知見

今回初めて3Dゲームの開発体験してみたけど

  • 3Dモデルのアニメーション
  • 地形の生成

に関しては自分で書いたプログラムでどうこうするUnityエディタ上の操作でほとんと作れるっぽい

地形

地形はUnityエディタ上で「Terrain」という3Dオブジェクトを作ってそこから山や木を生やしたり地形の表面にテクスチャ貼ったりをフォトショでブラシを塗るような感覚で作っていける。ちょっとビビるくらい簡単で便利。

3Dオブジェクトの操作

3Dオブジェクトに関しては「Mixamo」からダウンロードした時点で大分ゲームに組み込むための仕組みができていてそこがどう作られたのかは謎。「Blender」みたいな3DCG制作のソフトを使って自分で何かしら作ってみないと理解できないかも

MixamoからダウンロードしてUnityにインポートした時点でアニメーションが既に入ってる。例えばプレイヤーの3Dオブジェクトなら弾の装填とか銃を構えるアニメーション、ゾンビなら攻撃したり走ったり倒れたりする時のアニメーションが既に用意されていて、例えばフィールド上でゾンビを動かそうと思ったらUnity開発者は以下の挙動をプログラムすればいい

  • ゾンビのX、Z座標を一定の速度で動かし続ける。この座標が動いている間はゾンビが歩くアニメーションを繰り返すようにする
  • プレイヤーとの距離が一定に縮まったら歩くアニメーションから走るアニメーションに切り替えて移動速度を速くする
  • さらにプレイヤーとの縮まったら攻撃アニメーションに切り替えてプレイヤーのHPを減らす

アニメーション自体も3Dモデルの足や腕をプログラムで操作するのかな。。と思ってたけど少なくとも今回はそうではない

残ったバグ

最後まで動画見て同じようにUnityエディタ操作してC#スクリプト写経したはずが何故かバグが残ってしまった。

  • アイテムが何故か取れない
  • フィールド上の木の幹が謎に紫色になっている

この辺りは後で直したいが。。別のUnity講座もう買ってあるしそっちやりたいんで一旦放置

ノンフィールドRPGを作成するオンライン講座を受講してみた

Unityでゲーム作ってみたいと思い、Unityを使ってノンフィールドRPGを作成するUdemyの講座を受講してみた。 www.udemy.com

Unity選んだ経緯

2021年現在ゲームエンジンの人気はUnityかUnreal Engineの2択っぽい。以下Unreal Engineと比較しての選定理由

  • Unreal EngineはゲーミングPCみたいな高スペックのPCじゃないと開発が辛そう。普段使いのPCだとUnityの方が良さそう
  • Unreal EngineはPS5とかXBoxみたいな据え置きゲームの開発に使われていそうだが、とりあえずスマホゲームやブラウザゲームが作りたい。であればUnityの方が手軽そう。
  • Unreal Engineはプログラミングをしなくてもゲームが作れるのに対してUnityはC#スクリプトを書いて開発していく。ただ、ゲーム開発は未経験だけど職業プログラマだしC#書くのは問題なさそう
  • ネットの記事や書籍、オンライン講座などの情報も現状Unityの方がUnreal Engineより多そう

というような理由でとりあえずUnityに手を出してみることにした。

できたもの

講座内ではAndroidアプリとして公開すること前提に進めるけど、build設定をWebGLにしてブラウザで動かしてみた

vimeo.com

できるようになったこと

  • Unityの基本的なGUI操作
  • C#での基礎的なプログラミング
  • C#スクリプトでの2Dでのゲームオブジェクトの操作方法(ボタンクリックからのテキスト、画像、サウンドの切り替えやシーンの遷移など)
  • Prefabでのオブジェクトの再利用
  • サウンドの設定
  • アセットストアの使い方
  • 画像や音声などの素材の使い方
  • アニメーションのやエフェクトの実装

エラーメモ

初期設定

Mac Book ProでOSはBig Surの環境で構築してみた。

Unity HubというUnityの複数バージョン管理するツールでUnity2020をインストールしてみる。

unity3d.com

で、プロジェクト選択して立ち上げたら「「The project you are opening contains compilation errors. ...」みたいなエラーが出て言われるがままSafe Modeで立ち上げたらコンソールにエラーマークが出てるけど具体的なメッセージが出てこない。。

Safe Mode無視してそのまま立ち上げたら普通に動いたんだけどなんか気持ち悪いな。。

とりあえずエラーが出たのは初回だけでその後は普通に動作してそう。

DOTWeen

Udemyで買った講座を参考にDOTWeenというオブジェクトにアニメーションを追加するためのライブラリをインストールしたらコンパイルエラーになったがPCごと再起動したら直った。Unityだけ再起動してもダメだったんだけどこれもなんだったんだろう。Dockerコンテナいくつも立ち上げっぱなしにしてたりもしたんでリソース不足だったのか?

その他

WebGL向けの対応

この講座はAndrioidを想定して作られているけど自分としてはWebGLで自作のブラウザゲームを作って作って公開するのが第一目標なのでbuild設定をWebGLにして受講してみた。ただその場合は以下2点講座の内容と別に対応が必要。

  • 画面幅がそのままだと崩れるので各シーンのCanvasの「UI Scale Mode」を「Scale With Screen Size」に変更する必要あり
  • 日本語を表示する際にデフォルトのArelだと表示できないので日本語フォントをインストールする必要あり

f:id:ikeyu0806720:20211015144128p:plain f:id:ikeyu0806720:20211015144924p:plain

参考 naburacortan.blogspot.com qiita.com

今後

とりあえずクイズゲームみたいなシーンとテキスト、画像の遷移と最適源のエフェクトやアニメーションのみで作るゲームは自作できそうだけどもう少し凝った2Dゲーム(フィールド付きRPGとかレースゲームとか格闘ゲーム)を作るにはもう少しインプットの時間必要かな。。

あとUnityは3Dゲームも作れるけどそっちは全然わかってないので別途調べてみたい。

Railsデプロイ時の認証周りの対応メモ

最近新規で作ったRailsサービスのデプロイ作業してたら認証周りの対応が地味に面倒だったので対応メモ。

前提

  • JWTで認証するREST APIを提供するRailsサービス
  • Railsのバージョンは6.1.4
  • AWS ECS上のコンテナで稼働
  • RailsはPumaで起動してNginxとsocket通信させている

ロードバランサのヘルスチェック対応

まずデプロイしたらロードバランサ(ALB)のヘルスチェックで落ちるようになった。これは心当たりがあってrailsのconfigが原因で例えばrspecを起動する時にapplication.rbかtest.rbに以下の指定をしないと落ちる

config.hosts << "www.example.com"

ので本番環境もconfig.hostsの指定をしてないせいで、ロードバランサからのリクエストを拒否してしまってたのが原因とは気づいたけど、これどうやって許可するのかで迷った。

とりあえずconfig.host.clearと設定してしまえば通るんだけどなんか違う気がする。。

で、調べたらNginxでヘッダに許可するhostを指定する方法があってこれが良さそうだったのでこの通りに対応して通した。

Rails6のActionDispatch::HostAuthorizationとELBのヘルスチェックの共存 - Qiita

Railsのログ出力設定ではまる

これでヘルスチェックが通ってECSが動いたんだけど、その後適当なJSON投げて動作確認しようとしたら401が返ってきて通らない。CloudwatchはRailsとNginxでそれぞれロググループを作っていたんだけど、Nginx側のロググループにのみ401エラーが出ていてRails側には出力が何もない。

ってことはNginxの認証で落ちていてRailsに届いてないのでは??と思ってNginxの設定ファイルを見返したけどどう見ても問題なさそう。

それで試しにRailsのJWTの認証外してみたら通った。結局JWTがHTTPリクエストのAuthorizationのHeaderの鍵が間違っていたのが原因だったらしい。

じゃなんでRailsのログがCloudwatchに出てないんだ??と思って調べてたらconfigの設定でログが標準出力に出ていなかったのが原因だった。

config/environments/production.rb

  if ENV["RAILS_LOG_TO_STDOUT"].present?
    logger           = ActiveSupport::Logger.new(STDOUT)
    logger.formatter = config.log_formatter
    config.logger    = ActiveSupport::TaggedLogging.new(logger)
  end

環境変数RAILS_LOG_TO_STDOUTを追加したらCloudwatchで確認できるようになって解決。

<input type="file" accept="image/*">タグでAndroidの写真を扱うとエラーになる場合がある

HTMLで画像のみ受け付けるフォームを以下のように作って検証していたらAndroid端末でエラーが出るようになった。

<input type="file" accept="image/*">

スマホ端末だと上記のタグをつけた場合に保存されている写真をアップロードするのではなくカメラアプリを起動させて撮影した写真をそのまま送信できるんだけど、そうするとHuaweiAndroidでエラーが発生した。

で、調べたら対象の写真がHEIC形式(HEIF形式)でHTMLの"accept=image"がHEIC形式に対応していないのでエラーになっていたっぽい。

iPhoneで撮影した写真もHEICだけどiPhoneの場合はinputタグからアップロードする場合JPEGに勝手に変換してくれているらしい。自分はiPhoneユーザなのでここで差分があって気づかんかった。

対応

今回は上記のフォームから写真をバックエンドにpostしてからS3に送信したかったんだけど機能要件的にaccept="image"を外してサーバサイドでバリデーションかければいいよね。というかよく考えたら写真以外も扱える機能にしてもいいじゃん。という話になったけど、これ気づきにくいな。検証者がiPhoneユーザしかいないと辛い