public void Update() { if (Game.InFlightScene && this._isInitialized) { var craft = Game.Instance.FlightScene.CraftNode.CraftScript; var angularVelocity = craft.FlightData.AngularVelocity; // TODO: subtract the angular velocity of a target this._pitchRateText.text = $"{RadiansToDegrees(angularVelocity.x):F2} °/s"; this._yawRateText.text = $"{RadiansToDegrees(angularVelocity.y):F2} °/s"; this._rollRateText.text = $"{RadiansToDegrees(angularVelocity.z):F2} °/s"; this.SetRotationRateBars(angularVelocity); var target = craft.FlightData.NavSphereTarget; if (target != null && target.Parent == craft.CraftNode.Parent) { var relativeTargetPosition = target.Position - craft.CraftNode.Position; var relativeVelocity = target.Velocity - craft.CraftNode.Velocity; var velocityTowardsTarget = Vector3d.Project(relativeVelocity, relativeTargetPosition); this._translationRateX.text = $"{(Vector3d.Dot(relativeVelocity, craft.FlightData.CraftRight) * -1):F2} m/s"; this._translationRateY.text = $"{(Vector3d.Dot(relativeVelocity, craft.FlightData.CraftUp) * -1):F2} m/s"; this._translationRateZ.text = $"{Vector3d.Dot(relativeVelocity, craft.FlightData.CraftForward):F2} m/s"; var approachRate = velocityTowardsTarget.magnitude * (Vector3d.Angle(relativeTargetPosition, velocityTowardsTarget) > 90 ? -1 : 1); this._rateOfApproachText.text = $"{approachRate:F2} m/s"; var localRelativeTargetPosition = craft.CenterOfMass.InverseTransformDirection(craft.ReferenceFrame.PlanetToFrameVector(relativeTargetPosition)); var(dockingPort, dockingPortLocalPosition) = FindClosestDockingPort(craft, localRelativeTargetPosition); if (dockingPort != null) { localRelativeTargetPosition -= dockingPortLocalPosition; } this._targetOffsetX.text = $"{(localRelativeTargetPosition.x * -1):F2} m"; this._targetOffsetY.text = $"{(localRelativeTargetPosition.y * -1):F2} m"; this._targetOffsetZ.text = $"{localRelativeTargetPosition.z:F2} m"; this._rangeText.text = $"{localRelativeTargetPosition.magnitude:F1} m"; if (target is PartScript targetPart && targetPart.GetModifier <DockingPortScript>() != null) { var targetOrientationVector = (craft.ReferenceFrame.FrameToPlanetRotation(targetPart.Transform.rotation) * new Vector3(0, 1, 0) * -1).ToVector3(); var craftOrientationVector = dockingPort != null ? (craft.ReferenceFrame.FrameToPlanetRotation(dockingPort.Transform.rotation) * new Vector3(0, 1, 0)).ToVector3() : craft.FlightData.CraftForward.ToVector3(); var yawAxis = craft.FlightData.CraftUp.ToVector3(); var pitchAxis = craft.FlightData.CraftRight.ToVector3(); var rollAxis = craft.FlightData.CraftForward.ToVector3(); var yawOffset = Vector3.Angle(yawAxis, craftOrientationVector); if (yawOffset > 30 && yawOffset < 150) { var yawAngle = -1 * Vector3.SignedAngle( Vector3.ProjectOnPlane(craftOrientationVector, yawAxis), Vector3.ProjectOnPlane(targetOrientationVector, yawAxis), yawAxis ); this._yawAngleText.text = $"{yawAngle:F1} °"; } else { this._yawAngleText.text = ""; } var pitchOffset = Vector3.Angle(pitchAxis, craftOrientationVector); if (pitchOffset > 30 && pitchOffset < 150) { var pitchAngle = Vector3.SignedAngle( Vector3.ProjectOnPlane(craftOrientationVector, pitchAxis), Vector3.ProjectOnPlane(targetOrientationVector, pitchAxis), pitchAxis ); this._pitchAngleText.text = $"{pitchAngle:F1} °"; } else { this._pitchAngleText.text = ""; } var rollOffset = Vector3.Angle(rollAxis, craftOrientationVector); if (rollOffset > 30 && rollOffset < 150) { var rollAngle = Vector3.SignedAngle( Vector3.ProjectOnPlane(craftOrientationVector, rollAxis), Vector3.ProjectOnPlane(targetOrientationVector, rollAxis), rollAxis ); this._rollAngleText.text = $"{rollAngle:F1} °"; } else { this._rollAngleText.text = ""; } if (this.targetPositionMarker == null) { this.targetGuideMaterial = this.targetGuideMaterial ?? new Material(GuideMaterial) { color = new Color(0, 1, 0, 0.4f) }; this.targetPositionMarker = new GameObject(); // this.targetPositionMarker.transform.localScale = new Vector3(1, 1, 1); // this.targetPositionMarker.transform.localPosition = new Vector3(0, 0, 1); var children = new List <GameObject>(); for (var i = 1; i <= 5; i++) { var childTargetGuide = CreateTargetPortGuide(MeshCreator.CreateTorus(1, 0.1f / i), this.targetGuideMaterial); childTargetGuide.transform.parent = this.targetPositionMarker.transform; childTargetGuide.transform.position = new Vector3(0, i * 5, 0); childTargetGuide.transform.localScale = new Vector3(i, i, i); children.Add(childTargetGuide); this.targetPositionMarkerChildren = children; } } var targetRelativeOffset = targetPart.Transform.InverseTransformDirection( targetPart.Transform.position - (dockingPort?.Transform.position ?? craft.CenterOfMass.position) ); var translationError = (Single)Math.Min( 1.0, Math.Sqrt(Math.Pow(targetRelativeOffset.x, 2) + Math.Pow(targetRelativeOffset.z, 2)) / Math.Abs(targetRelativeOffset.y / 5) ); this.targetGuideMaterial.color = new Color( translationError <0.5f ? translationError * 2 : 1, translationError> 0.5f ? (1.0f - translationError) * 2 : 1, 0, 0.4f ); if (dockingPort != null && this.dockingPortMarker == null) { this.dockingPortMarker = GameObject.CreatePrimitive(PrimitiveType.Cylinder); Destroy(this.dockingPortMarker.GetComponent <Collider>()); this.dockingPortMarker.GetComponent <Renderer>().material = new Material(GuideMaterial) { color = new Color(1, 0, 0, 0.4f) }; this.dockingPortMarker.transform.localScale = new Vector3(0.05f, 4, 0.05f); } this.targetPositionMarker.transform.position = craft.ReferenceFrame.PlanetToFramePosition(target.Position); this.targetPositionMarker.transform.localRotation = targetPart.Transform.rotation; if (dockingPort != null) { this.dockingPortMarker.transform.position = dockingPort.Transform.position + (this.dockingPortMarker.transform.rotation * new Vector3(0, 4, 0)); this.dockingPortMarker.transform.rotation = dockingPort.Transform.rotation; } } else { this._pitchAngleText.text = ""; this._yawAngleText.text = ""; } } else { this.DestroyGuides(); this.ClearText(); } }