Example #1
0
    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;
    }