public VehicleWheel(  WheelCollider vehicleWheel,
                       WheelComponent wheelComponent,
                       WheelPosition frontRear,
                       WheelPosition leftRight )
 {
     wheelFrontRear = frontRear;
     wheelLeftRight = leftRight;
     checkCurrentWheelState = WheelsOnGround.WHEEL_ON_GROUND;
     mainWheelCollider = vehicleWheel;
     wheelPhysicsComponent = wheelComponent;
     visualWheel = vehicleWheel.GetComponentInChildren<MeshRenderer>( ).transform;
     wheelRadius = ( visualWheel.GetComponent<Renderer>().bounds.size.y / 2 );
     mainWheelCollider.radius = wheelRadius;
     mainWheelCollider.GetGroundHit( out wheelGroundContactPoint );
 }
Example #2
0
        public bool Initialize(WheelComponent wheelComponent, GameObject skidmarkContainer,
                               float minDistance,
                               int surfaceMapCount, int maxMarks, bool persistent, float persistentDistance,
                               float groundOffset, float smoothing, float lowerIntensityThreshold, bool fadeOverDistance, Material fallbackMaterial)
        {
            _targetWheelComponent    = wheelComponent;
            _minSqrDistance          = minDistance * minDistance;
            _maxMarks                = maxMarks;
            _surfaceMapCount         = surfaceMapCount;
            _persistent              = persistent;
            _persistentDistance      = persistentDistance;
            _fadeOverDistance        = !persistent && fadeOverDistance;
            _groundOffset            = groundOffset;
            _smoothing               = smoothing;
            _lowerIntensityThreshold = lowerIntensityThreshold;
            _skidmarkContainer       = skidmarkContainer;
            _fallbackMaterial        = fallbackMaterial;

            _maxTris     = maxMarks * 6;
            _outTriArray = new int[_maxTris];
            _markWidth   = wheelComponent.Width;

            _isInitial           = true;
            _prevSurfaceMapIndex = _surfaceMapIndex;

            GenerateNewSection();
            return(true);
        }
Example #3
0
        public void CalculateCamber()
        {
            if (isSolid && Wheels.Count == 2) // Calculate and set solid axle camber
            {
                WheelComponent leftWheel  = Wheels[0];
                WheelComponent rightWheel = Wheels[1];

                // Center point of imaginary axle
                _position = (leftWheel.wheelController.springTravelPoint +
                             rightWheel.wheelController.springTravelPoint) / 2f;
                _direction = _position - leftWheel.wheelController.springTravelPoint;

                // Calculate camber from the mid point
                float camberAngle = Vector3.SignedAngle(_vc.transform.right, _direction, _vc.transform.forward);
                camberAngle = Mathf.Clamp(camberAngle, -25f, 25f);

                // Set camber
                leftWheel.wheelController.SetCamber(camberAngle);
                rightWheel.wheelController.SetCamber(-camberAngle);
                camberAtBottom = camberAtTop = camberAngle;
            }
            else // Set normal camber
            {
                foreach (WheelComponent wheel in Wheels)
                {
                    wheel.wheelController.SetCamber(camberAtTop, camberAtBottom);
                }
            }
        }
Example #4
0
    private WheelComponent SetWheelComponent(Transform wheel, Transform axle, bool drive, float maxSteer, float pos_y)
    {
        WheelComponent result   = new WheelComponent();
        GameObject     wheelCol = new GameObject(wheel.name + "WheelCollider");



        wheelCol.transform.parent      = transform;
        wheelCol.transform.position    = wheel.position;
        wheelCol.transform.eulerAngles = transform.eulerAngles;
        pos_y = wheelCol.transform.localPosition.y;



        wheelCol.AddComponent(typeof(WheelCollider));


        result.drive    = drive;
        result.wheel    = wheel;
        result.axle     = axle;
        result.collider = wheelCol.GetComponent <WheelCollider>();
        result.pos_y    = pos_y;
        result.maxSteer = maxSteer;
        result.startPos = axle.transform.localPosition;

        return(result);
    }
Example #5
0
        public override bool OnNUI(Rect rect, SerializedProperty property, GUIContent label)
        {
            List <string> options = new List <string> {
                "[no axle]"
            };

            // Try to get vehicle controller from parent property
            vc = property.serializedObject.targetObject as VehicleController;

            if (vc == null)
            {
                selectedIndex = EditorGUI.Popup(rect, "Belongs to", 0, options.ToArray());
                return(false);
            }

            // Find the name and index of currently selected output
            groupIndexProperty = property.FindPropertyRelative("index");

            if (groupIndexProperty == null)
            {
                Debug.LogWarning("Property axleIndex not found.");
                return(false);
            }

            int    axleIndex     = groupIndexProperty.intValue;
            int    selectorIndex = axleIndex + 1;
            string name          = axleIndex >= vc.powertrain.wheelGroups.Count || axleIndex < 0
                ? ""
                : vc.powertrain.wheelGroups[axleIndex].name;

            // Add the names of other powertrain components
            for (int i = 0; i < vc.powertrain.wheelGroups.Count; i++)
            {
                options.Add($"{vc.powertrain.wheelGroups[i].name} [Group {i.ToString()}]");
            }

            // Display dropdown menu
            selectedIndex = EditorGUI.Popup(new Rect(rect.x, rect.y, rect.width, NUISettings.FIELD_HEIGHT),
                                            "Belongs to", selectorIndex, options.ToArray());

            // Display currently selected output
            groupIndexProperty.intValue = selectedIndex - 1;


            if (selectedIndex > 0 && selectedIndex <= vc.powertrain.wheelGroups.Count)
            {
                WheelComponent wheelComponent =
                    SerializedPropertyHelper.GetTargetObjectWithProperty(property) as WheelComponent;
                if (wheelComponent != null)
                {
                    wheelComponent.wheelGroup = vc.powertrain.wheelGroups[selectedIndex - 1];
                }
                else
                {
                    Debug.LogWarning("WheelComponent property not found. Wheel group will not be set.");
                }
            }

            return(true);
        }
Example #6
0
        public void CalculateARB()
        {
            if (Wheels.Count != 2)
            {
                return;
            }

            WheelComponent leftWheel  = Wheels[0];
            WheelComponent rightWheel = Wheels[1];

            // Apply anti roll bar
            if (antiRollBarForce > 0)
            {
                float leftTravel  = leftWheel.SpringTravel;
                float rightTravel = rightWheel.SpringTravel;

                // Cylindrical steel shaft of which ARBs are usually made have ~linear torque vs. angle of twist characteristic
                // for the low twist angle values.
                float springLengthDiff = leftWheel.wheelController.spring.length -
                                         rightWheel.wheelController.spring.length;
                _arbForce = springLengthDiff * antiRollBarForce;

                if (leftWheel.IsGrounded || rightWheel.IsGrounded)
                {
                    // Apply the ARB force at the shock anchor point.
                    _vc.vehicleRigidbody.AddForceAtPosition(leftWheel.ControllerTransform.up * -_arbForce,
                                                            leftWheel.ControllerTransform.position);
                    _vc.vehicleRigidbody.AddForceAtPosition(rightWheel.ControllerTransform.up * _arbForce,
                                                            rightWheel.ControllerTransform.position);
                }
            }
        }
Example #7
0
        public void Initialize(VehicleController vc, WheelComponent wheelComponent)
        {
            _vc             = vc;
            _wheelComponent = wheelComponent;

            if (!vc.groundDetection.IsEnabled || vc.groundDetection.groundDetectionPreset == null)
            {
                return;
            }

            // Initialize particles
            if (vc.groundDetection.groundDetectionPreset.particlePrefab != null)
            {
                particlePrefab = Object.Instantiate(
                    vc.groundDetection.groundDetectionPreset.particlePrefab,
                    wheelComponent.ControllerTransform,
                    true);
                particlePrefab.transform.position = wheelComponent.wheelController.wheel.worldPosition
                                                    - wheelComponent.wheelController.cachedTransform.up * (wheelComponent.wheelController.radius * 0.5f);
                particlePS      = particlePrefab.GetComponent <ParticleSystem>();
                particlePS.name = "SurfaceParticles";

                ParticleSystem.ShapeModule shape = particlePS.shape;
                shape.radius = wheelComponent.Width * 1.5f;

                _shapeModule        = particlePS.shape;
                _shapeModule.radius = wheelComponent.Width;
            }
            else
            {
                Debug.LogWarning("Smoke Prefab is null, wheel slip will not produce particles.");
            }

            // Initialize chunks
            if (vc.groundDetection.groundDetectionPreset.chunkPrefab != null)
            {
                chunkPrefab = Object.Instantiate(
                    vc.groundDetection.groundDetectionPreset.chunkPrefab,
                    wheelComponent.ControllerTransform,
                    true);
                chunkPrefab.transform.position = wheelComponent.wheelController.wheel.worldPosition
                                                 - wheelComponent.wheelController.cachedTransform.up *
                                                 wheelComponent.wheelController.radius
                                                 - wheelComponent.wheelController.cachedTransform.forward *
                                                 (wheelComponent.wheelController.radius * 0.7f);
                chunkPS      = chunkPrefab.GetComponent <ParticleSystem>();
                chunkPS.name = "SurfaceChunks";

                _shapeModule        = chunkPS.shape;
                _shapeModule.radius = wheelComponent.Width;
            }
            else
            {
                Debug.LogWarning("Dust Prefab is null, there will be no surface dust.");
            }

            _initialized = true;
        }
 private void Start ( )
 {
     vehicleWheels = new WheelCollider[ ]{ frontRightWheel, 
                                           frontLeftWheel, 
                                           rearRightWheel, 
                                           rearLeftWheel };
     gearsComponent = new GearsComponent( 6, 180 );
     wheelComponent = new WheelComponent( gameObject );
     engineComponent = gameObject.AddComponent<EngineComponent>( );
     engineComponent.Start( );
     UnityWheelBugFix( );
 }
Example #9
0
        public override void Initialize()
        {
            _wheelCount = vc.Wheels.Count;
            for (int index = 0; index < _wheelCount; index++)
            {
                WheelComponent wheel = vc.Wheels[index];
                AudioSource    a     = wheel.ControllerGO.AddComponent <AudioSource>();
                vc.soundManager.SetAudioSourceDefaults(a, true, true);
                Sources.Add(a);
            }

            AddSourcesToMixer();

            _prevVolume = new float[_wheelCount];
            _prevPitch  = new float[_wheelCount];

            initialized = true;
        }
Example #10
0
        public override bool OnNUI(Rect position, SerializedProperty property, GUIContent label)
        {
            if (!base.OnNUI(position, property, label))
            {
                return(false);
            }

            drawer.Field("groundDetectionPreset");

            GroundDetectionPreset gdPreset =
                ((GroundDetection)(SerializedPropertyHelper.GetTargetObjectOfProperty(property)
                                   as VehicleComponent))?.groundDetectionPreset;

            if (gdPreset != null)
            {
                drawer.EmbeddedObjectEditor(gdPreset, drawer.positionRect);
            }

            drawer.BeginSubsection("Debug Info");
            GroundDetection groundDetection =
                SerializedPropertyHelper.GetTargetObjectOfProperty(drawer.serializedProperty) as GroundDetection;

            if (groundDetection != null && groundDetection.VehicleController != null)
            {
                for (int i = 0; i < groundDetection.VehicleController.powertrain.wheels.Count; i++)
                {
                    WheelComponent wheelComponent = groundDetection.VehicleController.powertrain.wheels[i];
                    if (wheelComponent != null)
                    {
                        drawer.Label($"{wheelComponent.name}: {wheelComponent.surfacePreset?.name} SurfacePreset");
                    }
                }
            }
            else
            {
                drawer.Info("Debug info is available only in play mode.");
            }

            drawer.EndSubsection();


            drawer.EndProperty();
            return(true);
        }
Example #11
0
    private WheelComponent SetWheelComponent(Transform wheel, Transform axle, bool drive, float maxSteer, float pos_y)
    {
        WheelComponent result   = new WheelComponent();
        GameObject     wheelCol = new GameObject(wheel.name + "WheelCollider");



        wheelCol.transform.parent      = transform;
        wheelCol.transform.position    = wheel.position;
        wheelCol.transform.eulerAngles = transform.eulerAngles;
        pos_y = wheelCol.transform.localPosition.y;



        wheelCol.AddComponent(typeof(WheelCollider));


        result.drive = drive;
        result.wheel = wheel;
        result.axle  = axle;

        result.collider        = wheelCol.GetComponent <WheelCollider>();
        result.collider.radius = bikeWheels.setting.Radius;
        result.collider.center = bikeWheels.setting.WheelCenter;
        result.pos_y           = pos_y;
        result.maxSteer        = maxSteer;
        result.startPos        = axle.transform.localPosition;
        if (!drive)
        {
            // var spring = new JointSpring();
            // spring.spring = 35000;
            // spring.damper = 3500;
            // spring.targetPosition = 0.7f;
            // result.collider.suspensionSpring = spring;
        }

        // Physics.IgnoreCollision(result.collider, body);
        // Physics.IgnoreCollision(result.collider, body);
        return(result);
    }
    private WheelComponent SetWheelComponent(Transform wheel, Transform axle, bool drive, float maxSteer, float pos_y)
    {
        WheelComponent result   = new WheelComponent();
        GameObject     wheelCol = new GameObject(wheel.name + "WheelCollider");

        wheelCol.transform.parent      = transform;
        wheelCol.transform.position    = wheel.position;
        wheelCol.transform.eulerAngles = transform.eulerAngles;
        pos_y = wheelCol.transform.localPosition.y;

        wheel.gameObject.AddComponent <WheelCollider>();
        WheelCollider col = (WheelCollider)wheelCol.AddComponent(typeof(WheelCollider));
        //TODO: rewrite if we got some problem with wheels size
        //col.transform.localScale = wheel.localScale;

        float cof;

        if (wheel.parent.localScale.x == 1f)
        {
            cof = wheel.localScale.x;
        }
        else
        {
            cof = wheel.parent.localScale.x;
        }

        col.radius = wheel.GetComponent <WheelCollider>().radius *cof;
        Destroy(wheel.transform.GetComponent <WheelCollider>());

        result.drive    = drive;
        result.wheel    = wheel;
        result.axle     = axle;
        result.collider = wheelCol.GetComponent <WheelCollider>();
        result.pos_y    = pos_y;
        result.maxSteer = maxSteer;
        result.startPos = wheelCol.transform.localPosition;

        return(result);
    }
Example #13
0
        public float BrakeTorqueModifier()
        {
            if (!Active)
            {
                return(1f);
            }

            active        = false;
            slipThreshold = slipThreshold < 0 ? 0 : slipThreshold > 1 ? 1 : slipThreshold;

            // Prevent ABS from working in reverse and at low speeds
            if (vc.ForwardVelocity < lowerSpeedThreshold)
            {
                return(1f);
            }

            if (vc.brakes.Active && !vc.powertrain.engine.revLimiterActive && vc.input.Handbrake < 0.1f)
            {
                for (int index = 0; index < vc.Wheels.Count; index++)
                {
                    WheelComponent wheel = vc.Wheels[index];
                    if (!wheel.IsGrounded)
                    {
                        continue;
                    }

                    float longSlip = wheel.LongitudinalSlip;
                    if (longSlip > 0 && longSlip > slipThreshold)
                    {
                        active = true;
                        ABSActive.Invoke();
                        return(0.01f);
                    }
                }
            }

            return(1f);
        }
Example #14
0
 void Start()
 {
     wheelComponent = SetWheelComponent(wheel, axle, true, 0, axle.localPosition.y);
 }
    private WheelComponent SetWheelComponent(Transform wheel, Transform axle, bool drive, float maxSteer, float pos_y)
    {

        WheelComponent result = new WheelComponent();
        GameObject wheelCol = new GameObject(wheel.name + "WheelCollider");

        wheelCol.transform.parent = transform;
        wheelCol.transform.position = wheel.position;
        wheelCol.transform.eulerAngles = transform.eulerAngles;
        pos_y = wheelCol.transform.localPosition.y;

        wheel.gameObject.AddComponent<WheelCollider>();
        WheelCollider col = (WheelCollider)wheelCol.AddComponent(typeof(WheelCollider));
		//TODO: rewrite if we got some problem with wheels size
        //col.transform.localScale = wheel.localScale;
		float cof;
		if(wheel.parent.localScale.x == 1f)
			cof = wheel.localScale.x;
		else
			cof = wheel.parent.localScale.x;

        col.radius = wheel.GetComponent<WheelCollider>().radius * cof;
        Destroy(wheel.transform.GetComponent<WheelCollider>());

        result.drive = drive;
        result.wheel = wheel;
        result.axle = axle;
        result.collider = wheelCol.GetComponent<WheelCollider>();
        result.pos_y = pos_y;
        result.maxSteer = maxSteer;
        result.startPos = wheelCol.transform.localPosition;

        return result;
    }
Example #16
0
        public override void Update()
        {
            if (!Active)
            {
                return;
            }

            for (int i = 0; i < _wheelCount; i++)
            {
                WheelComponent wheelComponent = vc.Wheels[i];
                SurfacePreset  surfacePreset  = wheelComponent.surfacePreset;

                float newVolume = 0;
                float newPitch  = basePitch;

                if (wheelComponent.IsGrounded && surfacePreset != null && surfacePreset.playSurfaceSounds)
                {
                    if (surfacePreset.surfaceSoundClip != null)
                    {
                        AudioSource source = Sources[i];

                        if (!source.isPlaying)
                        {
                            source.Play();
                        }

                        if (source.clip != surfacePreset.surfaceSoundClip)
                        {
                            // Change skid clip
                            source.clip = surfacePreset.surfaceSoundClip;
                            source.time = Random.Range(0f, surfacePreset.surfaceSoundClip.length);
                            source.time = Random.Range(0f, source.clip.length);
                        }

                        float surfaceModifier = 1f;
                        if (surfacePreset.slipSensitiveSurfaceSound)
                        {
                            surfaceModifier = wheelComponent.NormalizedLateralSlip / vc.longitudinalSlipThreshold;
                            surfaceModifier = surfaceModifier < 0 ? 0 : surfaceModifier > 1 ? 1 : surfaceModifier;
                        }

                        float speedCoeff = vc.Speed / 20f;
                        speedCoeff = speedCoeff < 0 ? 0 : speedCoeff > 1 ? 1 : speedCoeff;

                        // Change surface volume and pitch
                        newVolume = surfacePreset.surfaceSoundVolume * surfaceModifier * speedCoeff;
                        newVolume = newVolume < 0 ? 0 : newVolume > 1 ? 1 : newVolume;
                        newVolume = Mathf.Lerp(_prevVolume[i], newVolume, vc.deltaTime * 12f);

                        newPitch = surfacePreset.surfaceSoundPitch * 0.5f + speedCoeff;
                    }
                }
                else
                {
                    newVolume = Mathf.Lerp(_prevVolume[i], 0, vc.deltaTime * 12f);
                    newPitch  = Mathf.Lerp(_prevPitch[i], basePitch, vc.deltaTime * 12f);
                }

                SetVolume(newVolume, i);
                SetPitch(newPitch, i);

                _prevVolume[i] = newVolume;
                _prevPitch[i]  = newPitch;
            }
        }
 public void Start ( )
 {
     vehiclePhysics = GetComponent<VehiclePhysics>( );
     wheelComponent = vehiclePhysics.wheelComponent;
 }
Example #18
0
        public override void Update()
        {
            if (!Active)
            {
                return;
            }

            // Check if can be updated
            if (vc.groundDetection == null || !vc.groundDetection.IsEnabled)
            {
                return;
            }

            // Check for added/removed wheels and re-init if needed
            int wheelCount = vc.powertrain.wheels.Count;

            if (prevWheelCount != wheelCount)
            {
                initialized = false;
                Initialize();
            }

            prevWheelCount = wheelCount;

            // Update skidmarks
            Debug.Assert(skidmarkGenerators.Count == vc.powertrain.wheels.Count,
                         "Skidmark generator count must equal wheel count");

            int n = skidmarkGenerators.Count;

            for (int i = 0; i < n; i++)
            {
                WheelComponent wheelComponent = vc.powertrain.wheels[i];
                SurfacePreset  surfacePreset  = wheelComponent.surfacePreset;
                if (surfacePreset == null || !surfacePreset.drawSkidmarks)
                {
                    continue;
                }

                bool surfaceMapIsNull = surfacePreset == null;

                int surfaceMapIndex = -1;
                if (!surfaceMapIsNull)
                {
                    surfaceMapIndex = wheelComponent.surfaceMapIndex;
                }

                float intensity = 1f;
                if (surfaceMapIndex >= 0)
                {
                    float latFactor = wheelComponent.NormalizedLateralSlip;
                    latFactor = latFactor < vc.lateralSlipThreshold ? 0 : latFactor - vc.lateralSlipThreshold;
                    float lonFactor = wheelComponent.NormalizedLongitudinalSlip;
                    lonFactor = lonFactor < vc.lateralSlipThreshold ? 0 : lonFactor - vc.lateralSlipThreshold;

                    float slipIntensity = latFactor + lonFactor;
                    float weightCoeff   = wheelComponent.wheelController.wheel.load * 2f /
                                          wheelComponent.wheelController.maximumTireLoad;
                    weightCoeff    = weightCoeff <0 ? 0f : weightCoeff> 1f ? 1f : weightCoeff;
                    slipIntensity *= wheelComponent.surfacePreset.slipFactor * weightCoeff;

                    intensity = wheelComponent.surfacePreset.skidmarkBaseIntensity + slipIntensity;
                    intensity = intensity > 1f ? 1f : intensity < 0f ? 0f : intensity;
                }

                intensity *= globalSkidmarkIntensity;
                intensity  = intensity <0f ? 0f : intensity> maxSkidmarkAlpha ? maxSkidmarkAlpha : intensity;

                float albedoIntensity = 0f;
                float normalIntensity = 0f;

                // TODO - check that fallback surface preset is not null

                skidmarkGenerators[i].Update(surfaceMapIndex, intensity, albedoIntensity, normalIntensity,
                                             wheelComponent.wheelController.pointVelocity, vc.fixedDeltaTime);
            }
        }
Example #19
0
 public void AddWheel(WheelComponent wheel)
 {
     Wheels.Add(wheel);
     wheel.wheelGroup = this;
 }
Example #20
0
        public override void Update()
        {
            if (!Active)
            {
                return;
            }

            float newVolume = 0;
            float newPitch  = basePitch;

            if (vc.groundDetection != null)
            {
                for (int i = 0; i < _wheelCount; i++)
                {
                    WheelComponent wheelComponent = vc.Wheels[i];
                    SurfacePreset  surfacePreset  = wheelComponent.surfacePreset;

                    bool hasSlip = wheelComponent.HasLateralSlip || wheelComponent.HasLongitudinalSlip;
                    if (wheelComponent.IsGrounded && surfacePreset != null && surfacePreset.playSkidSounds && hasSlip)
                    {
                        float slipPercent = wheelComponent.NormalizedLateralSlip +
                                            wheelComponent.NormalizedLongitudinalSlip;
                        slipPercent = slipPercent < 0 ? 0 : slipPercent > 1 ? 1 : slipPercent;

                        if (surfacePreset.skidSoundClip != null)
                        {
                            AudioSource source = Sources[i];

                            if (!source.isPlaying)
                            {
                                source.Play();
                            }

                            if (source.clip != surfacePreset.skidSoundClip)
                            {
                                // Change skid clip
                                source.clip = surfacePreset.skidSoundClip;
                                source.time = Random.Range(0f, surfacePreset.skidSoundClip.length);
                                source.time = Random.Range(0f, source.clip.length);
                            }

                            float absAngVel = wheelComponent.angularVelocity < 0
                                ? -wheelComponent.angularVelocity
                                : wheelComponent.angularVelocity;
                            float speedCoeff = vc.Speed / 3f + absAngVel / 20f;
                            speedCoeff = speedCoeff > 1f ? 1f : speedCoeff;
                            newVolume  = slipPercent * surfacePreset.skidSoundVolume * speedCoeff;
                            newVolume  = Mathf.Lerp(_prevVolume[i], newVolume, vc.deltaTime * 12f);

                            float loadCoeff = wheelComponent.wheelController.wheel.load /
                                              wheelComponent.wheelController.maximumTireLoad;
                            loadCoeff = loadCoeff > 1f ? 1f : loadCoeff;
                            newPitch  = surfacePreset.skidSoundPitch + loadCoeff * 0.3f;
                            newPitch  = Mathf.Lerp(_prevPitch[i], newPitch, vc.deltaTime * 18f);
                        }
                    }
                    else
                    {
                        newVolume = 0;
                        newPitch  = basePitch;
                    }

                    SetVolume(newVolume, i);
                    SetPitch(newPitch, i);

                    _prevVolume[i] = newVolume;
                    _prevPitch[i]  = newPitch;
                }
            }
        }
Example #21
0
 public void RemoveWheel(WheelComponent wheel)
 {
     Wheels.Remove(wheel);
 }