private void OnEnable() { if (_moverReference == null) { _moverReference = GetComponent <KeplerOrbitMover>(); } }
private List <Vector3d> CalculateVelocityDifference(KeplerOrbitMover a, KeplerOrbitMover b, KeplerOrbitData transitionOrbit, double departureTime, double duration, double eccAnomalyDeparture, double eccAnomalyArrival) { var aMeanAnomalyAtDeparture = a.OrbitData.MeanAnomaly + a.OrbitData.MeanMotion * departureTime; var aEccAnomAtDeparture = KeplerOrbitUtils.ConvertMeanToEccentricAnomaly(aMeanAnomalyAtDeparture, a.OrbitData.Eccentricity); var aVelocityAtDeparture = a.OrbitData.GetVelocityAtEccentricAnomaly(aEccAnomAtDeparture); var bMeanAnomalyAtArrival = b.OrbitData.MeanAnomaly + b.OrbitData.MeanMotion * (departureTime + duration); var bEccAnomAtArrival = KeplerOrbitUtils.ConvertMeanToEccentricAnomaly(aMeanAnomalyAtDeparture, a.OrbitData.Eccentricity); var bVelocityAtArrival = a.OrbitData.GetVelocityAtEccentricAnomaly(aEccAnomAtDeparture); var transitionVeloctyStart = transitionOrbit.GetVelocityAtEccentricAnomaly(eccAnomalyDeparture); var transitionVelcityEnd = transitionOrbit.GetVelocityAtEccentricAnomaly(eccAnomalyArrival); var result = new List <Vector3d>(); result.Add(transitionVeloctyStart - aVelocityAtDeparture); result.Add(bVelocityAtArrival - transitionVelcityEnd); return(result); }
/// <summary> /// Find and return referneces to three bodies: self, target and mutual attractor. /// Additional attractors chain arrays are used when mutual attractor is not direct parent of target body. /// If mutual attractor not existent, or target not assigned, then return empty data. /// </summary> /// <returns>All references data, or empty data if not found.</returns> public BodiesReferencesData GetBodiesReferences() { if (_orbitMover == null) { _orbitMover = GetComponent <KeplerOrbitMover>(); } if (_orbitMover == null || Target == null || _orbitMover == Target) { return(default(BodiesReferencesData)); } List <KeplerOrbitMover> attractorsA = new List <KeplerOrbitMover>(); List <KeplerOrbitMover> attractorsB = new List <KeplerOrbitMover>(); double mass = 0; double g = 0; Transform mutualAttractor = FindMutualAttractor( a: _orbitMover, b: Target, isGetFullChain: false, attractorsAChain: ref attractorsA, attractorsBChain: ref attractorsB, mass: ref mass, gConst: ref g); if (mutualAttractor != null) { return(new BodiesReferencesData() { Origin = _orbitMover, Target = Target, Attractor = mutualAttractor, OriginAttractorsChain = attractorsA.ToArray(), TargetAttractorsChain = attractorsB.ToArray(), AttractorMass = mass, GConst = g, }); } return(default(BodiesReferencesData)); }
private void OnEnable() { _target = target as KeplerOrbitMover; }
/// <summary> /// Find attractor transform, which is parent for both A and B. /// If mutual attractor is not direct parent of both A and B, then look in upper hierarchy of attractors. /// </summary> /// <param name="a">Body A.</param> /// <param name="b">Body B.</param> /// <param name="isGetFullChain">If true, attractors chains will include full hierarchy. In opposite case, chains will end before mutual attractor.</param> /// <param name="attractorsAChain">Chain of parent attractors for A.</param> /// <param name="attractorsBChain">Chain of parent attractors for B.</param> /// <param name="gConst">Attractor gravity const.</param> /// <param name="mass">Attractor mass.</param> /// <returns>Mutual attractor transform or null if not found.</returns> /// <remarks> /// Chain of attractors is constructed from attractors transforms, which also have own KeplerOrbitMover component. /// /// Note: this method also retreaving g and mass of attractor. Because these values can be different for any KeplerOrbitMover, those, what belong to body A are preffered. /// </remarks> public static Transform FindMutualAttractor(KeplerOrbitMover a, KeplerOrbitMover b, bool isGetFullChain, ref List <KeplerOrbitMover> attractorsAChain, ref List <KeplerOrbitMover> attractorsBChain, ref double mass, ref double gConst) { if (attractorsAChain == null) { attractorsAChain = new List <KeplerOrbitMover>(); } else { attractorsAChain.Clear(); } if (attractorsBChain == null) { attractorsBChain = new List <KeplerOrbitMover>(); } else { attractorsBChain.Clear(); } int maxChainLen = 1000; Transform mutualAttractor = null; if (a != null && b != null && a != b) { var attrTransform = a.AttractorSettings.AttractorObject; while (attrTransform != null && attractorsAChain.Count < maxChainLen) { var attrOrbitMover = attrTransform.GetComponent <KeplerOrbitMover>(); attrTransform = null; if (attrOrbitMover != null && !attractorsAChain.Contains(attrOrbitMover)) { attrTransform = attrOrbitMover.AttractorSettings.AttractorObject; attractorsAChain.Add(attrOrbitMover); } } attrTransform = b.AttractorSettings.AttractorObject; while (attrTransform != null && attractorsBChain.Count < maxChainLen) { var attrOrbitMover = attrTransform.GetComponent <KeplerOrbitMover>(); attrTransform = null; if (attrOrbitMover != null && !attractorsBChain.Contains(attrOrbitMover)) { attrTransform = attrOrbitMover.AttractorSettings.AttractorObject; attractorsBChain.Add(attrOrbitMover); } } if (a.AttractorSettings.AttractorObject == b.AttractorSettings.AttractorObject) { mutualAttractor = a.AttractorSettings.AttractorObject; gConst = a.AttractorSettings.GravityConstant; mass = a.AttractorSettings.AttractorMass; } else { for (int i = 0; i < attractorsAChain.Count && mutualAttractor == null; i++) { for (int n = 0; n < attractorsBChain.Count; n++) { if (attractorsAChain[i].AttractorSettings.AttractorObject == attractorsBChain[n].transform || attractorsAChain[i].AttractorSettings.AttractorObject == attractorsBChain[i].AttractorSettings.AttractorObject) { mutualAttractor = attractorsAChain[i].AttractorSettings.AttractorObject; gConst = attractorsAChain[i].AttractorSettings.GravityConstant; mass = attractorsAChain[i].AttractorSettings.AttractorMass; } else if (attractorsBChain[i].AttractorSettings.AttractorObject == attractorsAChain[i].transform) { mutualAttractor = attractorsBChain[i].AttractorSettings.AttractorObject; gConst = attractorsAChain[i].AttractorSettings.GravityConstant; mass = attractorsAChain[i].AttractorSettings.AttractorMass; } else { continue; } break; } } } if (!isGetFullChain && mutualAttractor != null) { int mutualAttractorIndex = -1; for (int i = 0; i < attractorsAChain.Count; i++) { if (attractorsAChain[i].transform == mutualAttractor) { mutualAttractorIndex = i; break; } } if (mutualAttractorIndex >= 0) { //mutualAttractorIndex++; while (attractorsAChain.Count > mutualAttractorIndex) { attractorsAChain.RemoveAt(attractorsAChain.Count - 1); } } mutualAttractorIndex = -1; for (int i = 0; i < attractorsBChain.Count; i++) { if (attractorsBChain[i].transform == mutualAttractor) { mutualAttractorIndex = i; break; } } if (mutualAttractorIndex >= 0) { //mutualAttractorIndex++; while (attractorsBChain.Count > mutualAttractorIndex) { attractorsBChain.RemoveAt(attractorsBChain.Count - 1); } } } return(mutualAttractor); } attractorsAChain.Clear(); attractorsBChain.Clear(); return(null); }
/// <summary> /// Get world space position vector at given time. /// </summary> /// <param name="target">Target body.</param> /// <param name="time">Time, relative to current time.</param> /// <param name="attractors">Optional chain of attractors. Order of attractors must be from closest to furthest in hierarchy.</param> /// <returns>Position at given time.</returns> /// <remarks> /// Zero time is considered current state. /// For example, at time 0 result position vector will be equal to current target position. /// This method allows to progress orbit in time forward (or backward, if passed time is negative) and get position of body at that time. /// If attractors collection is not null or empty, then evaluation process will propagate through all attractors, which will affect result. /// </remarks> public static Vector3 GetPositionAtGivenTime(KeplerOrbitMover target, float time, KeplerOrbitMover[] attractorsChain = null) { if (target == null) { return(new Vector3()); } if (!target.OrbitData.IsValidOrbit || target.AttractorSettings.AttractorObject == null) { return(target.transform.position); } if (attractorsChain == null || attractorsChain.Length == 0) { if (!target.enabled || target.TimeScale == 0f) { return(target.transform.position); } else { var finalMeanAnom = target.OrbitData.MeanAnomaly + target.OrbitData.MeanMotion * time; var finalEccAnom = KeplerOrbitUtils.ConvertMeanToEccentricAnomaly(finalMeanAnom, target.OrbitData.Eccentricity); var result = target.AttractorSettings.AttractorObject.transform.position + (Vector3)target.OrbitData.GetFocalPositionAtEccentricAnomaly(finalEccAnom); return(result); } } else { var relativePosition = new Vector3(); for (int i = 0; i < attractorsChain.Length; i++) { bool isLast = i == attractorsChain.Length - 1; if (attractorsChain[i].OrbitData.IsValidOrbit && attractorsChain[i].AttractorSettings.AttractorObject != null) { if (attractorsChain[i].enabled) { var attrMeanAnom = attractorsChain[i].OrbitData.MeanAnomaly + attractorsChain[i].OrbitData.MeanMotion * attractorsChain[i].TimeScale * time; var attrEccAnom = KeplerOrbitUtils.ConvertMeanToEccentricAnomaly(attrMeanAnom, attractorsChain[i].OrbitData.Eccentricity); relativePosition += (Vector3)attractorsChain[i].OrbitData.GetFocalPositionAtEccentricAnomaly(attrEccAnom); } else { relativePosition += attractorsChain[i].transform.position - attractorsChain[i].AttractorSettings.AttractorObject.transform.position; } if (isLast) { relativePosition += attractorsChain[i].AttractorSettings.AttractorObject.position; } } else { if (isLast || attractorsChain[i].AttractorSettings.AttractorObject == null) { relativePosition += attractorsChain[i].transform.position; } else { relativePosition += (Vector3)attractorsChain[i].OrbitData.Position; } } } if (!target.enabled || target.TimeScale == 0f) { relativePosition += target.transform.position - target.AttractorSettings.AttractorObject.position; } else { var finalMeanAnom = target.OrbitData.MeanAnomaly + target.OrbitData.MeanMotion * time; var finalEccAnom = KeplerOrbitUtils.ConvertMeanToEccentricAnomaly(finalMeanAnom, target.OrbitData.Eccentricity); relativePosition += (Vector3)target.OrbitData.GetFocalPositionAtEccentricAnomaly(finalEccAnom); } return(relativePosition); } }
private void Awake() { _orbitMover = GetComponent <KeplerOrbitMover>(); }
private void Awake() { _orbitMover = GetComponent <KeplerOrbitMover>(); _spawnNotifier = GetComponent <SpawnNotifier>(); }
public void NotifyBodySpawned(KeplerOrbitMover b) { _onGlobalBodySpawnedEvent?.Invoke(b); }
private void OnGlobalNotify(KeplerOrbitMover b) { onBodySpawnedEvent?.Invoke(b); }