Пример #1
0
        void OnEnable()
        {
            wc = (WheelController)target;

            // Wheel
            tireRadius     = serializedObject.FindProperty("wheel.tireRadius");
            wheelWidth     = serializedObject.FindProperty("wheel.width");
            rimOffset      = serializedObject.FindProperty("wheel.rimOffset");
            wheelMass      = serializedObject.FindProperty("wheel.mass");
            useRimCollider = serializedObject.FindProperty("useRimCollider");
            vehicleSide    = serializedObject.FindProperty("vehicleSide");
            dragForce      = serializedObject.FindProperty("wheel.dragForce");
            //rimRadius = serializedObject.FindProperty("wheel.rimRadius");
            //motorTorque = serializedObject.FindProperty("wheel.motorTorque");
            //brakeTorque = serializedObject.FindProperty("wheel.brakeTorque");

            // Geometry
            camberCurve = serializedObject.FindProperty("wheel.camberCurve");

            // Spring
            maxSpringForce   = serializedObject.FindProperty("spring.maxForce");
            springTravel     = serializedObject.FindProperty("spring.maxLength");
            springForceCurve = serializedObject.FindProperty("spring.forceCurve");

            // Damper
            damperBump        = serializedObject.FindProperty("damper.unitBumpForce");
            damperRebound     = serializedObject.FindProperty("damper.unitReboundForce");
            dampingForceCurve = serializedObject.FindProperty("damper.dampingCurve");


            // Forward friction
            fSlipCoefficient  = serializedObject.FindProperty("fFriction.slipCoefficient");
            fForceCoefficient = serializedObject.FindProperty("fFriction.forceCoefficient");
            fMaxForce         = serializedObject.FindProperty("fFriction.maxForce");

            // Side friction

            sSlipCoefficient  = serializedObject.FindProperty("sFriction.slipCoefficient");
            sForceCoefficient = serializedObject.FindProperty("sFriction.forceCoefficient");
            sMaxForce         = serializedObject.FindProperty("sFriction.maxForce");

            // Scan
            forwardScanResolution    = serializedObject.FindProperty("forwardScanResolution");
            sideToSideScanResolution = serializedObject.FindProperty("sideToSideScanResolution");

            // Misc
            activeFrictionPresetEnum = serializedObject.FindProperty("activeFrictionPresetEnum");
            parentObject             = serializedObject.FindProperty("parent");
            wheelVisual      = serializedObject.FindProperty("wheel.visual");
            wheelNonRotating = serializedObject.FindProperty("wheel.nonRotating");
            dbg = serializedObject.FindProperty("debug");
            scanIgnoreLayers   = serializedObject.FindProperty("scanIgnoreLayers");
            singleRay          = serializedObject.FindProperty("singleRay");
            applyForceToOthers = serializedObject.FindProperty("applyForceToOthers");
        }
Пример #2
0
        /// <summary>
        ///     Calculation of static parameters and creation of rim collider.
        /// </summary>
        public void Initialize(WheelController wc)
        {
            visualIsNull            = visual == null;
            nonRotatingVisualIsNull = nonRotatingVisual == null;

            // Precalculate wheel variables
            inertia = 0.5f * mass * (radius * radius + radius * radius);

            if (rimColliderGO != null || !wc.useRimCollider || visual == null)
            {
                return;
            }

            // Instantiate rim (prevent ground passing through the side of the wheel)
            rimColliderGO      = new GameObject();
            rimColliderGO.name = "RimCollider";
            rimColliderGO.transform.position =
                wc.transform.position + wc.transform.right * (rimOffset * (int)wc.vehicleSide);
            rimColliderGO.transform.parent = wc.transform;
            rimColliderGO.layer            = LayerMask.NameToLayer("Ignore Raycast");

            MeshFilter mf = rimColliderGO.AddComponent <MeshFilter>();

            mf.name      = "Rim Mesh Filter";
            mf.mesh      = GenerateRimColliderMesh(visual.transform);
            mf.mesh.name = "Rim Mesh";

            MeshCollider mc = rimColliderGO.AddComponent <MeshCollider>();

            mc.name   = "Rim MeshCollider";
            mc.convex = true;

            PhysicMaterial material = new PhysicMaterial();

            material.staticFriction  = 0f;
            material.dynamicFriction = 0f;
            material.bounciness      = 0.3f;
            mc.material = material;
        }
Пример #3
0
        public override bool OnInspectorNUI()
        {
            if (!base.OnInspectorNUI())
            {
                return(false);
            }

            float logoHeight = 40f;
            Rect  texRect    = drawer.positionRect;

            texRect.height = logoHeight;
            drawer.DrawEditorTexture(texRect, "Wheel Controller 3D/Editor/logo_wc3d", ScaleMode.ScaleToFit);
            drawer.Space(logoHeight);

            drawer.HorizontalRuler();

            drawer.BeginSubsection("Wheel");
            drawer.Field("vehicleSide");
            drawer.Field("wheel.radius", true, "m");
            drawer.Field("wheel.width", true, "m");
            drawer.Field("wheel.mass", true, "kg");
            drawer.Field("wheel.rimOffset", true, "m");
            drawer.Field("dragTorque", true, "Nm");
            drawer.Field("parent");
            drawer.Field("useRimCollider");
            drawer.EndSubsection();

            drawer.BeginSubsection("Wheel Model");
            drawer.Field("wheel.visual");
            drawer.Field("wheel.visualPositionOffset");
            drawer.Field("wheel.visualRotationOffset");
            drawer.Field("wheel.nonRotatingVisual");
            drawer.EndSubsection();

            drawer.BeginSubsection("Spring");
            drawer.Field("spring.maxForce", true, "Nm");
            if (Application.isPlaying)
            {
                WheelController wc = target as WheelController;
                if (wc != null && wc.vehicleWheelCount > 0)
                {
                    float minRecommended = wc.parentRigidbody.mass * -Physics.gravity.y * 2f / wc.vehicleWheelCount;
                    if (wc.spring.maxForce < minRecommended)
                    {
                        drawer.Info(
                            "MaxForce of Spring is most likely too low for the vehicle mass. Minimum recommended for current configuration is" +
                            $" {minRecommended}N.", MessageType.Warning);
                    }
                }
            }

            if (drawer.Field("spring.maxLength", true, "m").floatValue < Time.fixedDeltaTime * 10f)
            {
                drawer.Info(
                    $"Minimum recommended spring length for Time.fixedDeltaTime of {Time.fixedDeltaTime} is {Time.fixedDeltaTime * 10f}");
            }

            drawer.Field("spring.forceCurve");
            drawer.Info("X: Spring compression [%], Y: Force coefficient");
            drawer.Field("spring.bottomOutForceCoefficient");

            drawer.EndSubsection();

            drawer.BeginSubsection("Damper");
            drawer.Field("damper.bumpForce");
            drawer.Field("damper.reboundForce");
            drawer.Field("damper.curve");
            drawer.Info("X: Spring velocity (normalized) [m/s], Y: Force coefficient (normalized)");
            drawer.Info(
                "Since NVP2 damper curve is using normalized values. Make sure to adjust bump and rebound forces if you are updating from an older version.");
            drawer.EndSubsection();

            drawer.BeginSubsection("Geometry");
            drawer.Field("wheel.camberAtTop", true, "deg");
            drawer.Field("wheel.camberAtBottom", true, "deg");
            drawer.Field("squat");
            drawer.EndSubsection();

            drawer.BeginSubsection("Friction");
            drawer.Field("activeFrictionPreset");
            drawer.EmbeddedObjectEditor(((WheelController)target).activeFrictionPreset, drawer.positionRect);

            drawer.BeginSubsection("Longitudinal");
            drawer.Field("forwardFriction.slipCoefficient", true, "x100 %");
            drawer.Field("forwardFriction.forceCoefficient", true, "x100 %");
            drawer.EndSubsection();

            drawer.BeginSubsection("Lateral");
            drawer.Field("sideFriction.slipCoefficient", true, "x100 %");
            drawer.Field("sideFriction.forceCoefficient", true, "x100 %");
            drawer.EndSubsection();

            drawer.BeginSubsection("Load and Forces");
            drawer.Field("loadGripCurve");
            drawer.Info("X: Tire Load [N], Y: Max Tire Friction Force [N]");
            drawer.Field("maximumTireLoad", true, "Nm");
            drawer.Field("maximumTireGripForce", true, "Nm");
            drawer.EndSubsection();

            drawer.EndSubsection();

            drawer.BeginSubsection("Ground Detection");
            if (!drawer.Field("singleRay").boolValue)
            {
                SerializedProperty longScanRes =
                    drawer.Field("longitudinalScanResolution", !Application.isPlaying);
                SerializedProperty latScanRes =
                    drawer.Field("lateralScanResolution", !Application.isPlaying);
                if (longScanRes.intValue < 5)
                {
                    longScanRes.intValue = 5;
                }

                if (latScanRes.intValue < 1)
                {
                    latScanRes.intValue = 1;
                }

                int rayCount = longScanRes.intValue * latScanRes.intValue;
                drawer.Info($"Ray count: {rayCount}");
            }

            drawer.Field("applyForceToOthers");

            if (!drawer.Field("autoSetupLayerMask").boolValue)
            {
                drawer.Field("layerMask");
                drawer.Info(
                    "Make sure that vehicle's collider layers are unselected in the layerMask, as well as Physics.IgnoreRaycast layer. If not, " +
                    "wheels will collide with vehicle itself sand result in it behaving unpredictably.");
            }

            drawer.EndSubsection();

            drawer.BeginSubsection("Debug Values");
            drawer.Field("forwardFriction.slip", false, null, "Longitudinal Slip");
            drawer.Field("sideFriction.slip", false, null, "Lateral Slip");
            drawer.Field("suspensionForceMagnitude", false);
            drawer.Field("spring.bottomedOut", false);
            drawer.Field("wheel.motorTorque", false);
            drawer.Field("wheel.brakeTorque", false);

            drawer.Space();
            drawer.Field("debug");
            drawer.EndSubsection();

            drawer.EndEditor(this);
            return(true);
        }