ゲートの移動範囲がずれないように修正しました。
前の記事ではハンドルの回転だけを制限していましたが、ジョイントやコライダーの衝突を使ってゲートの動きを制限して、ゲートが制限まで達したときにハンドルを固定するようにします。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ValveScript2 : MonoBehaviour
{
[SerializeField] Text text01;
HingeJoint hj;
JointLimits jl;
Vector3 mPos;
Vector3 screenSizeHalf;
float previousRad;
float valveSpeed = 1f;
Rigidbody rb;
float tan;
bool awake = false;
public bool locked = false;
[SerializeField] GateScript sc_gate;
// Start is called before the first frame update
void Start()
{
rb = GetComponent();
rb.maxAngularVelocity = Mathf.Infinity;
hj = GetComponent();
// ゲートにこのスクリプトを設定
sc_gate.SetHandle(GetComponent());
}
public void Activate(bool b)
{
if (b)
{
screenSizeHalf.x = Screen.width / 2f;
screenSizeHalf.y = Screen.height / 2f;
screenSizeHalf.z = 0f;
mPos = Input.mousePosition - screenSizeHalf;
previousRad = Mathf.Atan2(mPos.x, mPos.y);
awake = true;
}
else
awake = false;
}
// Update is called once per frame
void Update()
{
if (awake)
{
mPos = Input.mousePosition - screenSizeHalf;
float rad = Mathf.Atan2(mPos.x, mPos.y); // 上向きとマウス位置のなす角
float dRad = rad - previousRad; // 前のフレームの角度との差
float t = Mathf.Tan(dRad);
// 速度が大きすぎないとき
if (Mathf.Abs(t) * Time.deltaTime <= 0.1f)
{
// ゲートを動かす
sc_gate.MoveGate(t);
// ロック中はハンドルを動かさない
if (!locked) rb.AddTorque(transform.TransformDirection(new Vector3(0f, t, 0f)), ForceMode.Impulse);
else rb.angularVelocity = Vector3.zero;
//tan += t;
}
previousRad = rad; // 今のフレームの角度を保存
text01.text = locked + "";
//text01.text = hj.angle + " " + tan + " " + t + " " + dRad;
}
}
}
マウスをドラッグするとゲートは常に動かしますが、ハンドルがロックされていればハンドルはうごかしません。ゲートは、床との衝突やジョイントによって移動が制限されています。
Configurable Jointでは、X MotionをLimitedにすると、Axisで設定した方向へ移動制限が付きます。それ以外はLockedにして動かないようにします。
ゲートを動かせる幅はLinear LimitのLimitでメートル単位で設定できます。X,Y,Zのすべての方向の両側に同じ値を使います。
ハンドルのロックはゲートのスクリプトでオンオフします。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GateScript : MonoBehaviour
{
[SerializeField] Text text02;
Rigidbody rb;
ValveScript2 sc_valve;
ConfigurableJoint cj;
float defPos;
bool col = false;
bool lim = false;
// Start is called before the first frame update
void Start()
{
rb = GetComponent();
cj = GetComponent();
defPos = transform.localPosition.y;
}
// Update is called once per frame
void Update()
{
//text02.text = transform.localPosition.y + " " + cj.linearLimit.limit;
// ジョイントの制限付近にあるとき
if (transform.localPosition.y - defPos > cj.linearLimit.limit - 0.001f || transform.localPosition.y - defPos < -cj.linearLimit.limit + 0.001f)
{
lim = true;
}
else { lim = false; }
// ハンドルをロック
if (lim || col)
{
sc_valve.locked = true;
}
else
{
sc_valve.locked = false;
}
}
// ゲートを動かす
public void MoveGate(float t)
{
rb.AddForce(Vector3.up * t / 5f, ForceMode.Impulse);
}
// ハンドルのスクリプトを設定
public void SetHandle(ValveScript2 sc_v)
{
sc_valve = sc_v;
}
// 衝突
private void OnCollisionEnter(Collision collision)
{
col = true;
}
private void OnCollisionExit(Collision collision)
{
col = false;
}
}
ゲートがジョイントの制限付近にあるか衝突しているときにハンドルをロックしています。