예제 #1
0
		void Awake() {
			GetTriggerCollider();
			_body = GetComponentInParent<CelestialBody>();
			if ( !_detector || !_body ) {
				enabled = false;
			}
			TriggerRadius = Mathf.Abs( TriggerRadius );
		}
예제 #2
0
 public FakeBody(SpaceGravity2D.CelestialBody body)
 {
     position          = body.transform.position;
     LastPosition      = body.LastPosition;
     Velocity          = body.Velocity;
     _additionVelocity = body._additionalVelocity;
     personalTimeScale = body.personalTimeScale;
 }
예제 #3
0
		void OnEnable() {
			if (_lineRenderer == null) {
				CreateLineRend();
			}
			if (_body == null) {
				_body = GetComponentInParent<CelestialBody>();
				if (_body == null) {
					Debug.LogWarning("SpaceGravity2D: Orbit Display can't find celestial body on " + name);
					enabled = false;
				}
			}
		}
예제 #4
0
		/// <summary>
		/// Post frame assignation coroutine is used for preventing cases, when random attractor is assigned from set of attractors
		/// </summary>
		IEnumerator SetNearestAttractor(bool checkIsInRange) {
			yield return new WaitForEndOfFrame();
			if (_newAttractorsBuffer == null || _newAttractorsBuffer.Count == 0) {
				yield break;
			}
			if (_newAttractorsBuffer.Count == 1) {
				if (checkIsInRange) {
					if (_newAttractorsBuffer[0] == null || ( _newAttractorsBuffer[0]._transform.position - _transform.position ).magnitude < Mathf.Min(_newAttractorsBuffer[0].MaxAttractionRange, _simulationControl.MaxAttractionRange)) {
						Attractor = _newAttractorsBuffer[0];
						CalculateNewOrbitData();
					}
				}
				else {
					Attractor = _newAttractorsBuffer[0];
					CalculateNewOrbitData();
				}
				_newAttractorsBuffer.Clear();
				yield break;
			}
			CelestialBody nearest = _newAttractorsBuffer[0];
			float sqrDistance = nearest != null ? ( nearest._transform.position - _transform.position ).sqrMagnitude : float.MaxValue;
			for (int i = 1; i < _newAttractorsBuffer.Count; i++) {
				if (_newAttractorsBuffer[i] == nearest) {
					continue;
				}
				if (_newAttractorsBuffer[i] != null && ( _newAttractorsBuffer[i].transform.position - _transform.position ).sqrMagnitude < sqrDistance) {
					nearest = _newAttractorsBuffer[i];
					sqrDistance = ( _newAttractorsBuffer[i].transform.position - _transform.position ).sqrMagnitude;
				}
			}
			_newAttractorsBuffer.Clear();
			Attractor = nearest;
			CalculateNewOrbitData();
		}
예제 #5
0
		/// <summary>
		/// Assign new attractor for body at the end of current frame. If called multiple times in single frame, nearest attractor will be chosen
		/// </summary>
		/// <param name="attr">new attractor reference or null</param>
		/// <param name="checkIsInRange"></param>
		/// <param name="instant">if false, attractor will be assigned at End Of Frame</param>
		public void SetAttractor(CelestialBody attr, bool checkIsInRange = false, bool instant = false) {
			if (attr == null || attr != Attractor && attr != this) {
				if (!Application.isPlaying || instant) {
					TerminateRailMotion();
					Attractor = attr;
					CalculateNewOrbitData();
					return;
				}
				if (_newAttractorsBuffer == null || _newAttractorsBuffer.Count == 0) {
					_newAttractorsBuffer = new List<CelestialBody>();
					StartCoroutine(SetNearestAttractor(checkIsInRange));
					TerminateRailMotion();
				}
				_newAttractorsBuffer.Add(attr);
			}
		}
예제 #6
0
		void UnregisterBody(CelestialBody body) {
			_bodies.Remove(body);
		}
예제 #7
0
		void RegisterBody(CelestialBody body) {
			_bodies.Add(body);
		}
예제 #8
0
		/// <summary>
		/// Return ratio of perturbation force from third body relative to attraction force of mainAttractor
		/// </summary>
		/// <param name="targetBody"></param>
		/// <param name="mainAttractor"></param>
		/// <param name="perturbatingAttractor"></param>
		public static float RelativePerturbationRatio(CelestialBody targetBody, CelestialBody mainAttractor, CelestialBody perturbatingAttractor) {
			float mainAcceleration = AccelerationByAttractionForce(targetBody._transform.position, mainAttractor._transform.position, mainAttractor.MG).magnitude;
			float perturbAcceleration = AccelerationByAttractionForce(targetBody._transform.position, perturbatingAttractor._transform.position, perturbatingAttractor.MG).magnitude;
			return perturbAcceleration / mainAcceleration;
		}
예제 #9
0
		/// <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);
			}
		}
예제 #10
0
 /// <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), false, true);
 }
예제 #11
0
		/// <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);
				}
			}
		}
예제 #12
0
		/// <summary>
		/// Find biggest attractor in scene
		/// </summary>
		public void GetCentralAttractor() {
			var tempBodies = Application.isPlaying ? _bodies.ToArray() : GameObject.FindObjectsOfType<CelestialBody>();
			if (tempBodies.Length == 0) {
				_centralAttractor = null;
				return;
			}
			if (tempBodies.Length == 1) {
				_centralAttractor = tempBodies[0];
				return;
			}
			var biggestMassIndex = 0;
			for (int i = 1; i < tempBodies.Length; i++) {
				if (!Application.isPlaying) {
					tempBodies[i - 1].FindReferences();
					tempBodies[i].FindReferences();
				}
				if (tempBodies[i].Mass > tempBodies[biggestMassIndex].Mass) {
					biggestMassIndex = i;
				}
			}
			if (biggestMassIndex >= 0 && biggestMassIndex < tempBodies.Length) {
				_centralAttractor = tempBodies[biggestMassIndex];
			}
		}
예제 #13
0
		public Vector2 CalcAcceleration(CelestialBody body) {
			Vector2 forceAcceleration = Vector2.zero;
			for (int i = 0; i < _attractorsCache.Count; i++) {
				if (_attractorsCache[i] == body) {
					continue;
				}
				forceAcceleration += AccelerationByAttractionForce(body._transform.position, _attractorsCache[i]._transform.position, _attractorsCache[i].MG, MinAttractionRange, Mathf.Min(MaxAttractionRange, _attractorsCache[i].MaxAttractionRange));
			}

			return forceAcceleration;
		}
		void Start() {
			cbody = GetComponentInParent<CelestialBody>();
			if (cbody == null) {
				enabled = false;
			}
		}
예제 #15
0
 public void SetBiggestAttractorForBody(CelestialBody body)
 {
     body.SetAttractor(FindBiggestAttractor(), false, true);
 }
예제 #16
0
		/// <summary>
		/// Test body for chain loops
		/// </summary>
		public bool AttractorChainContains(CelestialBody body) {
			CelestialBody current = Attractor;
			while (current != null) {
				if (current == body) {
					return true;
				}
				current = current.Attractor;
			}
			return false;
		}
예제 #17
0
		/// <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;
			}
		}
예제 #18
0
 /// <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), false, true);
 }