rb.velocity.magnitude
をカートのm_Speed
に代入しているとのことですが、rb.velocity.magnitude
は速度の大きさであって常に0以上の値になるでしょうから、rb
に逆方向の力を加え続けて運動の向きがバック側に振れてもm_Speed
はプラスの値になり、カートが前進してしまう...ということはありそうに思います。
もっとRigidbody
とCinemachineDollyCart
の連携の仕方を工夫してやる必要がありそうですね。ですが、bboydaisukeさんからも何をしようとしているのかわからないとのご指摘がありましたが、私としてもどういう理由からRigidbody
とCinemachineDollyCart
を複合させるという手をとろうとなさっているのか、ご質問文からはいまいち読み取れませんでした。
もしトラックの途中に障害物があって、それに当たるとリアリティのある吹っ飛び方で脱線させたいといった事情があれば、もしかするとRigidbody
が必要になってくるのかもしれません。ですが単純にトラック上で加速・減速するだけならばCinemachineDollyCart
単独でもいいんじゃないでしょうかね?
たとえば別途下記のようなスクリプトを用意して...
C#
using Cinemachine;
using UnityEngine;
public static class CinemachineDollyCartExtensions
{
public static void AddForce(
this CinemachineDollyCart dollyCart,
float forceAlongTrack,
ForceMode forceMode = ForceMode.Force,
float mass = 1.0f,
bool allowNegativeSpeed = true)
{
var deltaSpeed = forceAlongTrack;
// forceModeに応じて速度変化量を調整し...
if (forceMode is ForceMode.Force or ForceMode.Acceleration)
{
deltaSpeed *= Time.deltaTime;
}
if (forceMode is ForceMode.Force or ForceMode.Impulse)
{
deltaSpeed /= mass;
}
// 新しい速度を求め...
var speed = dollyCart.m_Speed + deltaSpeed;
// 負の速度を許さないなら(つまりバックを禁止するなら)
// 0未満を0とし...
if (!allowNegativeSpeed)
{
speed = Mathf.Max(speed, 0.0f);
}
// 新しい速度をdollyCartにセットする
dollyCart.m_Speed = speed;
}
}
Player
は下記のようにしたところ...
C#
using Cinemachine;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class Player : MonoBehaviour
{
[SerializeField] private CinemachineDollyCart dollyCart;
private float force;
private new Rigidbody rigidbody;
private void Awake()
{
// インスペクター上でdollyCartをセットしなかった場合、
// 親子階層の中からCinemachineDollyCartを探すことにしました
if (this.dollyCart == null)
{
this.dollyCart = this.GetComponentInParent<CinemachineDollyCart>();
if (this.dollyCart == null)
{
this.dollyCart = this.GetComponentInChildren<CinemachineDollyCart>();
if (this.dollyCart == null)
{
Debug.LogError($"{nameof(CinemachineDollyCart)} not found.");
this.enabled = false;
return;
}
}
}
this.rigidbody = this.GetComponent<Rigidbody>();
this.rigidbody.isKinematic = true;
}
private void FixedUpdate()
{
this.force = 0.0f;
if (Input.GetKey(KeyCode.W))
{
this.force += 1;
}
if (Input.GetKey(KeyCode.S))
{
this.force -= 1;
}
// オブジェクトの質量を得るためにrigidbodyを使用していますが、
// 動きはdollyCartによってコントロールされており、rigidbodyは関与していません
// もし質量が決め打ちでかまわなければ、あるいはForceModeが質量の影響を
// 受けないタイプでもかまわなければ、この質量の取得すら省くことができますので
// 完全にdollyCartだけで動かすことができるでしょう
this.dollyCart.AddForce(this.force, ForceMode.Force, this.rigidbody.mass); // 力をon!
// ちなみに「sキーを押して減速、その後停止するようにしたい。」と
// おっしゃっているということは、sキーでだんだん減速していった後
// さらにsキーを押し続けてバックし始めてしまうとまずいということでしょうか?
// その場合は、下記のように第4引数をfalseにするとバックしなくなるはずです
// this.dollyCart.AddForce(this.force, ForceMode.Force, this.rigidbody.mass, false);
}
private void OnGUI()
{
// 確認のため、現在カートにトラックに沿って加えられている力と
// カートのトラックに沿った速度を表示させてみました
GUI.color = Color.black;
GUILayout.Label($"Force: {this.force}");
GUILayout.Label($"Speed: {this.dollyCart.m_Speed}");
}
}
下図のようにレール上を加速・減速しました。

これだと意図と違うといった点がありましたらコメントください。私の分かる範囲でしたらなるべく案を考えてみようと思います。