public WormWayPoint(Vector3 pos, Quaternion rot, bool vis, WormWayPoint nex = null) { position = pos; rotation = rot; visible = vis; next = nex; milestone = false; }
//Body movement functions #region BodyMovement private void SetInitialBodyWayPoints() { headWayPoint = null; if (tailTrf != null) { headWayPoint = new WormWayPoint(tailTrf.position, tailTrf.rotation, false); } for (int i = bodySegmentsTrf.Length - 1; i >= 0; --i) { WormWayPoint segmentWayPoint = new WormWayPoint(bodySegmentsTrf[i].position, bodySegmentsTrf[i].rotation, false, (headWayPoint != null ? headWayPoint : null)); headWayPoint = segmentWayPoint; } if (headTrf != null) { headWayPoint = new WormWayPoint(headTrf.position, headTrf.rotation, false, (headWayPoint != null ? headWayPoint : null)); } }
public void UpdateBodyMovement() { sinDistanceFactor = 360 / WanderingSettingsPhase.sinLongitude; sinTimeFactor = 360 / WanderingSettingsPhase.sinCycleDuration; //If head has moved, create a new waypoint and recalculate all segments' position if ((headTrf.position != headWayPoint.position)) { //Update sin time sinElapsedTime += Time.deltaTime; if (sinElapsedTime >= WanderingSettingsPhase.sinCycleDuration) { sinElapsedTime -= WanderingSettingsPhase.sinCycleDuration; } sinTimeOffset = sinElapsedTime * sinTimeFactor; headWayPoint = new WormWayPoint(headTrf.position, headTrf.rotation, head.IsVisible(), headWayPoint); WormWayPoint current = headWayPoint; WormWayPoint next = current.next; //if we are in the last waypoint, there is nothing more we can do, so we quit if (next == null) { return; } float totalDistance = headToJunctionDistance; //Total distance we have to position the element from the head float consolidatedDistance = 0f; //Sum of the distances of evaluated waypoints float distanceBetween = (current.position - next.position).magnitude; //Distance between current current and next waypoints float effectiveDistance; float totalOffset = 0f; if (applySinMovement) { totalOffset = (Mathf.Sin((totalDistance * sinDistanceFactor) + sinTimeOffset) * WanderingSettingsPhase.sinAmplitude); effectiveDistance = totalDistance + totalOffset; } else { effectiveDistance = totalDistance; } //move each body segment through the virtual line for (int i = 0; i < bodySegmentsTrf.Length; ++i) { //---- Junction ---- //advance through waypoints until we find the proper distance while (consolidatedDistance + distanceBetween < effectiveDistance) { consolidatedDistance += distanceBetween; current = next; next = current.next; //if we are in the last waypoint, there is nothing more we can do, so we quit if (next == null) { return; } distanceBetween = (current.position - next.position).magnitude; } //We reached the line segment where this body part must be, so we calculate the point in current segment float remainingDistance = effectiveDistance - consolidatedDistance; Vector3 direction = (next.position - current.position).normalized * remainingDistance; junctionsTrf[i].position = current.position + direction; junctionsTrf[i].rotation = Quaternion.Slerp(current.rotation, next.rotation, remainingDistance / distanceBetween); //junctionsTrf[i].Translate(0f, -totalOffset, 0f, Space.Self); junctionsTrf[i].gameObject.SetActive(current.visible || next.visible); //---- Body ---- totalDistance += segmentToJunctionDistance; if (applySinMovement) { totalOffset = (Mathf.Sin((totalDistance * sinDistanceFactor) + sinTimeOffset) * WanderingSettingsPhase.sinAmplitude); effectiveDistance = totalDistance + totalOffset; } else { effectiveDistance = totalDistance; } //advance through waypoints until we find the proper distance while (consolidatedDistance + distanceBetween < effectiveDistance) { consolidatedDistance += distanceBetween; current = next; next = current.next; //if we are in the last waypoint, there is nothing more we can do, so we quit if (next == null) { return; } distanceBetween = (current.position - next.position).magnitude; } //We reached the line segment where this body part must be, so we calculate the point in current segment remainingDistance = effectiveDistance - consolidatedDistance; direction = (next.position - current.position).normalized * remainingDistance; bodySegmentsTrf[i].position = current.position + direction; bodySegmentsTrf[i].rotation = Quaternion.Slerp(current.rotation, next.rotation, remainingDistance / distanceBetween); //bodySegmentsTrf[i].Translate(0f, -totalOffset, 0f, Space.Self); bodySegmentControllers[i].SetVisible(current.visible || next.visible); //if it was the final body part and there is no tail, release the oldest waypoints if (i == bodySegmentsTrf.Length - 1) { if (tailTrf == null) { next.next = null; //Remove reference, let garbage collector do its job } } //else add total distance for the next iteration else { totalDistance += segmentToJunctionDistance; if (applySinMovement) { totalOffset = (Mathf.Sin((totalDistance * sinDistanceFactor) + sinTimeOffset) * WanderingSettingsPhase.sinAmplitude); effectiveDistance = totalDistance + totalOffset; } else { effectiveDistance = totalDistance; } } } //finally do the same for the tail if (tailTrf != null) { //---- Junction ---- totalDistance += segmentToJunctionDistance; if (applySinMovement) { totalOffset = (Mathf.Sin((totalDistance * sinDistanceFactor) + sinTimeOffset) * WanderingSettingsPhase.sinAmplitude); effectiveDistance = totalDistance + totalOffset; } else { effectiveDistance = totalDistance; } //advance through waypoints until we find the proper distance while (consolidatedDistance + distanceBetween < effectiveDistance) { consolidatedDistance += distanceBetween; current = next; next = current.next; //if we are in the last waypoint, there is nothing more we can do, so we quit if (next == null) { return; } distanceBetween = (current.position - next.position).magnitude; } //We reached the line segment where this body part must be, so we calculate the point in current segment float remainingDistance = effectiveDistance - consolidatedDistance; Vector3 direction = (next.position - current.position).normalized * remainingDistance; junctionsTrf[junctionsTrf.Length - 1].position = current.position + direction; junctionsTrf[junctionsTrf.Length - 1].rotation = Quaternion.Slerp(current.rotation, next.rotation, remainingDistance / distanceBetween); junctionsTrf[junctionsTrf.Length - 1].gameObject.SetActive(current.visible || next.visible); //---- Tail ---- totalDistance += tailToJunctionDistance; if (applySinMovement) { totalOffset = (Mathf.Sin((totalDistance * sinDistanceFactor) + sinTimeOffset) * WanderingSettingsPhase.sinAmplitude); effectiveDistance = totalDistance + totalOffset; } else { effectiveDistance = totalDistance; } //advance through waypoints until we find the proper distance while (consolidatedDistance + distanceBetween < effectiveDistance) { consolidatedDistance += distanceBetween; current = next; next = current.next; //if we are in the last waypoint, there is nothing more we can do, so we quit if (next == null) { return; } distanceBetween = (current.position - next.position).magnitude; } //We reached the line segment where this body part must be, so we calculate the point in current segment remainingDistance = effectiveDistance - consolidatedDistance; direction = (next.position - current.position).normalized * remainingDistance; tailTrf.position = current.position + direction; tailTrf.rotation = Quaternion.Slerp(current.rotation, next.rotation, remainingDistance / distanceBetween); tailController.SetVisible(current.visible || next.visible); //search for milestones WormWayPoint aux = next; while (aux != null) { if (aux.milestone) { aux.milestone = false; tailReachedMilestone = true; break; } aux = aux.next; } aux = null; //release the oldest waypoints next.next = null; //Remove reference, let garbage collector do its job } } }