void SolverOnCollision(object sender, Obi.ObiSolver.ObiCollisionEventArgs e) { foreach (Oni.Contact contact in e.contacts) { // this one is an actual collision: if (contact.distance < 0.01) { ActiveCollider ac = new ActiveCollider(); ObiSolver.ParticleInActor pa = solver.particleToActor[contact.particle]; ac.actor = pa.actor; ac.idxInAct = pa.indexInActor; ac.idxInSol = contact.particle; Component collider; if (ObiCollider.idToCollider.TryGetValue(contact.other, out collider)) { Vector3 SolvColPos = new Vector3(contact.point[0], contact.point[1], contact.point[2]); //print("Куб: Обнаружен контакт: " + contact.particle + " " + contact.point); Vector3 WorldColPos = solver.gameObject.transform.TransformPoint(SolvColPos); //marker.position = WorldColPos; ac.pos = WorldColPos; if (collider is Collider) { ac.col = collider as Collider; } } _actCol.Add(ac); } } }
// проверить, что ac контактирует с внешним коллайдером private bool FindExternalCol(ActiveCollider ac) { for (int i = 0; i < yachtCols.Length; i++) { if (ac.col == yachtCols[i]) { return(false); } } return(true); }
public void SolveAllRopes() { summF = Vector3.zero; //print("Утка " + name); // по всем канатам этой утки: for (int i = 0; i < Ropes.Count; i++) { if (!Ropes[i].obiRope.isActiveAndEnabled) { continue; } Vector3 direct = Vector3.zero; // направление силы на одном канате float valueF = 0; // величина силы на одном канате float curDist = 0; // от утки до точки закрепления с учетом изгибов // сортируем точки коллайдинга var sortedCol = from c in Ropes[i].actCol orderby c.idxInAct select c; List <ActiveCollider> sortCol = new List <ActiveCollider>(sortedCol); // вычислим текущую длинну каната - она состоит из длинн отрезков if (sortCol.Count == 0) { curDist = Vector3.Distance(transform.position, Ropes[i].Pos); } else { curDist = Vector3.Distance(transform.position, sortCol[0].pos); for (int j = 0; j < sortCol.Count - 1; j++) { curDist += Vector3.Distance(sortCol[j].pos, sortCol[j + 1].pos); } curDist += Vector3.Distance(sortCol[sortCol.Count - 1].pos, Ropes[i].Pos); } foreach (ActiveCollider ac in sortCol) { print(ac.actor.name + " " + ac.idxInAct + " " + ac.pos + " " + ac.col.name + " curDist = " + curDist); } direct = Vector3.zero; // проверка, не лопнул ли канат if (curDist / Ropes[i].Len > Ropes[i].Stretch) { print("Канат лопнул! Утка " + gameObject.name + " канат " + i); Ropes[i].obiRope.gameObject.SetActive(false); } else { // если не лопнул, считаем силу на этом канате valueF = 0; if (curDist > Ropes[i].Len) // имеется натяжение? { valueF = (curDist / Ropes[i].Len - 1) / (Ropes[i].Stretch - 1) * Ropes[i].MaxForce; // определяем направление силы if (sortCol.Count == 0) { // если нет коллайдеров на канате, направление - от утки к точке закрепления direct = (Ropes[i].Pos - transform.position).normalized; } else { // если еть коллайдеры на канате, надо найти первый коллайдер не принадлежащий яхте (временно!) ActiveCollider ac = null; for (int j = 0; j < sortCol.Count; j++) { if (FindExternalCol(sortCol[j])) { ac = sortCol[j]; break; } } if (ac == null) { // если коллайдеры только с корпусом яхты, направление - от утки к точке закрепления (временно!) direct = (Ropes[i].Pos - transform.position).normalized; } else { direct = (ac.pos - transform.position).normalized; } } } } Ropes[i].curForce = direct * valueF; summF += Ropes[i].curForce; } }