Help us understand the problem. What is going on with this article?

【Unity(C#)】魚をゆらゆらと自由に泳がせてみた

More than 1 year has passed since last update.

良いAssetを教えてもらいました。
イワシくん

泳ぎのアニメーションが最初からついているので

イワシのRigidbody.velocity = this.gameObject.transform.forward;

これで前に進めてあげるだけで泳いでいる感じが出ます。

ランダムに方向転換

今回はAddTorqueで向きを変えたいと思います。

Unity道場を参考にしました。
Youtube

動画にもありますが、
AddTorque(回転力)は重ねても破綻することはないとのこと。

もちろん求めている動きにするには調整して回転力を重ねる必要がありますが

"X軸に回転力が加っている最中にZ軸の回転力を重ねて加える"
"X軸のプラス方向の回転力をX軸のマイナス方向の回転力で打ち消す"

みたいなことも可能と解釈しました。(間違っていたらご指摘ください)

デモ

実際にTorqueを合成したデモがこちらです。
赤い線はイワシくんの軌跡です。
Fish_T_Add.gif

一度目の方向転換時には
左向きにAddTorque、下向きにAddTorqueを同時に行っています。

Script

練習がてらUniRxを使って実装しました。
使い方を覚えたかっただけで特に意味はありません。

using UniRx;
using UnityEngine;
using System;

public class MoveIwashi : MonoBehaviour
{
    [SerializeField]
    float speed = 0.3f;

    [SerializeField]
    float rotationSpeed = 0.01f;

    [SerializeField]
    float rotation_Interval = 3;

    Rigidbody iwasirigid;

    void Start()
    {
        iwasirigid = GetComponent<Rigidbody>();

        Observable.Timer(TimeSpan.FromSeconds(rotation_Interval))
            .Repeat()
            .Subscribe(_ =>
            {
                int count = UnityEngine.Random.Range(0, 6);
                print(count);
                if (count == 0)
                {
                    //左向き、下向きにトルクをかける
                    iwasirigid.AddTorque(Vector3.down * rotationSpeed, ForceMode.Impulse);
                    iwasirigid.AddTorque(Vector3.right * rotationSpeed, ForceMode.Impulse);
                }
                else if (count == 1)
                {
                    //右向き、下向きにトルクをかける
                    iwasirigid.AddTorque(Vector3.up * rotationSpeed, ForceMode.Impulse);
                    iwasirigid.AddTorque(Vector3.right * rotationSpeed, ForceMode.Impulse);

                }
                else if (count == 2)
                {
                    //左向き、上向きにトルクをかける
                    iwasirigid.AddTorque(Vector3.down * rotationSpeed, ForceMode.Impulse);
                    iwasirigid.AddTorque(Vector3.left * rotationSpeed, ForceMode.Impulse);
                }
                else if(count == 3)
                {
                    //右向き、上向きにトルクをかける
                    iwasirigid.AddTorque(Vector3.up * rotationSpeed, ForceMode.Impulse);
                    iwasirigid.AddTorque(Vector3.right * rotationSpeed, ForceMode.Impulse);
                }
                else if(count == 4)
                {
                    //右向きにトルクをかける
                    iwasirigid.AddTorque(Vector3.up * rotationSpeed, ForceMode.Impulse);
                }
                else if(count == 5)
                {
                    //左向きにトルクをかける
                    iwasirigid.AddTorque(Vector3.down * rotationSpeed, ForceMode.Impulse);
                }
            })
            .AddTo(this);

    }


    void Update()
    {
        //前に進む
        iwasirigid.velocity = this.gameObject.transform.forward * speed;

        //外積で元に戻す X軸方向
        Vector3 left = this.gameObject.transform.TransformVector(Vector3.left);
        Vector3 hori_left = new Vector3(left.x, 0, left.z).normalized;
        iwasirigid.AddTorque(Vector3.Cross(left, hori_left) * 4, ForceMode.Force);

        //外積で元に戻す Z軸方向
        Vector3 forward = this.gameObject.transform.TransformVector(Vector3.forward);
        Vector3 hori_forward = new Vector3(forward.x, 0, forward.z).normalized;
        iwasirigid.AddTorque(Vector3.Cross(forward, hori_forward) * 4, ForceMode.Force);

    }
}

外積で水平に戻す

今回はUnity道場の動画にも紹介があった外積を利用しています。
回転を加えた際に魚がひっくり返ったりしないように
水平を保つ回転力を外積から算出して加えています。

水平を保ちたいだけであれば外積を使わなくてもRigidbodyの設定から可能です。
FreezeRotationで固定したい軸にチェックを入れればOKです。
IwashiFreezeRotation.png

今回は角度を変えながら自由に動き回った後で水平に戻る仕様にしたいので
外積を利用しました。

加える回転力を調節すれば、画像右側のようにゆらゆらと動かすこともできます。
Fish_C.gif

AngularDrag

自然と水平に戻るようにAngularDragを調整しておきます。
IwashiRigid.png

AngularDragは文字通り、角度に対する抵抗力です。
ここがもし0であれば、角度に対して加えた力は永遠に消滅せずに回転を続けます。

最後に

終わってから調べて気付きましたが、そもそもイワシはゆらゆらのんびりと泳がないっぽいです。
イワシがどう泳ぐかなんて心底どうでもいいのでこのまま公開することにしました。

今回使ったAddTorqueや外積などを組み合わせると、
ゆらゆらした動きや方向転換が簡単に再現できるのでぜひお試しください。

あとUnity道場は私くらいの初心者レベルだと本当にためになることばかりなので
初学者の方は軽い気持ちで覗いてみることをお勧めします。

OKsaiyowa
備忘録として学んだことを記録します。 あやふやな箇所が多いですが、そんなときはビシッと指摘いただけますと幸いです。
https://www.wantedly.com/users/98233916
unity-game-dev-guild
趣味・仕事問わずUnityでゲームを作っている開発者のみで構成されるオンラインコミュニティです。Unityでゲームを開発・運用するにあたって必要なあらゆる知見を共有することを目的とします。
https://unity-game-dev-guild.github.io/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした