正しい重力には従わないキャラクターのコンポーネント設定

Unityにて3Dキャラクターのコリジョン処理を含めた移動処理を実現したい場合、

  • CharacterControllerを使う
  • StandardAssetsのThird Person Controller的にCollider+Rigidbodyを制御する

などの方法や、その他ゴニョゴニョするなどがありますが、
どれが最適かはそれぞれのゲームで表現したいことなどに依存するかと思います。

今回、余暇で作ってるゲームのキャラクター挙動で、
Rigidbodyもつけつつ、Physicsの重力計算は無視したくなり、
いくつか試行錯誤したので、
その結果と過程におけるキャラクターのコンポーネント構成/設定を書いてみたいと思います。

キャラクター制御に対する一つのアプローチだと思って頂ければと思います。

そもそも

上記に上げたほうほうでなにが都合が悪いのか。

CharacterController

http://docs.unity3d.com/ja/current/Manual/class-CharacterController.html

Character Controller は、主にRigidbody による物理特性を使用しない、3 人称や 1 人称のプレイヤー制御に使用されます。

Character Controllerを使うと、Rigidbodyが無くても地形・壁との接触判定をした移動をしてくれます。
逆に、Rigidbodyを想定した、その他のRigidbodyを持つオブジェクトと共有できるような普遍的なコンポーネントなどを作るのは難しくなっちゃいます。

一方、プレイヤーキャラクターが物理特性の影響をうけるようにしたい場合は、キャラクターコントローラーの代わりに、リジッドボディ を使用した方がよいでしょう。

ともあります。

Third Person Controller

Standard Assetsのサンプルシーンに含まれる
https://www.assetstore.unity3d.com/jp/#!/content/32351
人型のキャラクターEthanがフィールドを走り回るデモです。

EthanにはRigidbodyとCupsleColliderがついており、
OnAnimatorMove()でanimator.deltaPositionから平行移動、
FixedUpdate()からRigidbodyに対してジャンプ処理のためにAddForceをしています。


物理的な挙動になりますが、
細かな挙動の作成が面倒であったり、
プレイヤーの状態によって色々な挙動にしたい場合など、
ちょっと面倒に思います。
特徴的なアクションをキャラクターにさせたい場合、
例えば残像を残しずつ瞬間移動をしたりとか、
そういうときはforceではなく、座標を直接制御したくなったりします。

今回、ひとまず落ち着いた方法としては、
上の二つの中間のようなあたりのやり方になります。

設定

f:id:kurihara-n:20160731174612p:plain

キャラクターにはColliderとRigidbodyをつけます。
壁等とのコリジョン処理はRigidbodyによって押し合い・壁ズリ処理してもらいます。
useGravityを無効にして、ジャンプ、落下処理は自分で行います。
一方、地面との設置判定は自前のスクリプトで、
Rayを飛ばして判定をとるようにします。

インスペクタはこんな感じ。
f:id:kurihara-n:20160731224556p:plain

LayerはPlayerにしています。
これはレイキャストによる地面判定時に自分のコリジョンにレイがヒットしないように
Playerのマスクを無視するよう指定するためです。

コンポーネントは上から、
Rigidbody
SphereCollider
CharacterLocomotion(移動のための自作スクリプト)
以下はその他もろもろ

要点としてはRigidbodyの設定になります。
まず、Dragはデフォルトでゼロになっていると思いますが、
物理挙動による力が加わった場合に減衰させるための値を入れておきます。

use Gravityのチェックは外しておきます。
このケースでは落下処理はスクリプトで行います。

constrintsの設定は、回転に関して3軸固定にするためチェックを入れておきます。
物理計算時に回転が入ってしまうことを防ぎます。

Character Locomotion

これは移動処理を行う自作スクリプトです。

例えば、ジャンプボタンを軽く押した場合に短いジャンプをし、
ジャンプボタンを長押しした場合にゆっくり大きいジャンプをする、
というようなキャラクターの挙動を書いてみたとします。

gist.github.com

途中にアニメータのフラグの設定など余計なものがありますが、あくまでひとつの例ということで
とりあえずそのままにしてます。

        verticalSpeed -= Time.deltaTime * gravityScale;
        transform.position += new Vector3(0.0f, verticalSpeed, 0.0f) + horizontalSpeed;

で自前で落下の処理を行っています。

その処理のあとのRayCastをしているあたりが地面の判定をしている箇所になります。
さきに書いたように自分自身のLayerであるPlayerのマスクを無視するよう指定しています。

JumpInputという別のコンポーネントで、ジャンプボタンの入力をトリガーするようにしています。
短いジャンプのイベントがきたら、

        verticalSpeed = 0.2f;
        gravityScale = 1f;

長いジャンプの入力で

        verticalSpeed = 0.08f;
        gravityScale = 0.1f;

と重力計算パラメータを変更するようにしています。

f:id:kurihara-n:20160731231753g:plain

あくまで一つの例ではありますし、
プログラムもこのままではまずいですが、
こういう実装の選択肢もあるかと思います。


ユニティちゃんライセンス

この作品はユニティちゃんライセンス条項の元に提供されています

Unreal Engine 4 で極めるゲーム開発 感想

Unreal Engine 4で極めるゲーム開発:サンプルデータと動画で学ぶUE4ゲーム制作プロジェクト

Unreal Engine 4で極めるゲーム開発:サンプルデータと動画で学ぶUE4ゲーム制作プロジェクト

とりあえず読了。
理解のためにはハンズオンが基本的には必要だけど、
後半時間があまりなかったので、
少々飛ばし読みしてしまいました。

もう少し実務でUE4を使うか、
サイドプロジェクトで使うとなったら
全て手順通りやってみたいと思います。

まずUE4の入門書としては
実際にサンプルのゲーム制作を通して
ひととおり必要になる要素に説明をしていて
とても良いと思います。
これはまだ僕がUE4初級者だから、ということもあり、
熟練者からしたら少し視点が違うかもですが。

この本は、ゲーム開発に関わる様々なセクションの人に向けて書かれており
各章ごと、どのセクション向けかという案内がされていたりもします。
その点では色々な人が導入しやすいような作りになっています。
ただゲームプログラマ視点からいうと、

  • 入力をとる
  • ゲームオブジェクトを移動させる
  • ゲームオブジェクトを動的に生成させる

という処理の実現方法が、
もう少し早い段階できても良かったかな、とは思いました。
ただ上に書いたとおりプログラマ向けだけの本ではないので、
そこはあまり無理を言ってもというところであります。

特に良いなと思ったのがワークフローについてで、
それぞれの章での説明の背景に、
つねにワークフローが意識されつつ、
本が構成されているように思ったところです。
4.2節ではまるまるワークフローに説明が割かれています。
また、他の箇所でも、
ゲームの実制作におけるワークフローの在り方について意識がされているように思いました。

そういう意味で、これはUE4の本ではありますが、
UE4を使用する人以外でも、
読んでみて為になることはあるのではないかと思いました。

Constant Force コンポーネント

 
Constant Force コンポーネントについて。
 
子供と作ってるゲームのために武器のアセットを買ってみたのですが、
 
 
デモの挙動を見ていると、
Constant Forceという慣れないコンポーネントがついていました。
 
Rigidbodyに一定の力を与えるためのコンポーネントのようです。
 
 
ドキュメントによるとforce/relative force, torgue/relative torqueというパラメータがあります。
relativeはオブジェクトのローカル座標系におけるベクトルで、
そうでないほうはワールドで処理されます。
 
ミサイルのように前に前にと飛んでいくオブジェクトはrelative forceを設定します。
また、例えば外からの力で飛ばされるような場合はワールドのほうを使うと良いのかと思います。
 
どうも検索すると3,4年前の動画も出てくるので、
ずっと前から存在していたコンポーネントのようです。
でも知らなかった…か、忘れてたか…。
 
このコンポーネントと同様な表現は、それほど難しくないスクリプトで実現できますが、
覚えておくと手早く使えて便利そうです。
 
飛んでく弾がConstant Forceによるものです。 

f:id:kurihara-n:20160721001338g:plain

着弾時にStandard assetsのparticle demoで使われているexplosionを生成すると

rigidbodyを持つオブジェクトが飛ばせて良い感じ:)

ユニティちゃんライセンス

この作品はユニティちゃんライセンス条項の元に提供されています

 

Unity アプリのバージョンを知る

スマートフォンアプリを開発していて、複数のデバイスを使っていたりすると、
「あれ、このデバイスに入っているこのアプリはいつのバージョンのもの?」
みたいなことに立ち会うことがたまにあります。

開発用のビルドでは、そのアプリがいつのアプリなのか分かると助かります。

そのためバージョンナンバーをアプリアイコンにオーバーレイで書き込むアセットを作って
ストアに公開しました。

AppVersionIcon
https://www.assetstore.unity3d.com/jp/#!/content/65849

f:id:kurihara-n:20160712230042p:plain

こんな感じのエディタウィンドウでバージョン番号を設定してapplyすると
アプリのアイコンにナンバーが書かれます。

f:id:kurihara-n:20160712230308p:plain

こんな感じ。

これは割とマイルストーンごとに手動で使ってもらうことを想定しているので、
自動でビルド毎にナンバーが書かれるようなものにはなっていません。

もう1つのやり方として、
自身のアセンブリからバージョン情報を取得し実行中にどこかで表示するという方法があります。

using UnityEngine;
using System.Collections;
using System.Reflection;
using System;

[assembly: AssemblyVersion("1.0.*")]
public class BuildDate : MonoBehaviour
{
    string   dateText;
    GUIStyle style = new GUIStyle();
    Rect     rect  = new Rect(0, 0, 640, 30);
    const int defaultFontSize = 12;

    void Start()
    {
        var asm = System.Reflection.Assembly.GetExecutingAssembly();
        var version = asm.GetName().Version;

        int days = version.Build;
        int seconds = version.Revision * 2;

        DateTime baseDate = new DateTime(2000, 1, 1);
        DateTime buildDate = baseDate.AddDays(days);
        DateTime buildDateTime = buildDate.AddSeconds(seconds);

        dateText = "Build date :" + buildDateTime.ToString();
        style.fontSize = (int)(defaultFontSize * Mathf.Max(1.0f, ((float)Screen.width / rect.width)));
    }

    void OnGUI()
    {
        GUI.Label(rect, dateText, style);
    }
}
<||

こちらはスクリプトをコンポーネントとしてアプリのメイン画面に存在するオブジェクトなどに追加しておけば、
ビルド毎の時間を時間を表示してくれるので便利です。
アプリを起動する必要はありますが、自動にビルドごとに更新されていくので情報は確実です。

例えば、相互に通信するアプリを作っていた場合バージョン違いで送受信するデータに不整合が起こるようなことは
まま起こりえます。

Electronに入門してみる

WinでもMacでも使えるGUI環境を持つツールなどのために、
ゲーム開発でも、
Electronが使える、使われるようになっていくかもしれないので
とりあえず環境の導入を試みてみました。

Windows 7 環境でのインストールのメモ。

基本的にはコチラに書いてある通りに行いました。

qiita.com

ダウンロードしたNode.jsのインストーラ
https://nodejs.org/download/release/latest/
node-v5.7.0-x64.msi

electronのバージョンは
v0.36.8
でした。

package.jsに書かれているmainのjavascript名が
index.jsになっていたので、そのままindex.jsを作成しました。

あとはQiita記事にある通りに進めて
electron-packagerで実行ファイルが作れてしまいました。
超簡単でした。

問題はこの先進めるにあたり、僕がnode.jsに詳しくない、
それどころかJavaScript自体に馴染みが無いってことかな。

AndroidでビルドはもういいRunしたいってとき

このポストは

Unity 2 Advent Calendar 2015 - Qiita

の7日目の記事です。

 

UnityでAndroidアプリ開発をしていて、apkをビルドはしないで、インストール&実行だけしたいときの解決っという小ネタです。

 

UnityのメニューやBuild settingsから行えるのは

Build  -> apkの作成

Build & Run -> apkの作成、デバイスへのインストール、実行

の2つ。

 

すでに一度apkを作成しており、デバイスにインストール&実行したいっていう場合には対応したメニューはありません。

そういった場合にUnity上だけの作業でどうにかしようとするのであれば、

もう一度Build& Runを実行する。

でも、これだともう一回ビルドしてapkを作成してしまうので、

その分、ビルドをする分時間がもったいないです。

 

まあ、そもそも、

この欲求を感じるケースが、

そんなに良くあるケースかというと、

どうだろうという話でもあるのではありますが、

同じビルドを配布したいようなケースではUnity Cloud buildを使えばいいし。

どういう場合にあるかというと、例えば、

オンライン要素のあるゲームで、

ローカル作業の変更をビルドして2つのデバイスにインストールして確認したい、とか。

まあ、たまにあったり、

ゲームのある部分の開発をしているときだけ良くあったりする、という感じでしょうか。

自分では、最近しばしば、どうにかしたいときがあったので、

対処を考えてみました。

 

解決方法として、

apkはandroidSdkに含まれるadbコマンドでインストールや起動ができるので、

それらを行うエディタ拡張をメニューに追加してやります。

 

 

gist.github.com

 

 外部プロセスの実行はProcessを使用して行います。

これを使ってadbコマンドを呼び出します。

最初にEditorUtility.OpenFilePanel()を使って、apkを選択します。

そのあと最初のプロセスでデバイスへのインストール(adb install)を行います。

WaitForExit()で終了をまち、その次にActivityを指定して起動を行うプロセスを実行します。

 

Windowsではアプリの起動までできることを確認しています。

Macでも一応試したのですが、僕の環境では起動には失敗しているみたいで、

ちょっと問題がある?かもしれません。インストールはできていますが、

完璧でなくて申し訳ないです。

 

 

 

Unity cloud buildのFailedメールをデスクトップ通知

Unity cloud build のビルド結果はメールで送られてくるが、

Failedの場合のメールも簡潔なので、
もう少し注意を引くようにしたい。
 
チーム開発している場合、
メインリポジトリのビルドの失敗はすぐ修正しなくてはいけない最優先事項。
コードの問題にはもちろん各人注意するとして、
コミット漏れなどで
たまにビルドに失敗するということはしばしばある。
 
以前の職場ではCIにはJenkinsを使っていたが、
ビルドステータスをCCTrayで表示しておくようにしていた。

Download Files List - CruiseControl.NET - OSDN

 

独自のchrome拡張で表示するようにしたかったが、

gmail関係の処理の扱いが分からなかったので、

既存の拡張機能を使ってデスクトップ通知を表示するようにする。

 

使ったchrome拡張は

chrome.google.com

 

まず、Unity Cloud Build からのメールでかつ、Faildがsubjectに入る場合に特定のラベルに仕分けをするようにgmailで設定。

from:(cloudbuild@unity3d.com) subject:Failed

というフィルタになる。

Checker plus for gmailは特定のラベルだけを通知するようにできるので、

オプションで、新しく追加したラベルだけ通知するように

オプションのAccounts/Labelsで受信トレイのチェックを外し、

新しいラベルだけにチェックを入れる。

通知が消えてしまうのは困るので、

オプションの「通知」、「テキスト通知ウィンドウ」を「後に閉じる」を「決してしない」に変更。

ひとまず以上でデスクトップ通知が行われるようになる。

もとからChecker plus for gmailを使っている場合は少々困るかもでけど、

gmail標準のデスクトップ通知とは共存できることを確認した。

 

本当は、chrome拡張を用意して、ユニティちゃんの絵で通知を表示するようにしたかった。

誰かこのあたりに精通している人が作ってくれないものだろうか。