コード例 #1
0
    private void FixedUpdate()
    {
        transform.position = target.transform.position;
        camRig.velocity    = playerRig.velocity;

        //transform.rotation = target.transform.rotation;
        transform.rotation = SmoothDamp.Rotate(transform.rotation, target.transform.rotation, 1f, .5f);
    }
コード例 #2
0
    private void RunFlightModelLinear(float deltaTime)
    {
        // Gravity can speed the plane up in a dive, or slow it in a climb.
        Vector3 gravityForce = Physics.gravity * Mass;

        // Engines provide thrust forwards.
        float   thrust      = FlightInput.Reheat ? ReheatThrust : FlightInput.Throttle * MilThrust;
        Vector3 thrustForce = transform.forward * thrust;

        // Drag holds the plane back the faster it goes, until it eventually reaches an equilibrium
        // between the drag force and thrust at the plane's top speed.
        float linearDrag = Mathf.Pow(Speed, 2f) * Drag;
        float totalDrag  = linearDrag;

        // Extending things from the plane increases drag.
        if (Brakes.ExtendState > Mathf.Epsilon)
        {
            totalDrag += linearDrag * Brakes.DragMultiplier * Brakes.ExtendState;
        }
        if (Gear.ExtendState > Mathf.Epsilon)
        {
            totalDrag += linearDrag * Gear.DragMultiplier * Gear.ExtendState;
        }
        if (Flaps.ExtendState > Mathf.Epsilon)
        {
            totalDrag += linearDrag * Flaps.DragMultiplier * Flaps.ExtendState;
        }

        Vector3 dragForce = -transform.forward * totalDrag;

        // Induced drag decreases speed when turning. The higher the angle of attack, the more drag.
        var     inducedAOA       = Vector3.Angle(transform.forward, VelocityDirection);
        Vector3 inducedDragForce = -transform.forward * Mathf.Pow(Speed, 2f) * InducedDrag * inducedAOA;

        // Consider the forces only as they affect forward speed as a simplification of physics.
        var acceleration = (gravityForce + thrustForce + dragForce + inducedDragForce) / Mass;
        var forwardAccel = Vector3.Dot(transform.forward, acceleration);

        Speed += forwardAccel * deltaTime;

        // Stalling will turn the velocity vector down towards the ground.
        var stallAOA = Maths.Remap(DynamicStallSpeed, DynamicStallSpeed * 1.5f, StallAOA, 0f, Speed);

        // The direction that the velocity vector would ideally face. This includes things that
        // affect it such as stalling, which lowers the velocity vector towards the ground.
        var targetVelocityVector = transform.forward;

        targetVelocityVector = Vector3.RotateTowards(targetVelocityVector, Vector3.down, stallAOA * Mathf.Deg2Rad, 0f);

        // Change the direction of the velocity smoothly so that some alpha gets generated.
        VelocityDirection = SmoothDamp.Move(
            VelocityDirection, targetVelocityVector,
            Responsiveness, deltaTime);

        Velocity            = VelocityDirection * Speed;
        transform.position += Velocity * Scale * deltaTime;
    }
コード例 #3
0
    private void FixedUpdate()
    {
        var targetVolume = Mathf.Lerp(MinVolume, MaxVolume, ship.Pilot.Throttle);

        smoothVolume = SmoothDamp.Move(audio.volume, targetVolume, 0.5f, Time.fixedDeltaTime);
        audio.volume = smoothVolume;

        var targetPitch = Mathf.Lerp(MinPitch, MaxPitch, ship.Pilot.Throttle);

        smoothPitch = SmoothDamp.Move(audio.pitch, targetPitch, 0.5f, Time.fixedDeltaTime);
        audio.pitch = smoothPitch;
    }
コード例 #4
0
    private void RunFlightModelRotations(float deltaTime)
    {
        PitchG         = Maths.CalculatePitchG(transform, Velocity, PitchRate);
        PitchGSmoothed = SmoothDamp.Move(PitchGSmoothed, PitchG, 3f, deltaTime);

        // The stall speed affects low speed handling. The lower the stall speed, the more control
        // the plane has at low speeds. A high stall speed results in not only poor control at low
        // speed, but also requires more speed to generate the maximum turn rate.
        var controlAuthority = GetControlAuthority();

        // Limit pitch input based on G. This is a reactive system. At low framerates (e.g. 10) the
        // sample rate will cause oscillations similar to RPMs bouncing off a rev limiter. A better
        // way to do this would be to pre-calculate a max turn rate based for a given G.
        float gLerp = PitchG > 0
            ? Mathf.InverseLerp(MaxG, MaxG + MaxG * .1f, PitchG)
            : Mathf.InverseLerp(-MinG, -MinG - MinG * .1f, PitchG);
        var gLimiter = Mathf.Lerp(0f, 1f, 1f - gLerp);

        // For each axis, generate a rotation and then damp it to create smooth motion.
        var targetPitch = FlightInput.Pitch * MaxPitchRate * gLimiter * controlAuthority;

        PitchRate = SmoothDamp.Move(PitchRate, targetPitch, PitchResponse, deltaTime);
        var pitchRotation = Quaternion.AngleAxis(PitchRate * deltaTime, Vector3.right);

        var targetYaw = FlightInput.Yaw * MaxYawRate * controlAuthority;

        YawRate = SmoothDamp.Move(YawRate, targetYaw, YawResponse, deltaTime);
        var yawRotation = Quaternion.AngleAxis(YawRate * deltaTime, Vector3.up);

        var targetRoll = FlightInput.Roll * MaxRollRate * controlAuthority;

        RollRate = SmoothDamp.Move(RollRate, targetRoll, RollResponse, deltaTime);
        var rollRotation = Quaternion.AngleAxis(-RollRate * deltaTime, Vector3.forward);

        transform.localRotation *= pitchRotation * rollRotation * yawRotation;

        // When stalling, the plane pitches down towards the ground.
        var stallRate = GetStallRate();

        if (stallRate > 0f)
        {
            // Generate stall rotation.
            var stallAxis = Vector3.Cross(transform.forward, Vector3.down);
            transform.rotation = Quaternion.AngleAxis(stallRate * deltaTime, stallAxis) * transform.rotation;
        }
    }
コード例 #5
0
    public void Update(Pilot pilot, ref ShipSpecs specs)
    {
        if (isDestroyed)
        {
            return;
        }

        rigidbody.AddRelativeTorque(
            pilot.Pitch * specs.Engine.Torque * Multiplier,
            pilot.Yaw * specs.Engine.Torque * Multiplier,
            -pilot.Roll * specs.Engine.Torque * Multiplier);

        // Ramp up/down speed for smoother acceleration.
        smoothThrottle = SmoothDamp.Move(
            smoothThrottle,
            pilot.Throttle,
            specs.Engine.Accel,
            Time.fixedDeltaTime);

        rigidbody.AddRelativeForce(
            Vector3.forward * specs.Engine.Thrust * Multiplier * smoothThrottle,
            ForceMode.Force);
    }
コード例 #6
0
    private void RunGroundHandling(float deltaTime)
    {
        var hitSomething = Physics.Raycast(
            origin: transform.position,
            direction: -transform.up,
            hitInfo: out RaycastHit hitInfo,
            maxDistance: GearHeight * 2f,
            layerMask: CollisionMask);

        // Panic early escape in something weird happened.
        // Might trigger if the player drove off a sheer cliff?
        if (!hitSomething)
        {
            IsGrounded = false;
            return;
        }

        Vector3 thrustForce        = CalculateThrustForce();
        Vector3 dragForce          = CalculateDragForce();
        Vector3 gravityForce       = CalculateGravityForce();
        var     accelerationVector = (thrustForce + dragForce + gravityForce) / Mass;

        if (accelerationVector.y <= 0f)
        {
            // If the velocity vector is still pointing down, the plane is still grounded.
            // Care only about the speed/acceleration in the forward direction. (No slipping.)
            var acceleration = Vector3.Dot(transform.forward, accelerationVector);
            Speed += acceleration * deltaTime;

            // Brakes get an extra boost to being stopping because of wheel brakes.
            Speed = Mathf.MoveTowards(Speed, 0f, Brakes.ExtendState * 5f * deltaTime);

            // Stalling will turn the velocity vector down towards the ground.
            var stallAOA = Maths.Remap(DynamicStallSpeed, DynamicStallSpeed * 1.5f, StallAOA, 0f, Speed);

            // The direction that the velocity vector would ideally face. This includes things that
            // affect it such as stalling, which lowers the velocity vector towards the ground.
            var targetVelocityVector = transform.forward;
            targetVelocityVector = Vector3.RotateTowards(targetVelocityVector, Vector3.down, stallAOA * Mathf.Deg2Rad, 0f);

            if (targetVelocityVector.y < 0f)
            {
                // Velocity still isn't going up, so stay ground clamped.
                targetVelocityVector.y = 0f;
                Velocity          = targetVelocityVector * Speed;
                VelocityDirection = targetVelocityVector;

                transform.position += Velocity * Scale * deltaTime;

                // Handle rotation. Re-uses a lot of the same code as the flying stuff.
                PitchG         = 1f;
                PitchGSmoothed = 1f;

                // Pitching uses the same control authority as in flight to simulate aerodynamics.
                var controlAuthority = GetControlAuthority();

                // Same pitching code as when in flight, but without the stalling rotation stuff.
                var targetPitch = FlightInput.Pitch * MaxPitchRate * controlAuthority;
                var stallRate   = GetStallRate() * deltaTime;
                PitchRate         = SmoothDamp.Move(PitchRate + stallRate, targetPitch, PitchResponse, deltaTime);
                LandedPitchAngle += PitchRate * deltaTime;

                // Prevent pitch down into the ground while grounded. The way the rotation math
                // works out, negative values for pitch are what result in a pitch up.
                LandedPitchAngle = Mathf.Clamp(LandedPitchAngle, -30f, 0f);
                var pitchRotation = Quaternion.AngleAxis(LandedPitchAngle, Vector3.right);

                // Nosewheel steering allows the plane to be turned while on the ground.
                // Blend roll and yaw so that roll can be used to steer on the ground like in old games.
                // You'd probably want this to be optional in a real game.
                const float NosewheelTurnRate         = 45f;
                const float NosewheelSteeringResponse = 3f;
                float       nosewheelSteeringYawRate  = Speed >= 5f
                    ? Mathf.InverseLerp(45f, 15f, Speed)
                    : Mathf.InverseLerp(0f, 5f, Speed);

                // Allow for some yaw authority after nosewheel steering reaches zero power so that
                // adjustments can continue to be made at high speed. In real life, this would be
                // caused by the rudder rather than any kind of steering system. This specific
                // method has the side effect of allowing the plane to turn in place while stopped,
                // but I won't tell if you don't.
                float maxYawRate = Mathf.Max(
                    NosewheelTurnRate * 0.1f,
                    nosewheelSteeringYawRate * NosewheelTurnRate);

                var blendedYawInput = Mathf.Clamp(FlightInput.Yaw + FlightInput.Roll, -1f, 1f);
                var targetYaw       = blendedYawInput * maxYawRate;

                YawRate = SmoothDamp.Move(YawRate, targetYaw, NosewheelSteeringResponse, deltaTime);
                var yawRotation = Quaternion.AngleAxis(YawRate * deltaTime, Vector3.up);

                // This SERIOUSLY breaks down if the ground beneath the player isn't flat. To fix
                // this requires some fancy vector math that I don't have a handle on quite yet.
                var flattenedForward = GetFlattenedForward();
                transform.rotation       = Quaternion.LookRotation(flattenedForward, hitInfo.normal);
                transform.localRotation *= yawRotation * pitchRotation;
            }
            else
            {
                // Acceleration vector now points skywards. Take off!
                IsGrounded = false;
                Debug.Log($"{name}: Took off!");
            }
        }
        else
        {
            // The velocity vector is starting to point upwards, which means the plane wants to go
            // up and the plane has taken off.
            IsGrounded = false;
        }
    }
コード例 #7
0
    private void LateUpdate()
    {
        if (!_active)
        {
            return;
        }

        // スピードダウン
        if (Input.GetButtonDown(InputPredefined.JOYSTICK_LEFT_PRESS) || Input.GetKeyDown(KeyCode.F))
        {
            switch (_speedMode)
            {
            case SpeedMode.Default:
                _speedMode = SpeedMode.Slow;
                break;

            case SpeedMode.Turbo:
                _speedMode = SpeedMode.Default;
                break;

            default:
                break;
            }
        }

        // スピードアップ
        if (Input.GetButtonDown(InputPredefined.JOYSTICK_RIGHT_PRESS) || Input.GetKeyDown(KeyCode.G))
        {
            switch (_speedMode)
            {
            case SpeedMode.Default:
                _speedMode = SpeedMode.Turbo;
                break;

            case SpeedMode.Slow:
                _speedMode = SpeedMode.Default;
                break;

            default:
                break;
            }
        }

        _mousePosDelta = Input.mousePosition - _prevMousePos;
        _prevMousePos  = Input.mousePosition;
        _nextPosition  = transform.position;

        // 速度の設定
        var movingSpeed   = _movingSensitivity;
        var hoveringSpeed = _hoveringSensitivity;

        if (Input.GetKey(KeyCode.LeftShift))
        {
            _speedMode = SpeedMode.Turbo;
        }
        else
        {
            _speedMode = SpeedMode.Default;
        }

        switch (_speedMode)
        {
        case SpeedMode.Slow:
            movingSpeed   = _movingSensitivity * 0.5f;
            hoveringSpeed = _hoveringSensitivity * 0.5f;
            break;

        case SpeedMode.Default:
            movingSpeed   = _movingSensitivity * 1.0f;
            hoveringSpeed = _hoveringSensitivity * 1.0f;
            break;

        case SpeedMode.Turbo:
            movingSpeed   = _movingSensitivity * 2.0f;
            hoveringSpeed = _hoveringSensitivity * 2.0f;
            break;

        default:
            break;
        }
        movingSpeed *= transform.lossyScale.x;

        var smoothness = _smoothMode == SmoothMode.Smooth ? _smoothness : _noSmoothness;

        var deltaTime = Time.deltaTime;

        var rightDir   = transform.right;
        var upDir      = _axisMode == AxisMode.Global ? Vector3.up : transform.up;
        var forwardDir = _axisMode == AxisMode.Global ? Vector3.ProjectOnPlane(transform.forward, Vector3.up) : transform.forward;

        var leftJoystick = new Vector2(Input.GetAxis(InputPredefined.HORIZONTAL_LEFT),
                                       Input.GetAxis(InputPredefined.VERTICAL_LEFT));
        var rightJoystick = new Vector2(Input.GetAxis(InputPredefined.HORIZONTAL_RIGHT),
                                        Input.GetAxis(InputPredefined.VERTICAL_RIGHT));

        var trigger = 0f;

        if (Input.GetAxis(InputPredefined.TRIGGER_LEFT) > 0f)
        {
            trigger = -_hoveringSensitivity * (Input.GetAxis(InputPredefined.TRIGGER_LEFT) + 1) / 2.0f;
        }
        else if (Input.GetAxis(InputPredefined.TRIGGER_RIGHT) > 0f)
        {
            trigger = _hoveringSensitivity * (Input.GetAxis(InputPredefined.TRIGGER_RIGHT) + 1) / 2.0f;
        }

        if (Input.GetMouseButton(1) || Input.GetKey(KeyCode.LeftAlt) && Input.GetMouseButton(0) || leftJoystick.sqrMagnitude > 0f || rightJoystick.sqrMagnitude > 0f || trigger != 0f)
        {
            // キーボード移動
            if (Input.GetKey(KeyCode.W))
            {
                _nextPosition = _nextPosition + forwardDir * movingSpeed;
            }

            if (Input.GetKey(KeyCode.A))
            {
                _nextPosition = _nextPosition - rightDir * movingSpeed;
            }

            if (Input.GetKey(KeyCode.S))
            {
                _nextPosition = _nextPosition - forwardDir * movingSpeed;
            }

            if (Input.GetKey(KeyCode.D))
            {
                _nextPosition = _nextPosition + rightDir * movingSpeed;
            }

            if (Input.GetKey(KeyCode.Q))
            {
                _nextPosition = _nextPosition - upDir * hoveringSpeed;
            }

            if (Input.GetKey(KeyCode.E))
            {
                _nextPosition = _nextPosition + upDir * hoveringSpeed;
            }

            // コントローラー移動
            _nextPosition += rightDir * leftJoystick.x * movingSpeed + forwardDir * leftJoystick.y * movingSpeed + upDir * trigger * movingSpeed;

            // マウス回転
            _elapsedAngles.y += Input.GetAxis(InputPredefined.MOUSE_X) * _rotationSensitivity;
            _elapsedAngles.x += -Input.GetAxis(InputPredefined.MOUSE_Y) * _rotationSensitivity;

            // コントローラー回転
            _elapsedAngles.y += rightJoystick.x * _rotationSensitivity;
            _elapsedAngles.x += -rightJoystick.y * _rotationSensitivity;

            transform.localRotation = SmoothDamp.Pow(transform.localRotation,
                                                     Quaternion.Euler(
                                                         new Vector3(_elapsedAngles.x, _elapsedAngles.y, 0f)), smoothness, deltaTime);
        }
        else if (Input.GetMouseButton(2))
        {
            var mouseDelta = _mousePosDelta;
            _nextPosition -= rightDir * mouseDelta.x * movingSpeed * 0.1f;
            _nextPosition -= upDir * mouseDelta.y * movingSpeed * 0.1f;
            //Debug.Log("mouseDelta : " + mouseDelta);
        }

        if (Input.mousePosition.x < Screen.width && Input.mousePosition.x > 0 && Input.mousePosition.y < Screen.height && Input.mousePosition.y > 0)
        {
            // マウスホイール前後移動
            _nextPosition += forwardDir * Input.GetAxis(InputPredefined.MOUSE_SCROLLWHEEL) * movingSpeed * _mouseWheelSensitivity;
        }

        transform.position = SmoothDamp.Pow(transform.position, _nextPosition, smoothness, deltaTime);

        // ズーム
        if (Input.GetKey(KeyCode.C) || Input.GetButton(InputPredefined.BUMPER_RIGHT_PRESS))
        {
            _cam.fieldOfView = SmoothDamp.Pow(_cam.fieldOfView, _defaultFov * 0.5f, 0.01f, deltaTime);
        }
        else if (Input.GetKey(KeyCode.Z) || Input.GetButton(InputPredefined.BUMPER_LEFT_PRESS))
        {
            _cam.fieldOfView = SmoothDamp.Pow(_cam.fieldOfView, _defaultFov * 1.5f, 0.01f, deltaTime);
        }
        else
        {
            _cam.fieldOfView = SmoothDamp.Pow(_cam.fieldOfView, _defaultFov, 0.01f, deltaTime);
        }
    }