/// <summary> /// あたり判定メッシュ上において、パーツを構成する面の大きさをゼロにする。 /// </summary> /// <param name="part">破壊したいパーツ</param> public void breakPartInHitMesh(_StructurePart3 part) { if (part.hitIndexInfo.isEmpty) { return; } if (colliderTriangles == null) { // 初回はメッシュ生成 // 案:パーツコンテンツがホルダーの場合はメッシュ生成なしでいけるんじゃないのか? // あと結構メッシュ生成が重い気がするので、あらかじめ全部作ってしまうのはダメだろうか… var oldmesh = collider.sharedMesh; // これはちゃんと同じメッシュを受け取ってるっぽい //Debug.Log( oldmesh.GetInstanceID() ); var newmesh = new Mesh(); newmesh.MarkDynamic(); newmesh.bounds = oldmesh.bounds; newmesh.vertices = oldmesh.vertices; collider.sharedMesh = newmesh; // enable をオフオンするまで実際には切り替わらなかったように思う hitmesh = newmesh; colliderTriangles = oldmesh.triangles; // これは実際には get で配列生成されてるっぽい(クローン不要) } // 三角形の大きさをゼロにする(全インデックスが 0 を指すようにする)。 Array.Clear(colliderTriangles, part.hitIndexInfo.startTriangle * 3, part.hitIndexInfo.triangleLength * 3); // 残面数を割り出す。 triangleRemaining -= part.hitIndexInfo.triangleLength; if (isBroken) { // 全破壊された場合、コライダをオフにするだけで済ませる。 downMeshCollider(); } else if (!isColliderBrokenInFrame) { // フレーム中に複数回更新されるのをふせぐ structure.StartCoroutine(applyBrokenCollider()); } }
public void breakPartInHitMesh(_StructurePart3 part) { if (part.hitIndexInfo.isEmpty) { return; } if (colliderTriangles == null) { // 初回はメッシュ生成 // 案:パーツコンテンツがホルダーの場合はメッシュ生成なしでいけるんじゃないのか? // あと結構メッシュ生成が重い気がするので、あらかじめ全部作ってしまうのはダメだろうか… collider.enabled = false; var oldmesh = collider.sharedMesh; // これはちゃんと同じメッシュを受け取ってるっぽい var newmesh = new Mesh(); newmesh.MarkDynamic(); newmesh.bounds = oldmesh.bounds; newmesh.vertices = oldmesh.vertices; colliderTriangles = oldmesh.triangles; // これは実際には get で配列生成されてるっぽい(クローン不要) collider.sharedMesh = newmesh; triangleToPartId.alloc(hitter.parts); } Array.Clear(colliderTriangles, part.hitIndexInfo.startTriangle * 3, part.hitIndexInfo.triangleLength * 3); // 三角形の大きさをゼロにする(全インデックスが 0 を指すようにする)。 triangleToPartId.remarkOffsets(part); // PhysX と Mesh のずれを解消する。ずれない仕様に戻ればなくしてよい。 if (!triangleToPartId.isFaceExist) // 全破壊された場合、コライダをオフにするだけで済ませる。 { collider.enabled = false; //Component.Destroy( collider ); } else if (!isColliderBrokenInFrame) // フレーム中に複数回更新されるのをふせぐ { //if( hitter.isBreakLocked ) return;// 暫定 //GM.startCoroutine( applyBrokenCollider() ); hitter.parentHitter.StartCoroutine(applyBrokenCollider()); } }
public PartInfo(_StructurePart3 p) { part = p; tf = p.transform; //mesh = p.GetComponent<MeshCollider>()?.sharedMesh ?? p.GetComponent<MeshFilter>().sharedMesh; var mc = p.GetComponent <MeshCollider>(); mesh = mc ? mc.sharedMesh : p.GetComponent <MeshFilter>().sharedMesh; }
/// <summary> /// 破壊フラグを立て、レンダラに非表示を指示する。 /// </summary> /// <param name="part">破壊したいパーツ</param> public void breakAndPartVisibilityOff(_StructurePart3 part) { breakManager.brokenFlags[part.partId] = true; structure.nearRenderer.setPartVisibilityOff(ref breakManager.brokenFlags, part.partId); if (part.isHittable & !isDestructed) { breakManager.breakers[(int)part.type].breakPartInHitMesh(part); } }
public void reparentAllCutcables(_StructurePart3 pole) { //var tfPole = pole.transform; var rbPole = pole.GetComponent <Rigidbody>(); for (var cutcable = cutcableLink; cutcable != null; cutcable = cutcable.cutcableLink) { cutcable.transform.parent = null; //tfPole; cutcable.rb.isKinematic = false; cutcable.GetComponent <FixedJoint>().connectedBody = rbPole; //gameObject.AddComponent<FixedJoint>().connectedBody = rbPole; GameObject.Destroy(cutcable.gameObject, 2.0f); } }
/// <summary> /// PhysX と Mesh のずれを解消する。 /// </summary> /// <param name="part">破壊されたパーツ</param> public void remarkOffsets(_StructurePart3 part) { faceLength -= part.hitIndexInfo.triangleLength; var ofsBytes = offsets[part.partId] * 2; var lenBytes = part.hitIndexInfo.triangleLength * 2; // パーツIDリストから破壊された面を削除(後ろが前に詰められる)。 Buffer.BlockCopy(partIds_back, ofsBytes + lenBytes, partIds_back, ofsBytes, partIds.Length * 2 - (ofsBytes + lenBytes)); // 面格納位置を破壊されたパーツの分だけ前にずらす(後ろのパーツ全てに影響する)。 // 破壊されたパーツの分は修正しなくてもいいが、その判定をとるなら全て修正したほうがよさそう? for (var i = part.partId + 1; i < offsets.Length; i++) { offsets[i] -= (ushort)part.hitIndexInfo.triangleLength; } }