4
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Unityで配管工風3Dアクションゲームを作った知見

Posted at

はじめに

1か月ほどで某配管工のような3Dアクションゲームを作りました。
以下のサイトにて遊べます。
SpaceJumpGame | unityroom

今後のゲーム制作にも役立ちそうな知見をまとめました。

(参考にならない)コードはGitHubにあげてます
https://github.com/Papyrustaro/Unity3DActionGame

バージョン

Unity2019.4.0f1

Cinemachineを使ったカメラの追従

プレイヤーが常に画面の中心になるようにカメラを移動すると、どの方向にプレイヤーが進んでいるのかわかりにくい。
ワンテンポ遅れて追従するようなカメラをCinemachineを利用することで簡単に実装できる。
CinemachineVirtualCameraのFollowにプレイヤーの(中心の)Transformを代入する。
あとはBodyとAimのタイプと、各種パラメータを設定するだけでそれっぽくなる。

cinema1.png
cinema0.png

今回はBodyをFraming Transposer、AimをDo nothingと置き、カメラの回転は別途スクリプトで書いた。
特に操作したパラメータは、画面のどこに対象物が映るようにするのか(Screen X/Y)、対象物とカメラの距離(Camera Distance)

Cinemachineを使った特定経路のカメラの移動

今回メニュー画面で、カメラがステージの周りを回り続けるようにしている。
これもCinemachineを利用して簡単に実装している。
CinemachineSmoothPathでカメラの通過点を設定。
スクリプトからCinemachineTrackedDollyのm_PathPositionの値を変えることで通路上のどこにいるのかを変えている。

cinema2.png

エディタ上から特定の処理を呼ぶ

今回はNaughtyAttributesというエディタ拡張を利用した。
https://github.com/dbrizov/NaughtyAttributes

これによって手作業でやっていたInspectorの操作などを大幅に削減できる。
以下はシーンに存在するスイッチと、スイッチで切り替わるステージを代入するスクリプトとInspector上の見え方。

[SerializeField, ReadOnly] private List<SwitchOnOffStageInHitHead> switches;
[SerializeField, ReadOnly] private List<SwitchOnOffStage> switchStages;

/*~~~~~~~~~~*/

/// <summary>
/// シーンに存在するswitch、onOffStageを代入・初期化。Inspector上から
/// </summary>
[Button(enabledMode: EButtonEnableMode.Editor)]
private void SetAllSwitchesAndOnOffStages()
{
    this.switches = new List<SwitchOnOffStageInHitHead>();
    foreach(GameObject obj in GameObject.FindGameObjectsWithTag("SwitchOnOff"))
    {
        this.switches.Add(obj.GetComponent<SwitchOnOffStageInHitHead>());
    }

    this.switchStages = new List<SwitchOnOffStage>();
    foreach(GameObject obj in GameObject.FindGameObjectsWithTag("SwitchOnOffStage"))
    {
        this.switchStages.Add(obj.GetComponent<SwitchOnOffStage>());
    }
}

extendEditer.png

自前で用意したい場合はこちらの記事などを参考にしてみては。
https://kan-kikuchi.hatenablog.com/entry/CustomEditor_Button

DoTweenはいいぞ(いいぞ)

今回初めてDoTweenを利用してみましたが、とにかく便利。
Unity全利用者使ってみるべき。

入門ブログを以前書きましたが、簡単なUIの処理にも重宝した。
これからもかなりお世話になりそう。
https://qiita.com/papyrustaro/items/2435369d13373417e1fd

WebGLでのJoy-Con操作

Unity上とWebGLビルド上ではどうもJoy-Conの入力が違うらしい。
アナログスティックは検知できない、という記事も見かけたが、全入力検知できた。
正直全く詳しくないので、環境次第では上手くいかないかもしれない。

以下のサイトにて、unityroomでのパッド入力の確認ができるようにしています。
https://unityroom.com/games/inputchecker

衝突したColliderの法線ベクトルが知りたい

まず、調べた限りTrigger(OnTrigger...)ではできない。
OnCollision...の中で、collision.contacts[0].normalでできる(1つでいいなら)

https://docs.unity3d.com/ja/current/ScriptReference/Collision-contacts.html
https://docs.unity3d.com/ja/current/ScriptReference/Collision.html

スクリプトからEventTriggerを設定する

ButtonなどのGUIでは、選択されたときやカーソルが上に乗ったときに特定の処理をさせたいことが頻繁に起こる。
そんなときにEventTriggerを利用しているのだが、Inspector上で毎回処理を代入するのが非常に面倒。
スクリプトでawakeなどで代入するのが楽。
https://light11.hatenadiary.com/entry/2018/01/31/234716

しかし、この場合だと処理を登録してもInspector上から見えないのが欠点。
見えないが登録はされている。
このせいで、予めスクリプトによる代入ができないのが悩みどころ。

床の移動にあわせてプレイヤーも移動させる

Rigidbodyによる摩擦計算を利用すれば、乗っている床が移動してもプレイヤーは乗ったままだが、
CharacterControllerを利用してプレイヤーを動かしていた場合、そうはいかない。
何もしないと、プレイヤーの座標はそのままで床だけ移動してしまう(しまいには落ちる)

一番手っ取り早い方法はプレイヤーgameObjectを移動床の子オブジェクトにすることだが、できることが制限されるので今回は別の方法を検討。

今回は移動する可能性のある床に接地したら、床のTransformを記憶し、前フレームからの移動分プレイヤーも移動させることで、移動リフトの上に乗ることを実装した。
移動リフトはいろんなゲームで登場するのでもっと賢い実装がありそうだ...

その他

壁キック実装

ブログを別で書きました。
https://papyrustaro.hatenablog.jp/entry/2020/06/17/121100

アニメーションによって、gameObjectが移動しないようにする

(怒涛のURL貼り付け)
http://tsubakit1.hateblo.jp/entry/2017/11/03/235913
http://aluminum-pepe.hatenablog.com/entry/2019/01/07/064816
https://gametukurikata.com/program/scriptisgrounded

アニメーションを瞬時に変える

has exit time をfalseに
transration duration を0に

時にはanimationclip自体の編集も

CharacterControllerを使用したときにキャラが地面から浮く

SkinWidthが原因。リファレンスではradisの10%。

ライティング

これ以上わかりやすい資料があるでしょうか、というほどわかりやすい資料
https://learning.unity3d.jp/2224/

線を描く

LineRendererを使う。
Inspector上からメソッドを呼ぶことで、特定のVector配列で線を引くことも可能

移動リフトの線を引く例

    /// <summary>
    /// Inspectorからリフトの軌道上の線を作成
    /// </summary>
    [ContextMenu("GenerateLineOfOrbit")]
    public void GenericLineOfOrbit()
    {
        List<Vector3> paths = new List<Vector3>();
        paths.Add(this.transform.position);
        for(int i = 0; i < this.path.Length; i++)
        {
            paths.Add(this.path[i] + paths[i]);
        }
        LineRenderer lineRenderer = this.gameObject.AddComponent<LineRenderer>();
        lineRenderer.positionCount = paths.Count;
        lineRenderer.SetPositions(paths.ToArray());
        lineRenderer.startWidth = 0.1f;
        lineRenderer.endWidth = 0.1f;
    }

プロパティをinspector上から変更する

自動でいい感じのColliderを作成する

SDユニティちゃんにライトが当たらない

shaderのせいみたいだが、変えると見栄えが...おとなしく初期設定に戻した。

Particleが場所や観る角度によって見え方が変わる

影がついているのが原因
ShaderをParticles/Standard Surfaceなどから、Particles/Standard Unlitなどに変えることで解決(壁張り付き時の煙)

4
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?