using System; using System.Collections.Generic; using UnityEngine; public class DynamicMuneYureBone : MonoBehaviour, IDynamicBone { public void Init(DynamicMuneBone mune_bone) { this.m_Exclusions = new List(); this.m_Root = base.transform; this.MuneBone = mune_bone; Transform transform = null; for (int i = 0; i < base.transform.childCount; i++) { Transform child = base.transform.GetChild(i); if (!child.name.Contains("Mune_") || !child.name.Contains("_yure_")) { this.m_Exclusions.Add(child); } else { for (int j = 0; j < child.childCount; j++) { this.m_Exclusions.Add(child.GetChild(j)); } float value = Mathf.Cos((float)(this.BoneYureDataDic.Count * 45) * 0.017453292f); if (this.BoneYureDataDic.Count == 0) { transform = child; } this.BoneYureDataDic[child] = new DynamicMuneYureBone.YureBoneData(); this.BoneYureDataDic[child].baseWeight = Mathf.InverseLerp(-1f, 1f, value); this.BoneYureDataDic[child].muneSizeWeight = this.MuneBone.muneSizeNormalized; } } this.CurCenterPos = this.m_Root.position + this.m_Root.rotation * Vector3.left * Vector3.Dot(transform.position - this.m_Root.position, this.m_Root.rotation * Vector3.left); this.LocalCenterPos = this.m_Root.InverseTransformPoint(this.CurCenterPos); this.NotDynamicCenter = (this.LastCenterPos = this.CurCenterPos); this.LastMuneBonePos = this.MuneBone.transform.position; this.SetupParticles(); base.enabled = false; } public void UnInit() { } private void SetupParticles() { this.m_Particles.Clear(); if (this.m_Root == null) { return; } this.m_LocalGravity = this.m_Root.InverseTransformDirection(this.m_Gravity); this.m_ObjectScale = Mathf.Abs(base.transform.lossyScale.x); this.m_ObjectPrevPosition = base.transform.position; this.m_ObjectMove = Vector3.zero; this.m_BoneTotalLength = 0f; this.AppendParticles(this.m_Root, -1, 0f); this.UpdateParameters(); } private void AppendParticles(Transform b, int parentIndex, float boneLength) { DynamicMuneYureBone.Particle particle = new DynamicMuneYureBone.Particle(); particle.m_Transform = b; particle.m_ParentIndex = parentIndex; if (b != null) { particle.m_Position = (particle.m_PrevPosition = b.position); particle.m_InitLocalPosition = b.localPosition; particle.m_InitLocalRotation = b.localRotation; } else { Transform transform = this.m_Particles[parentIndex].m_Transform; if (this.m_EndLength > 0f) { Transform parent = transform.parent; if (parent != null) { particle.m_EndOffset = transform.InverseTransformPoint(transform.position * 2f - parent.position) * this.m_EndLength; } else { particle.m_EndOffset = new Vector3(this.m_EndLength, 0f, 0f); } } else { particle.m_EndOffset = transform.InverseTransformPoint(base.transform.TransformDirection(this.m_EndOffset) + transform.position); } particle.m_Position = (particle.m_PrevPosition = transform.TransformPoint(particle.m_EndOffset)); } if (parentIndex >= 0) { boneLength += (this.m_Particles[parentIndex].m_Transform.position - particle.m_Position).magnitude; particle.m_BoneLength = boneLength; this.m_BoneTotalLength = Mathf.Max(this.m_BoneTotalLength, boneLength); } int count = this.m_Particles.Count; this.m_Particles.Add(particle); if (particle.m_Transform && this.BoneYureDataDic.ContainsKey(particle.m_Transform)) { this.BoneYureDataDic[particle.m_Transform].particle = particle; } if (b != null) { for (int i = 0; i < b.childCount; i++) { bool flag = false; if (this.m_Exclusions != null) { for (int j = 0; j < this.m_Exclusions.Count; j++) { Transform x = this.m_Exclusions[j]; if (x == b.GetChild(i)) { flag = true; break; } } } if (!flag) { this.AppendParticles(b.GetChild(i), count, boneLength); } else if (this.m_EndLength > 0f || this.m_EndOffset != Vector3.zero) { this.AppendParticles(null, count, boneLength); } } if (b.childCount == 0 && (this.m_EndLength > 0f || this.m_EndOffset != Vector3.zero)) { this.AppendParticles(null, count, boneLength); } } } public void UpdateParameters() { if (this.m_Root == null) { return; } this.m_LocalGravity = this.m_Root.InverseTransformDirection(this.m_Gravity); for (int i = 0; i < this.m_Particles.Count; i++) { DynamicMuneYureBone.Particle particle = this.m_Particles[i]; particle.m_Damping = ((!this.BoneYureDataDic.ContainsKey(particle.m_Transform)) ? this.m_Damping : this.BoneYureDataDic[particle.m_Transform].damping); particle.m_Elasticity = this.m_Elasticity; particle.m_Stiffness = ((!this.BoneYureDataDic.ContainsKey(particle.m_Transform)) ? this.m_Stiffness : this.BoneYureDataDic[particle.m_Transform].stiffness); particle.m_Inert = ((!this.BoneYureDataDic.ContainsKey(particle.m_Transform)) ? this.m_Inert : this.BoneYureDataDic[particle.m_Transform].inert); particle.m_Radius = this.m_Radius; if (this.m_BoneTotalLength > 0f) { float time = particle.m_BoneLength / this.m_BoneTotalLength; if (this.m_DampingDistrib != null && this.m_DampingDistrib.keys.Length > 0) { particle.m_Damping *= this.m_DampingDistrib.Evaluate(time); } if (this.m_ElasticityDistrib != null && this.m_ElasticityDistrib.keys.Length > 0) { particle.m_Elasticity *= this.m_ElasticityDistrib.Evaluate(time); } if (this.m_StiffnessDistrib != null && this.m_StiffnessDistrib.keys.Length > 0) { particle.m_Stiffness *= this.m_StiffnessDistrib.Evaluate(time); } if (this.m_InertDistrib != null && this.m_InertDistrib.keys.Length > 0) { particle.m_Inert *= this.m_InertDistrib.Evaluate(time); } if (this.m_RadiusDistrib != null && this.m_RadiusDistrib.keys.Length > 0) { particle.m_Radius *= this.m_RadiusDistrib.Evaluate(time); } } particle.m_Damping = Mathf.Clamp01(particle.m_Damping); particle.m_Elasticity = Mathf.Clamp01(particle.m_Elasticity); particle.m_Stiffness = Mathf.Clamp01(particle.m_Stiffness); particle.m_Inert = Mathf.Clamp01(particle.m_Inert); particle.m_Radius = Mathf.Max(particle.m_Radius, 0f); } } public void PhysicsReset() { this.ResetParticlesPosition(); } private void ResetParticlesPosition() { for (int i = 0; i < this.m_Particles.Count; i++) { DynamicMuneYureBone.Particle particle = this.m_Particles[i]; if (particle.m_Transform != null) { particle.m_Position = (particle.m_PrevPosition = particle.m_Transform.position); } else { Transform transform = this.m_Particles[particle.m_ParentIndex].m_Transform; particle.m_Position = (particle.m_PrevPosition = transform.TransformPoint(particle.m_EndOffset)); } } this.m_ObjectPrevPosition = base.transform.position; } public void PreUpdate() { if (this.m_Weight > 0f && (!this.m_DistantDisable || !this.m_DistantDisabled)) { this.InitTransforms(); } } private void InitTransforms() { for (int i = 0; i < this.m_Particles.Count; i++) { DynamicMuneYureBone.Particle particle = this.m_Particles[i]; if (particle.m_Transform != null) { particle.m_Transform.localPosition = particle.m_InitLocalPosition; particle.m_Transform.localRotation = particle.m_InitLocalRotation; } } if (this.m_Root) { this.NotDynamicCenter = this.GetCenterPos(); } } public void CalcMuneEditMove() { Vector3 centerPos = this.GetCenterPos(); this.MuneEditMove = this.m_Root.InverseTransformVector(this.NotDynamicCenter - centerPos); } public void DynamicUpdate() { this.CurCenterPos = this.GetCenterPos(); if (this.isDynamicOn) { if (!this.MuneBone.isDynamicReset) { this.m_Force = this.LastCenterPos - this.CurCenterPos; this.m_Force -= this.LastMuneBonePos - this.MuneBone.transform.position; } else { this.m_Force = Vector3.zero; } foreach (DynamicMuneYureBone.YureBoneData yureBoneData in this.BoneYureDataDic.Values) { yureBoneData.muneSizeWeight = this.MuneBone.muneSizeNormalized; } if (this.m_DistantDisable) { this.CheckDistance(); } if (this.m_Weight > 0f && (!this.m_DistantDisable || !this.m_DistantDisabled)) { float t = (this.m_UpdateMode != DynamicMuneYureBone.UpdateMode.UnscaledTime) ? Time.deltaTime : Time.unscaledDeltaTime; this.UpdateDynamicBones(t); } } this.LastMuneBonePos = this.MuneBone.transform.position; this.LastCenterPos = this.CurCenterPos; } private void CheckDistance() { Transform transform = this.m_ReferenceObject; if (transform == null && Camera.main != null) { transform = Camera.main.transform; } if (transform != null) { float sqrMagnitude = (transform.position - base.transform.position).sqrMagnitude; bool flag = sqrMagnitude > this.m_DistanceToObject * this.m_DistanceToObject; if (flag != this.m_DistantDisabled) { if (!flag) { this.ResetParticlesPosition(); } this.m_DistantDisabled = flag; } } } private void UpdateDynamicBones(float t) { if (this.m_Root == null) { return; } this.m_ObjectScale = Mathf.Abs(base.transform.lossyScale.x); this.m_ObjectMove = base.transform.position - this.m_ObjectPrevPosition; this.m_ObjectPrevPosition = base.transform.position; int num = 1; if (this.m_UpdateRate > 0f) { float num2 = 1f / this.m_UpdateRate; this.m_Time += t; num = 0; while (this.m_Time >= num2) { this.m_Time -= num2; if (++num >= 3) { this.m_Time = 0f; break; } } } if (num > 0) { for (int i = 0; i < num; i++) { this.UpdateParticles1(); this.UpdateParticles2(); this.m_ObjectMove = Vector3.zero; } } else { this.SkipUpdateParticles(); } this.ApplyParticlesToTransforms(); } private void UpdateParticles1() { Vector3 a = this.m_Gravity; Vector3 normalized = this.m_Gravity.normalized; Vector3 lhs = this.m_Root.TransformDirection(this.m_LocalGravity); Vector3 b = normalized * Mathf.Max(Vector3.Dot(lhs, normalized), 0f); a -= b; Transform parent = this.m_Root.parent; Vector3 normalized2 = this.m_Force.normalized; Vector3 b2 = this.m_Root.TransformVector(this.MuneEditMove); for (int i = 0; i < this.m_Particles.Count; i++) { DynamicMuneYureBone.Particle particle = this.m_Particles[i]; if (particle.m_ParentIndex >= 0) { Vector3 a2 = particle.m_Position - particle.m_PrevPosition; Vector3 b3 = this.m_ObjectMove * particle.m_Inert; particle.m_PrevPosition = particle.m_Position + b3; float d = (!this.BoneYureDataDic.ContainsKey(particle.m_Transform)) ? 1f : this.BoneYureDataDic[particle.m_Transform].baseWeight; Vector3 vector = (a + this.m_Force * d) * this.m_ObjectScale; if (this.BoneYureDataDic.ContainsKey(particle.m_Transform)) { float f = Vector3.Dot(normalized2, (particle.m_Transform.position - this.CurCenterPos).normalized); f = Mathf.Abs(f); float num = Mathf.Acos(f) * 57.29578f; if (float.IsNaN(num)) { num = 0f; } vector *= Mathf.Clamp01(num / this.RimmitAngle); vector -= b2; } particle.m_Position += a2 * (1f - particle.m_Damping) + vector + b3; } else { particle.m_PrevPosition = particle.m_Position; particle.m_Position = particle.m_Transform.position; } } } private void UpdateParticles2() { Plane plane = default(Plane); for (int i = 1; i < this.m_Particles.Count; i++) { DynamicMuneYureBone.Particle particle = this.m_Particles[i]; DynamicMuneYureBone.Particle particle2 = this.m_Particles[particle.m_ParentIndex]; float magnitude; if (particle.m_Transform != null) { magnitude = (particle2.m_Transform.position - particle.m_Transform.position).magnitude; } else { magnitude = particle2.m_Transform.localToWorldMatrix.MultiplyVector(particle.m_EndOffset).magnitude; } float num = Mathf.Lerp(1f, particle.m_Stiffness, this.m_Weight); if (num > 0f || particle.m_Elasticity > 0f) { Matrix4x4 localToWorldMatrix = particle2.m_Transform.localToWorldMatrix; localToWorldMatrix.SetColumn(3, particle2.m_Position); Vector3 a; if (particle.m_Transform != null) { a = localToWorldMatrix.MultiplyPoint3x4(particle.m_Transform.localPosition); } else { a = localToWorldMatrix.MultiplyPoint3x4(particle.m_EndOffset); } Vector3 a2 = a - particle.m_Position; particle.m_Position += a2 * particle.m_Elasticity; if (num > 0f) { a2 = a - particle.m_Position; float magnitude2 = a2.magnitude; float num2 = magnitude * (1f - num) * 2f; if (magnitude2 > num2) { particle.m_Position += a2 * ((magnitude2 - num2) / magnitude2); } } } if (this.m_Colliders != null) { float particleRadius = particle.m_Radius * this.m_ObjectScale; for (int j = 0; j < this.m_Colliders.Count; j++) { DynamicBoneColliderBase dynamicBoneColliderBase = this.m_Colliders[j]; if (dynamicBoneColliderBase != null && dynamicBoneColliderBase.enabled) { dynamicBoneColliderBase.Collide(ref particle.m_Position, particleRadius); } } } if (this.m_FreezeAxis != DynamicMuneYureBone.FreezeAxis.None) { DynamicMuneYureBone.FreezeAxis freezeAxis = this.m_FreezeAxis; if (freezeAxis != DynamicMuneYureBone.FreezeAxis.X) { if (freezeAxis != DynamicMuneYureBone.FreezeAxis.Y) { if (freezeAxis == DynamicMuneYureBone.FreezeAxis.Z) { plane.SetNormalAndPosition(particle2.m_Transform.forward, particle2.m_Position); } } else { plane.SetNormalAndPosition(particle2.m_Transform.up, particle2.m_Position); } } else { plane.SetNormalAndPosition(particle2.m_Transform.right, particle2.m_Position); } particle.m_Position -= plane.normal * plane.GetDistanceToPoint(particle.m_Position); } if (this.BoneYureDataDic.ContainsKey(particle.m_Transform)) { Vector3 vector = base.transform.rotation * Vector3.left; Vector3 b = vector * Vector3.Dot(particle.m_Position - this.CurCenterPos, vector); particle.m_Position -= b; float magnitude3 = (particle.m_Transform.position - this.CurCenterPos).magnitude; float magnitude4 = (particle.m_Position - this.CurCenterPos).magnitude; float num3 = magnitude4 / magnitude3; if (num3 > 1f + this.LengthRimmitRange) { particle.m_Position = this.CurCenterPos + (particle.m_Position - this.CurCenterPos) / num3 * (1f + this.LengthRimmitRange); } else if (num3 < 1f - this.LengthRimmitRange) { particle.m_Position = this.CurCenterPos + (particle.m_Position - this.CurCenterPos) / num3 * (1f - this.LengthRimmitRange); } } } } private void SkipUpdateParticles() { for (int i = 0; i < this.m_Particles.Count; i++) { DynamicMuneYureBone.Particle particle = this.m_Particles[i]; if (particle.m_ParentIndex >= 0) { particle.m_PrevPosition += this.m_ObjectMove; particle.m_Position += this.m_ObjectMove; DynamicMuneYureBone.Particle particle2 = this.m_Particles[particle.m_ParentIndex]; float magnitude; if (particle.m_Transform != null) { magnitude = (particle2.m_Transform.position - particle.m_Transform.position).magnitude; } else { magnitude = particle2.m_Transform.localToWorldMatrix.MultiplyVector(particle.m_EndOffset).magnitude; } float num = Mathf.Lerp(1f, particle.m_Stiffness, this.m_Weight); if (num > 0f) { Matrix4x4 localToWorldMatrix = particle2.m_Transform.localToWorldMatrix; localToWorldMatrix.SetColumn(3, particle2.m_Position); Vector3 a; if (particle.m_Transform != null) { a = localToWorldMatrix.MultiplyPoint3x4(particle.m_Transform.localPosition); } else { a = localToWorldMatrix.MultiplyPoint3x4(particle.m_EndOffset); } Vector3 a2 = a - particle.m_Position; float magnitude2 = a2.magnitude; float num2 = magnitude * (1f - num) * 2f; if (magnitude2 > num2) { particle.m_Position += a2 * ((magnitude2 - num2) / magnitude2); } } Vector3 a3 = particle2.m_Position - particle.m_Position; float magnitude3 = a3.magnitude; if (magnitude3 > 0f) { particle.m_Position += a3 * ((magnitude3 - magnitude) / magnitude3); } } else { particle.m_PrevPosition = particle.m_Position; particle.m_Position = particle.m_Transform.position; } } } private void ApplyParticlesToTransforms() { for (int i = 1; i < this.m_Particles.Count; i++) { DynamicMuneYureBone.Particle particle = this.m_Particles[i]; DynamicMuneYureBone.Particle particle2 = this.m_Particles[particle.m_ParentIndex]; if (particle2.m_Transform.childCount <= 1) { Vector3 direction; if (particle.m_Transform != null) { direction = particle.m_Transform.localPosition; } else { direction = particle.m_EndOffset; } Vector3 toDirection = particle.m_Position - particle2.m_Position; Quaternion lhs = Quaternion.FromToRotation(particle2.m_Transform.TransformDirection(direction), toDirection); particle2.m_Transform.rotation = lhs * particle2.m_Transform.rotation; } if (particle.m_Transform != null) { particle.m_Transform.position = particle.m_Position; } } } private static Vector3 MirrorVector(Vector3 v, Vector3 axis) { return v - axis * (Vector3.Dot(v, axis) * 2f); } public float GetWeight() { return this.m_Weight; } public void SetWeight(float w) { if (this.m_Weight != w) { if (w == 0f) { this.InitTransforms(); } else if (this.m_Weight == 0f) { this.ResetParticlesPosition(); } this.m_Weight = w; } } private Vector3 GetCenterPos() { return this.m_Root.TransformPoint(this.LocalCenterPos); } private const float YURE_PARAM_MIN = 0.1f; private const float YURE_PARAM_MAX = 0.9f; [Header("揺れ有効")] public bool isDynamicOn = true; [Tooltip("The root of the transform hierarchy to apply physics.")] public Transform m_Root; [Tooltip("Internal physics simulation rate.")] public float m_UpdateRate; public DynamicMuneYureBone.UpdateMode m_UpdateMode; [Tooltip("How much the bones slowed down.")] [Range(0f, 1f)] public float m_Damping = 0.1f; public AnimationCurve m_DampingDistrib; [Tooltip("How much the force applied to return each bone to original orientation.")] [Range(0f, 1f)] public float m_Elasticity = 0.1f; public AnimationCurve m_ElasticityDistrib; [Tooltip("How much bone's original orientation are preserved.")] [Range(0f, 1f)] public float m_Stiffness = 0.1f; public AnimationCurve m_StiffnessDistrib; [Tooltip("How much character's position change is ignored in physics simulation.")] [Range(0f, 1f)] public float m_Inert; public AnimationCurve m_InertDistrib; [Tooltip("Each bone can be a sphere to collide with colliders. Radius describe sphere's size.")] public float m_Radius; public AnimationCurve m_RadiusDistrib; [Tooltip("If End Length is not zero, an extra bone is generated at the end of transform hierarchy.")] public float m_EndLength; [Tooltip("If End Offset is not zero, an extra bone is generated at the end of transform hierarchy.")] public Vector3 m_EndOffset = Vector3.zero; [Tooltip("The force apply to bones. Partial force apply to character's initial pose is cancelled out.")] public Vector3 m_Gravity = Vector3.zero; [Tooltip("The force apply to bones.")] public Vector3 m_Force = Vector3.zero; [Tooltip("Collider objects interact with the bones.")] public List m_Colliders; [Tooltip("Bones exclude from physics simulation.")] public List m_Exclusions; [Tooltip("Constrain bones to move on specified plane.")] public DynamicMuneYureBone.FreezeAxis m_FreezeAxis; [Tooltip("Disable physics simulation automatically if character is far from camera or player.")] public bool m_DistantDisable; public Transform m_ReferenceObject; public float m_DistanceToObject = 20f; private Vector3 m_LocalGravity = Vector3.zero; private Vector3 m_ObjectMove = Vector3.zero; private Vector3 m_ObjectPrevPosition = Vector3.zero; private float m_BoneTotalLength; private float m_ObjectScale = 1f; private float m_Time; private float m_Weight = 1f; private bool m_DistantDisabled; private List m_Particles = new List(); private Vector3 LocalCenterPos; private Vector3 CurCenterPos; private Vector3 LastCenterPos; private Dictionary BoneYureDataDic = new Dictionary(); [SerializeField] [Range(1f, 90f)] private float RimmitAngle = 90f; private DynamicMuneBone MuneBone; private Vector3 LastMuneBonePos; private Vector3 NotDynamicCenter; [SerializeField] private Vector3 MuneEditMove; [SerializeField] [Range(0f, 1f)] private float LengthRimmitRange = 0.15f; public enum UpdateMode { Normal, AnimatePhysics, UnscaledTime } public enum FreezeAxis { None, X, Y, Z } [Serializable] private class Particle { public Transform m_Transform; public int m_ParentIndex = -1; public float m_Damping; public float m_Elasticity; public float m_Stiffness; public float m_Inert; public float m_Radius; public float m_BoneLength; public Vector3 m_Position = Vector3.zero; public Vector3 m_PrevPosition = Vector3.zero; public Vector3 m_EndOffset = Vector3.zero; public Vector3 m_InitLocalPosition = Vector3.zero; public Quaternion m_InitLocalRotation = Quaternion.identity; } private class YureBoneData { public DynamicMuneYureBone.Particle particle { get { return this.Particle; } set { this.Particle = value; this.UpdateParticleParam(); } } public float baseWeight { get { return this.BaseWeight; } set { this.BaseWeight = Mathf.Clamp01(value); this.UpdateParticleParam(); } } public float muneSizeWeight { get { return this.MuneSizeWeight; } set { this.MuneSizeWeight = Mathf.Clamp01(value); this.UpdateParticleParam(); } } public float damping { get { float b = Mathf.Lerp(0.1f, 0.9f, 1f - this.baseWeight); return Mathf.Lerp(1f, b, this.MuneSizeWeight); } } public float stiffness { get { float b = Mathf.Lerp(0.1f, 0.9f, 1f - this.baseWeight); return Mathf.Lerp(1f, b, this.MuneSizeWeight); } } public float inert { get { float b = Mathf.Lerp(0.1f, 0.9f, 1f - this.baseWeight); return Mathf.Lerp(1f, b, this.MuneSizeWeight); } } private void UpdateParticleParam() { if (this.particle != null) { this.particle.m_Stiffness = this.stiffness; this.particle.m_Damping = this.damping; this.particle.m_Inert = this.inert; } } private DynamicMuneYureBone.Particle Particle; private float BaseWeight; private float MuneSizeWeight; } }