void FixedUpdate() { _OnDrawGizmos = null; Vector3 gravity = (planet.transform.position - transform.position).normalized; Vector3 groundDirection = gravity; // TODO shift it with velocity Ray groundRay = new Ray(transform.position, groundDirection); RaycastHit groundHit; if (Physics.Raycast(groundRay, out groundHit, Mathf.Infinity, ~terrainLayer)) { float hoverDelta = altitude - groundHit.distance; Vector3 velocity = m_rigidbody.velocity; float upwardSpeed = (transform.worldToLocalMatrix * velocity).y; float lift = hoverDelta * Mathf.Pow(hoverForce, 2); lift += (1 * Mathf.Sign(hoverDelta)) * hoverAmplitude * hoverSinusoidal((Time.fixedTime % hoverPeriod) / hoverPeriod).y / lift; // Debug.Log($"lift {lift} velocity.y {velocity.y} upwardSpeed {upwardSpeed}"); m_rigidbody.AddForce(lift * -groundDirection, ForceMode.Acceleration); } Vector3 transformUp = transform.up; Vector3 forwardShift = Vector3.Cross(groundDirection, transform.right).normalized; // Debug.Log("dot gravity transformDown" + Vector3.Dot(gravity, transformUp)); // Debug.DrawRay(transform.position, transform.forward, Color.red); // Debug.DrawRay(transform.position, forwardShift, Color.green); forwardShift *= Mathf.Sign(Vector3.Dot(transform.forward, forwardShift)) * shipRadius; Vector3 groundNormal = transform.GetGroundNormal(planet, groundDirection, terrainLayer); Plane gravityPlane = new Plane(-gravity, transform.position); Debug.DrawRay(transform.position, groundNormal, Color.cyan); Quaternion rotateToGround = Quaternion.FromToRotation(transform.up, groundNormal); rotateToGround = _rotateToGround = Quaternion.SlerpUnclamped(_rotateToGround, rotateToGround, 30 * Time.fixedDeltaTime); // Debug.Log("groundNormal " + groundNormal + " magnitude " + groundNormal.magnitude + " rotateToGround " + rotateToGround); Vector3 _mouseDirection = Vector3.zero; Vector2 mousePosition = Mouse.current.position.ReadValue(); Ray mouseRay = m_camera.ScreenPointToRay(mousePosition); // Debug.Log("dot gravity groundNormal: " + Vector3.Dot(gravity, groundNormal)); float enter; if (gravityPlane.Raycast(mouseRay, out enter)) { Vector3 hitPoint = mouseRay.GetPoint(enter); _mouseDirection = (hitPoint - transform.position).normalized; _OnDrawGizmos += () => { // Gizmos.DrawSphere(hitPoint, 0.1f); // Gizmos.color = Color.cyan; // CGizmos.DrawPlane(gravityPlane, transform.position, 0.25f * Vector3.one); }; } Plane normalPlane = new Plane(groundNormal, transform.position); Vector3 mouseDirection = Vector3.ProjectOnPlane(_mouseDirection, groundNormal).normalized; _OnDrawGizmos += () => { // Gizmos.color = Color.magenta; // CGizmos.DrawPlane(normalPlane, transform.position, 0.25f * Vector3.one); // Gizmos.color = Color.black; // Gizmos.DrawRay(transform.position, _mouseDirection); // Gizmos.color = Color.yellow; // Gizmos.DrawRay(transform.position, mouseDirection); }; Quaternion rotateToMouseDirection = Quaternion.FromToRotation(transform.forward, mouseDirection); // Debug.Log($"unit length: rotateToMouseDirection {rotateToMouseDirection} rotateToGround {rotateToGround}"); m_rigidbody.MoveRotation( rotateToMouseDirection.normalized * rotateToGround.normalized * m_rigidbody.rotation ); float t = 0; var ctx2 = lastMoves.Get(2); var ctx1 = lastMoves.Get(1); Vector2 move1 = ctx1?.value ?? Vector2.zero; var ctx0 = lastMoves.ElementAtOrDefault(0); Vector2 move0 = ctx0.value; double moveDeltaTime = Time.realtimeSinceStartupAsDouble - ctx0.time; double delay = ctx0.time - (ctx1?.time ?? -1); if ((move1.magnitude == 0 || move0.magnitude == 0) && (delay > delayBeforeStop)) // stop or go { t = (float)moveDeltaTime / accelerationTime; } else // only direction change { t = 1; } float kvelocity = Tooling.GetBezierCubicPoint(Mathf.Clamp01(t), speedCurve).y; if (move0.magnitude == 0) { kvelocity = 1 - kvelocity; } bool same = ctx0.Equals(ctx2); // choose the move direction from the last move or not Vector2 _moveDirection = move0.magnitude == 0 ? move1 // deceleration : move0 // acceleration ; _moveDirection.Normalize(); Resolution resolution = Screen.currentResolution; Ray forwardRay = m_camera.ScreenPointToRay(new Vector2(resolution.width / 2, resolution.height)); if (gravityPlane.Raycast(forwardRay, out enter)) { Vector3 hitPoint = forwardRay.GetPoint(enter); Vector3 mouseForward = (hitPoint - transform.position).normalized; Vector3 moveDirection = Quaternion.FromToRotation(transform.forward, mouseForward) * transform.TransformDirection(_moveDirection.x, 0, _moveDirection.y); const float C = 100; m_rigidbody.velocity = C * moveDirection * kvelocity * moveSpeed * Time.deltaTime; } m_camera.transform.position = transform.position + 25 * -gravity; }