/// <summary>
        /// Fast and simple way to find attractor;
        /// But note, that not always nearest attractor is most proper
        /// </summary>
        /// <param name="body"></param>
        public void FindNearestAttractorForBody(CelestialBody body)
        {
            CelestialBody resultAttractor = null;
            float         sqrDistance     = 0;

            if (!Application.isPlaying)
            {
                _bodies = new List <CelestialBody>(GameObject.FindObjectsOfType <CelestialBody>());
            }
            foreach (var otherBody in _bodies)
            {
                if (otherBody == body || otherBody.Mass < MinAttractorMass || (otherBody.transform.position - body.transform.position).magnitude > Mathf.Min(MaxAttractionRange, otherBody.MaxAttractionRange))
                {
                    continue;
                }
                float _sqrDistance = (body._transform.position - otherBody._transform.position).sqrMagnitude;
                if (resultAttractor == null || sqrDistance > _sqrDistance)
                {
                    resultAttractor = otherBody;
                    sqrDistance     = _sqrDistance;
                }
            }
            if (!Application.isPlaying)
            {
                _bodies.Clear();                 //_bodies must be empty in editor mode
            }
            if (resultAttractor != null)
            {
                if (resultAttractor != body.Attractor)
                {
                    body.SetAttractor(resultAttractor, false, true);
                }
            }
        }
 /// <summary>
 /// One more convenient way to set attractor;
 /// </summary>
 /// <param name="body"></param>
 public void SetBiggestAttractorForBody(CelestialBody body)
 {
     GetCentralAttractor();
     if (_centralAttractor != null)
     {
         body.SetAttractor(_centralAttractor, false, true);
     }
 }
        /// <summary>
        /// Find attractor which has biggest gravitational influence on body comparing to others. If fail, null will be assigned.
        /// It can be used in realtime for implementing more precise transitions beetween spheres of influence,
        /// but, without optimisations, performance cost definetly will be very high
        /// </summary>
        /// <param name="body"></param>
        public void FindMostProperAttractorForBody(CelestialBody body)
        {
            CelestialBody resultAttractor = null;

            if (!Application.isPlaying)
            {
                _bodies = new List <CelestialBody>(GameObject.FindObjectsOfType <CelestialBody>());
            }
            // Search logic:
            // calculate mutual perturbation for every pair of attractors in scene and select one,
            // which attracts the body with biggest force and is least affected by others.
            foreach (var otherBody in _bodies)
            {
                if (otherBody == body || !otherBody.isActiveAndEnabled || otherBody.Mass < MinAttractorMass || (otherBody.transform.position - body.transform.position).magnitude > Mathf.Min(MaxAttractionRange, otherBody.MaxAttractionRange))
                {
                    continue;
                }
                if (!Application.isPlaying)
                {
                    otherBody.FindReferences();
                }
                if (resultAttractor == null)
                {
                    resultAttractor = otherBody;
                    continue;
                }
                if (RelativePerturbationRatio(body, resultAttractor, otherBody) > RelativePerturbationRatio(body, otherBody, resultAttractor))
                {
                    resultAttractor = otherBody;
                }
            }
            if (!Application.isPlaying)
            {
                _bodies.Clear();                 //_bodies must be empty in editor mode
            }
            if (resultAttractor != body.Attractor)
            {
                body.SetAttractor(resultAttractor, false, true);
                //body.Attractor = resultAttractor;
            }
        }
 /// <summary>
 /// Assign biggest attractor on scene to target body.
 /// </summary>
 /// <param name="body"></param>
 public void SetBiggestAttractorForBody(CelestialBody body)
 {
     body.SetAttractor(FindBiggestAttractor());
 }
 /// <summary>
 /// Find attractor which has biggest gravitational influence on body comparing to others. If fail, null will be assigned.
 /// It can be used in realtime for implementing more precise transitions beetween spheres of influence,
 /// but performance cost is high
 /// </summary>
 public void SetMostProperAttractorForBody(CelestialBody body)
 {
     body.SetAttractor(FindMostProperAttractor(body));
 }
 /// <summary>
 /// Fast and simple way to find attractor;
 /// But note, that not always nearest attractor is most proper
 /// </summary>
 public void SetNearestAttractorForBody(CelestialBody body)
 {
     body.SetAttractor(FindNearestAttractor(body));
 }
		/// <summary>
		/// One more convenient way to set attractor;
		/// </summary>
		/// <param name="body"></param>
		public void SetBiggestAttractorForBody(CelestialBody body) {
			GetCentralAttractor();
			if (_centralAttractor != null) {
				body.SetAttractor(_centralAttractor, false, true);
			}
		}
		/// <summary>
		/// Find attractor which has biggest gravitational influence on body comparing to others. If fail, null will be assigned.
		/// It can be used in realtime for implementing more precise transitions beetween spheres of influence, 
		/// but, without optimisations, performance cost definetly will be very high
		/// </summary>
		/// <param name="body"></param>
		public void FindMostProperAttractorForBody(CelestialBody body) {
			CelestialBody resultAttractor = null;
			if (!Application.isPlaying) {
				_bodies = new List<CelestialBody>(GameObject.FindObjectsOfType<CelestialBody>());
			}
			// Search logic:
			// calculate mutual perturbation for every pair of attractors in scene and select one, 
			// which attracts the body with biggest force and is least affected by others.
			foreach (var otherBody in _bodies) {
				if (otherBody == body || !otherBody.isActiveAndEnabled || otherBody.Mass < MinAttractorMass || ( otherBody.transform.position - body.transform.position ).magnitude > Mathf.Min(MaxAttractionRange, otherBody.MaxAttractionRange)) {
					continue;
				}
				if (!Application.isPlaying) {
					otherBody.FindReferences();
				}
				if (resultAttractor == null) {
					resultAttractor = otherBody;
					continue;
				}
				if (RelativePerturbationRatio(body, resultAttractor, otherBody) > RelativePerturbationRatio(body, otherBody, resultAttractor)) {
					resultAttractor = otherBody;
				}
			}
			if (!Application.isPlaying) {
				_bodies.Clear(); //_bodies must be empty in editor mode
			}
			if (resultAttractor != body.Attractor) {
				body.SetAttractor(resultAttractor, false, true);
				//body.Attractor = resultAttractor;
			}
		}
		/// <summary>
		/// Fast and simple way to find attractor; 
		/// But note, that not always nearest attractor is most proper
		/// </summary>
		/// <param name="body"></param>
		public void FindNearestAttractorForBody(CelestialBody body) {
			CelestialBody resultAttractor = null;
			float sqrDistance = 0;
			if (!Application.isPlaying) {
				_bodies = new List<CelestialBody>(GameObject.FindObjectsOfType<CelestialBody>());
			}
			foreach (var otherBody in _bodies) {
				if (otherBody == body || otherBody.Mass < MinAttractorMass || ( otherBody.transform.position - body.transform.position ).magnitude > Mathf.Min(MaxAttractionRange, otherBody.MaxAttractionRange)) {
					continue;
				}
				float _sqrDistance = ( body._transform.position - otherBody._transform.position ).sqrMagnitude;
				if (resultAttractor == null || sqrDistance > _sqrDistance) {
					resultAttractor = otherBody;
					sqrDistance = _sqrDistance;
				}
			}
			if (!Application.isPlaying) {
				_bodies.Clear(); //_bodies must be empty in editor mode
			}
			if (resultAttractor != null) {
				if (resultAttractor != body.Attractor) {
					body.SetAttractor(resultAttractor, false, true);
				}
			}
		}