172 lines
5.9 KiB
C#
172 lines
5.9 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using BITKit.Core.Tuple;
|
|
using UnityEngine;
|
|
|
|
namespace BITKit.Physics
|
|
{
|
|
[Serializable]
|
|
public class JointConfigure
|
|
{
|
|
public Transform animate;
|
|
public ConfigurableJoint joint;
|
|
public Quaternion InitialRotation { get; set; }
|
|
public Rigidbody Rigidbody { get; set; }
|
|
public ConfigurableJointMotion AngularXMotion { get; set; }
|
|
public ConfigurableJointMotion AngularYMotion { get; set; }
|
|
public ConfigurableJointMotion AngularZMotion { get; set; }
|
|
public ConfigurableJointMotion XMotion { get; set; }
|
|
public ConfigurableJointMotion YMotion { get; set; }
|
|
public ConfigurableJointMotion ZMotion { get; set; }
|
|
}
|
|
public class PhysicsBasedAnimation : MonoBehaviour
|
|
{
|
|
[Header(Constant.Header.Settings)]
|
|
[Range(0, 1)] public float Blend;
|
|
|
|
[SerializeField] public bool allowFixedJoints;
|
|
|
|
[Header(Constant.Header.Components)]
|
|
[SerializeField] private JointConfigure[] fixedJointConfigures;
|
|
[SerializeField] private JointConfigure[] jointConfigures;
|
|
|
|
[Header(Constant.Header.Settings)]
|
|
[SerializeField] private float positionSpring;
|
|
[SerializeField] private float positionDamper;
|
|
[SerializeField] private float torqueForce;
|
|
[SerializeField] private float maximumForce;
|
|
|
|
[Header(Constant.Header.Optional)]
|
|
[SerializeField] private Optional<UnityTuple<Rigidbody, Transform>> rootSync;
|
|
[SerializeField] private Optional<ConfigurableJointMotion> overrideMotion;
|
|
[SerializeField] private Optional<ConfigurableJointMotion> overrideAngularMotion;
|
|
|
|
private readonly ValidHandle allowFixedJoint = new();
|
|
private readonly ValidHandle allowPhysicsAnimation = new();
|
|
|
|
private void Start()
|
|
{
|
|
foreach (var x in jointConfigures)
|
|
{
|
|
x.InitialRotation = x.animate.localRotation;
|
|
if (x.animate.localRotation != x.joint.transform.localRotation)
|
|
{
|
|
BIT4Log.Log<PhysicsBasedAnimation>($"{x.animate.name}初始旋转与关节旋转不一致,将会导致动画不正确");
|
|
}
|
|
|
|
x.Rigidbody = x.joint.GetComponent<Rigidbody>();
|
|
x.AngularXMotion = x.joint.angularXMotion;
|
|
x.AngularYMotion = x.joint.angularYMotion;
|
|
x.AngularZMotion = x.joint.angularZMotion;
|
|
x.XMotion = x.joint.xMotion;
|
|
x.YMotion = x.joint.yMotion;
|
|
x.ZMotion = x.joint.zMotion;
|
|
}
|
|
|
|
allowFixedJoint.AddListener(OnAllowFixedJoint);
|
|
allowPhysicsAnimation.AddListener(OnAllowPhysicsAnimation);
|
|
}
|
|
|
|
private void OnAllowPhysicsAnimation(bool allow)
|
|
{
|
|
foreach (var x in jointConfigures)
|
|
{
|
|
x.joint.angularXMotion = !allow ? x.AngularXMotion : ConfigurableJointMotion.Free;
|
|
x.joint.angularYMotion = !allow ? x.AngularYMotion : ConfigurableJointMotion.Free;
|
|
x.joint.angularZMotion = !allow ? x.AngularZMotion : ConfigurableJointMotion.Free;
|
|
x.joint.xMotion = !allow ? x.XMotion : ConfigurableJointMotion.Locked;
|
|
x.joint.yMotion = !allow ? x.YMotion : ConfigurableJointMotion.Locked;
|
|
x.joint.zMotion = !allow ? x.ZMotion : ConfigurableJointMotion.Locked;
|
|
}
|
|
}
|
|
|
|
private void FixedUpdate()
|
|
{
|
|
allowFixedJoint.SetElements(this,allowFixedJoints);
|
|
allowPhysicsAnimation.SetElements(this,Blend is not 0);
|
|
|
|
//var spring = Mathf.Lerp(Blend,0,angularSprint);
|
|
var drive = new JointDrive
|
|
{
|
|
positionDamper = positionDamper,
|
|
positionSpring =Mathf.Lerp(0,positionSpring,Blend),
|
|
maximumForce = maximumForce,
|
|
};
|
|
|
|
var blendTorqueForce = Mathf.Lerp(0,this.torqueForce,Blend);
|
|
foreach (var jointConfigure in jointConfigures)
|
|
{
|
|
jointConfigure.joint.angularXDrive = drive;
|
|
jointConfigure.joint.angularYZDrive = drive;
|
|
jointConfigure.joint.xDrive = drive;
|
|
jointConfigure.joint.yDrive = drive;
|
|
jointConfigure.joint.zDrive = drive;
|
|
|
|
jointConfigure.joint.targetRotation =
|
|
Quaternion.Lerp(
|
|
jointConfigure.joint.transform.localRotation,
|
|
Quaternion.Inverse(jointConfigure.animate.localRotation) *
|
|
jointConfigure.InitialRotation,Blend
|
|
)
|
|
;
|
|
jointConfigure.joint.targetPosition =
|
|
Vector3.Lerp(
|
|
jointConfigure.joint.transform.localPosition,
|
|
jointConfigure.animate.localPosition,
|
|
Blend
|
|
);
|
|
|
|
if (overrideAngularMotion.Allow)
|
|
{
|
|
jointConfigure.joint.angularXMotion = overrideAngularMotion.Value;
|
|
jointConfigure.joint.angularYMotion = overrideAngularMotion.Value;
|
|
jointConfigure.joint.angularZMotion = overrideAngularMotion.Value;
|
|
}
|
|
|
|
if (overrideMotion.Allow)
|
|
{
|
|
jointConfigure.joint.xMotion = overrideMotion.Value;
|
|
jointConfigure.joint.yMotion = overrideMotion.Value;
|
|
jointConfigure.joint.zMotion = overrideMotion.Value;
|
|
}
|
|
|
|
jointConfigure.Rigidbody.AddTorque(
|
|
MathV.CalculateTorque(jointConfigure.joint.transform,jointConfigure.animate.rotation) * blendTorqueForce
|
|
,ForceMode.VelocityChange
|
|
);
|
|
|
|
// jointConfigure.Rigidbody.AddForce(
|
|
// jointConfigure.animate.localPosition - jointConfigure.Rigidbody.position,ForceMode.VelocityChange
|
|
// );
|
|
jointConfigure.Rigidbody.useGravity =Blend is 0;
|
|
|
|
//jointConfigure.Rigidbody.MoveRotation(jointConfigure.animate.rotation);
|
|
}
|
|
|
|
if (rootSync.Allow)
|
|
{
|
|
var root = rootSync.Value;
|
|
root.Item1.transform.localPosition = root.Item2.localPosition;
|
|
root.Item1.MoveRotation(root.Item2.rotation);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
private void OnAllowFixedJoint(bool allow)
|
|
{
|
|
foreach (var x in fixedJointConfigures)
|
|
{
|
|
x.joint.angularXMotion = allow ? ConfigurableJointMotion.Limited : ConfigurableJointMotion.Free;
|
|
x.joint.angularYMotion = allow ? ConfigurableJointMotion.Limited : ConfigurableJointMotion.Free;
|
|
x.joint.angularZMotion = allow ? ConfigurableJointMotion.Limited : ConfigurableJointMotion.Free;
|
|
x.joint.xMotion = allow ? ConfigurableJointMotion.Limited : ConfigurableJointMotion.Free;
|
|
x.joint.yMotion = allow ? ConfigurableJointMotion.Limited : ConfigurableJointMotion.Free;
|
|
x.joint.zMotion = allow ? ConfigurableJointMotion.Limited : ConfigurableJointMotion.Free;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|