// Magica Cloth. // Copyright (c) MagicaSoft, 2020-2022. // https://magicasoft.jp using UnityEngine; namespace MagicaCloth { /// /// 球コライダー /// [HelpURL("https://magicasoft.jp/magica-cloth-sphere-collider/")] [AddComponentMenu("MagicaCloth/MagicaSphereCollider")] public class MagicaSphereCollider : ColliderComponent { [SerializeField] [Range(0.001f, 0.5f)] private float radius = 0.05f; //========================================================================================= public override ComponentType GetComponentType() { return ComponentType.SphereCollider; } private void OnValidate() { if (Application.isPlaying) DataUpdate(); } /// /// パーティクルのデータ更新処理 /// internal override void DataUpdate() { base.DataUpdate(); // radius, localPos foreach (var c in particleDict.Values) { for (int i = 0; i < c.dataLength; i++) { MagicaPhysicsManager.Instance.Particle.SetRadius(c.startIndex + i, radius); MagicaPhysicsManager.Instance.Particle.SetLocalPos(c.startIndex + i, Center); } } } //========================================================================================= public float Radius { get { return radius; } set { radius = value; ReserveDataUpdate(); } } /// /// データハッシュ計算 /// /// public override int GetDataHash() { int hash = base.GetDataHash(); hash += radius.GetDataHash(); return hash; } protected override ChunkData CreateColliderParticleReal(int teamId) { uint flag = 0; flag |= PhysicsManagerParticleData.Flag_Kinematic; flag |= PhysicsManagerParticleData.Flag_Collider; flag |= PhysicsManagerParticleData.Flag_Transform_Read_Base; flag |= PhysicsManagerParticleData.Flag_Step_Update; flag |= PhysicsManagerParticleData.Flag_Reset_Position; flag |= PhysicsManagerParticleData.Flag_Transform_Read_Local; //flag |= PhysicsManagerParticleData.Flag_Transform_Read_Scl; // 現在スケールは見ていない var c = CreateParticle( flag, teamId, // team 0.0f, // depth radius, Center ); if (c.IsValid()) MagicaPhysicsManager.Instance.Team.AddCollider(teamId, c.startIndex); return c; } /// /// スケール値を取得 /// /// public float GetScale() { // X軸のみを見る return transform.lossyScale.x; } /// /// 指定座標に最も近い衝突点pと、中心軸からのpへの方向dirを返す。 /// ※エディタ計算用 /// /// /// /// public override bool CalcNearPoint(Vector3 pos, out Vector3 p, out Vector3 dir, out Vector3 d, bool skinning) { dir = Vector3.zero; float scl = GetScale(); //d = transform.position; d = transform.TransformPoint(Center); var v = pos - d; float vlen = v.magnitude; if (vlen <= Radius * scl) { // 衝突している p = pos; if (vlen > 0.0f) dir = v.normalized; } else { dir = v.normalized; p = d + dir * Radius; } return true; } } }