レバーを使って機械をオンオフしてみます。
まずレバーを作ってHingeジョイントを付けます。レバーの根本で、レバーの回転に垂直な方向に軸を設定しました。レバーが元の位置に戻るようにSpringを使います。また、Limitsでレバーの動かせる範囲に制限を付けます。
レバーはスプリングでTarget Positionの位置に戻りますが、重力も加わります。
レバーにスクリプトを付けます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
[RequireComponent(typeof(HingeJoint))]
public class LeverScript : MonoBehaviour
{
HingeJoint hj;
bool locked = false;
JointLimits defLimits;
JointSpring defSpring;
public bool useMax = true;
public bool useMin = true;
public bool useLock = false;
[SerializeField] UnityEvent minEvent = new UnityEvent();
[SerializeField] UnityEvent maxEvent = new UnityEvent();
// Start is called before the first frame update
void Start()
{
hj = GetComponent();
defLimits = hj.limits;
defSpring = hj.spring;
}
// Update is called once per frame
void Update()
{
if (!locked && hj.velocity > 0f)
{
// レバーを限界付近まで押す
if (useMin && hj.angle <= defLimits.min + 1)
{
// レバーをロックする時
if (useLock)
{
locked = true;
JointLimits jl = hj.limits;
jl.max = defLimits.min + 8;
hj.limits = jl;
minEvent.Invoke();
}
// ロックしないとき
else
{
JointSpring js = hj.spring;
js.targetPosition = defLimits.min + 5;
hj.spring = js;
minEvent.Invoke();
}
}
// レバーを限界付近まで引く
else if (useMax && hj.angle >= defLimits.max - 1)
{
// レバーをロックするとき
if (useLock)
{
locked = true;
JointLimits jl = hj.limits;
jl.min = defLimits.max - 8;
hj.limits = jl;
maxEvent.Invoke();
}
// ロックしないとき
else
{
JointSpring js = hj.spring;
js.targetPosition = defLimits.max + 5;
hj.spring = js;
maxEvent.Invoke();
}
}
}
if (Input.GetKeyDown(KeyCode.U))
{
UnLockLever();
}
}
// ロックを解除する
public void UnLockLever()
{
locked = false;
hj.limits = defLimits;
hj.spring = defSpring;
}
}
今回はレバーをロックするときとしない時を切り替えられるようにしました。ロックする時はヒンジジョイントのLimitsの片方を近づけて、ロックしない時は、SpringのTarget Positionをレバーを動かした方の限界付近に移動して、レバーがそこにとどまるようにします。
レバーでオンオフする歯車にもヒンジジョイントが付いていて、Motorで動くようになっています。
歯車につけたスクリプトでHingeJoint.useMotorをtrueにすると動き出します。Rigidbodyの抵抗の値が小さいと、falseにしてから動きが止まるまでに時間がかかるようです。
歯車のスクリプトのメソッドをレバーから実行するときは、UnityEventを使うと便利です。
UnityEvent.Invoke()を実行すると、インスペクタで登録したすべてのメソッドが実行されます。引数も設定できます。
// レバー
[SerializeField] UnityEvent minEvent = new UnityEvent();
minEvent.Invoke();
//---
// 歯車
public void UseMotor(bool b)
{
hj.useMotor = b;
}
レバーをロックしない場合は、レバーを限界付近まで上げ下げすると、Springによってそこでレバーが止まります。