gologiusの巣

プログラミングなどの技術メモです。誰かの役に立てるとうれしいです。

Unity 地面との接触判定

【2018/04/07追記】 ※この方法、OverrapSphereの半径分だけ、空中で判定されちゃうんですよね。 なので、着地判定時にモーション再生するときに、空中で着地してるように見えてしまいますね。 ダメですねこれ

本文

↓このクソみたいな発想後に考えたまともな接触判定方法

Unity 簡単な地面との接触判定 - gologiusの巣

方法

CapsuleColliderの足元でPhysics.OverlapSphere()を使用する→Sphere内のオブジェクトを走査→中に無機物があれば地面に接触している

gist.github.com

実行結果はこちら。注意点としては、使用するCapsuleCollider自体の接触判定が常にあります。

f:id:gologius:20171015124126g:plain

【再再更新】Unityでカメラ追跡したときにガタつく原因を考える

Unityで,プレイヤーを追跡するカメラスクリプトを作成していました.

まぁやっている方はたくさんおられるので説明は略しますが...

 

で,ゆっくり追従(追尾、補間)するカメラをつくろうとしたら,カメラがガタついてしまいます.

Vector3.Lerp や Vector3.SmoothDampでの補間を利用したものです↓

Unity でプレイヤーを追跡するカメラのスクリプト

ちなみに僕は Vector3.SmoothDampでやっています.Lerpよりガタつきが減ったように見えたので.

 

調べたところ,物理演算とゲームループが同期できていない?(Unity カメラ がたつく,等で調べてください)のが原因の一つかもしれないことが判明.

【2017/10/15追記】Rigidbodyがついているオブジェクト を追跡する際に発生する問題っぽい?

対策1:Update()から移動させる

処理をFixedUpdate()がLateUpdate()に移植する。

どちらが良いかは不明。 RigidbodyをもつObjectを追跡するときはFixedUpdate()がよいのか?

やってみて治ればバンザイ(∩´∀`)∩

 

対策2:FPSを落とす

ふと,処理速度が速すぎて,追跡しきれてないのでは?と思いFPSを見てみたら300FPSとか普通に出てました.

f:id:kamiwo_koete:20160904104717p:plain

とりあえずFPS落としてみるかと思い↓等を参考にエディタ上やスクリプト上で落としてみました.

Unityゲーム開発所 - UnityでFPSを設定する方法

 

FPS落ちない.上記リンク先によるとビルド後でないと反映されないみたいです.

結局ビルドしてみたらがたつきは治りました. 

前もビルドしたら治った案件があったので,一回ビルドして確かめるのもいいかも.

 

対策3:RigidbodyのInterpolateを見直す

RigidbodyのInterpolateがNoneの場合とそれ以外(Interpolate,Extrapolate)とでがたつきが変わる。Noneにすれば治る場合がある

 

対策4: スクリプトの実行順番を変更する

追跡対象のGameObjectの移動が、カメラ追跡スクリプトの実行順より遅い場合、

・ カメラスクリプトで追跡→GameObjectが移動

となるので、ガタつく?

 

結果:よくわからん

前はFPSを弄ったら治ったし、今やってる案件ではFixedUpdate()に放り込んだら治った。よくわからない。以上。

Particle SystemでBillboardを無効化する(カメラ方向に常に向かないようにする)

問題

f:id:gologius:20171009101058g:plain

デフォルトだとParticleが常にカメラの方向に向く。

煙とかならよいが、壁のエフェクトを出したい、となると困る。実際困っている方がおられた。

[Unity] 頂点カラーを利用して平面メッシュをテクスチャアニメーションさせる - Qiita

解決策

「Render Alignment」を「Local」にしましょう(Unity環境は Version 2017.1.1f1)。 たぶん古いバージョンだと「Billboard Alignment」を弄ればよいと思われます。 f:id:gologius:20171009101331g:plain

f:id:gologius:20171009101428g:plain

Unity 簡単な地面との接触判定

SphereCastやらRaycastやら調べたら色々ありました。

しかし私は新しくLayerを作るのが気に入らなかった。

そこで私は考えた

Rigidbodyがアタッチされているなら、速度のy要素が(ほぼ)0になったとき、でよいのではなかろうか???

bool isGround = Mathf.Abs(rbody.velocity.y) < 0.001f ? true : false;

y要素が

  • 負なら重力による落下
  • 正ならジャンプ中など
  • (ほぼ)0なら地面に着くか、空中で静止している状態か

となる。

これでよくね?

追記(10/08)

ずっと平面なら別にいいんだけど、坂道があったらこの前提は崩壊します。

素直にSphereCastとか使いましょうね

おしまい

Akeytsuで作成したfbxをUnityでimportした場合、一部の部位が消える

Akeytsuで作成したfbxをUnityでimportした場合、一部の部位が消える場合の対処法です。

現象

Akeytsuでモーション作成 f:id:gologius:20170928201752g:plain

Unityでインポートしたモーション f:id:gologius:20170928202230g:plain

手がないですね

原因

前提説明

原因を説明する前に、このモデルの構造をお話しします。 実は、指にボーンは入っておらず、閉じた手(に武器)と開いた手の二種類(×左右の二つ)のモデルがあります。 それをスケールを1や0にすることで、表示非表示を切り替えています。

↓を見ると、閉じた手と重なった手が重なっていることが分かるかと思います。 f:id:gologius:20170928202134p:plain

デフォルトのポーズ

Unityでインポートして、シーンに配置したときにモデルがやっているポーズ。 Akeytsuで出力したfbxだと、最初に作ったAnimationがデフォルトのポーズになるみたいです。

原因説明

恐らくですが、デフォルトのモーション(ポーズ)で、スケールを0にしている部位があると、他のモーションで表示させようとすると見えなくなるみたいです。

↓のように、スケールが0の部位(この例だと閉じた手)があるポーズが、デフォルトのポーズだとダメ f:id:gologius:20170928202704p:plain

結論

Akeytsuで一番初めに作るポーズは、部位を全部Scale=1にしておきましょう。

そもそも、Akeytsuは最初はTポーズのScale=1ですし、Tポーズをとっている方がUnityでのインポート後の後処理が楽です。

Unity一週間ゲームジャム テーマ「フロー」に参加し・・・ようとして完成しなかった話

結果から言うと完成しませんでした。 原因の考察は後程

前回同様に

  • 新しい技術にチャレンジ
    • 今回はUnity2017から導入されたTimeLineを使ってみました+後で説明する波打つ床
  • 前回の反省を活かす
    • スイカ割りという、みんなすぐに思いつく&独創性がない、のでもっとオリジナリティあふれるものにしたい

というのをやっていこうと思いました。

何を作るか決める

フローと聞いて、水が思い浮かびました。凡人の発想ですね。 で、前回のこの作品が、メッシュを生成して頂点移動している話を思い出しました。

やまくずし | ゲーム投稿サイト unityroom - Unityのゲームをアップロードして公開しよう

頂点動かして、波発生させたりしたら面白そうだとおもいました。

とりあえずそれ作るか、ということで作った

ここで何を作るかきちんと決めなかったのが悪かった・・・

波打つ床

ソースは後日あげます(ゲームが完成してないのでせめてなにか残したい)

個人的には、見た目が結構面白いと思いました。なのでこれでゲーム作れたらいいなと思いました。

が、これに引きずられてアイデアが全く出てきませんでした。

その他原因と今後

  • 社会人生活ストレス
  • Switchのモンハン(ほとんどやってませんが)

Unityでオブジェクトを割る

Unityでこんな感じで画像を割ります。

f:id:gologius:20170819124203g:plain

ちなみに予め破片モデルを用意する方法です。なので、毎回割れ方は同じです。 有料Assetならもっといいのがあるのですが。

ソース

さっさとデータ欲しい、見たい人はこちら github.com

説明

先に述べたように、予めモデルを作っておいて破壊時に散らかす方法です。 DebrisにRididbodyとColoderを設定した上で非表示(SetActive(false))にしておいて、スペースキーを押すと Coliderのおかげで勝手に弾けて散らかる、という感じです。

GameObjectのDebrisの子要素に、破片用オブジェクトがないと、動かないので注意してください。

モデルはMetasequoiaで作成しました。

f:id:gologius:20170819124901p:plain

using UnityEngine;
using System.Collections;
using System.IO;


/// <summary>
/// 条件
/// * このGameObject以下に破片用の子GameObject(以下破片オブジェクト)がある
/// * 破片オブジェクトにRigidbodyとColiderが設定されている
/// </summary>
public class ImagePanel : MonoBehaviour {

    [Tooltip("表示させる画像")]
    public Texture texure = null;

    [Tooltip("破壊前に見える板")]
    public GameObject panel;

    [Tooltip("破壊後の破片を纏めているオブジェクト")]
    public GameObject debris;

    private bool isFinish = false; //debug

    void Start()
    {
        //エラー処理
        if (texure == null)
        {
            Debug.LogError("Texture is null");
            isFinish = true;
            return;
        }

        debris.SetActive(false); //飛び散らないように非アクティブにしておく

        //Texture設定
        panel.GetComponent<Renderer>().material.mainTexture = texure;
        foreach (Transform child in debris.transform)
        {
            child.gameObject.GetComponent<Renderer>().material.mainTexture = texure; //破片すべてにTexture設定
        } 
    }

    void Update () {
        //debug スペースキーを押すと爆散する
        if (Input.GetKeyDown(KeyCode.Space) && !isFinish)
        {
            crash();
            isFinish = true;
        }
    }


    public void crash()
    {
        debris.SetActive(true); //破片を表示
        debris.transform.parent = null; //Destroy(this.gameObject)に巻き込まれないように
        Destroy(debris, 10.0f);


        Destroy(this.gameObject);
    }
 }

最初は破壊前の板、このサンプルではPanelは使用していませんでした。 ただ、

  • ヒビが見える(透明なマテリアルを適用したときには特に)
  • 処理速度が遅い(Coliderの衝突判定が常に走るから)

の理由で、破壊前の板を用意しています。