Пример #1
0
 void Start()
 {
     Rd = Road.Instance;
     AdjustedTurninXSec = Road.Instance.XSecs[0];
     _playerGPS         = DrivingPlayManager.Current.PlayerCarManager.Gps;
     _rb = GetComponent <Rigidbody>();
 }
Пример #2
0
    public static XSec CalcXSecPerp(int PathId, int RoadWidth)
    {
        XSec       rtn = new XSec(PathId);
        BezierLine Bez = BezierLine.Instance;
        Vector3    Path3d;

        if (PathId == Bez.Path.Count)
        {
            Path3d = Bez.CtrlPts[Bez.CtrlPts.Count - 2].Pos;
        }
        else
        {
            Path3d = Bez.Path[PathId];
        }
        Vector2 Path2d  = Convert2d(Path3d);
        Vector2 Perp1   = Perpndclr(PathId);
        Vector2 KerbR2d = Path2d + Perp1 * RoadWidth;
        Vector2 KerbL2d = Path2d - Perp1 * RoadWidth;

        Vector3 KerbR = new Vector3(KerbR2d.x, Path3d.y, KerbR2d.y);
        Vector3 KerbL = new Vector3(KerbL2d.x, Path3d.y, KerbL2d.y);


        rtn.TerrainL = (KerbL - Path3d) * 1.3f + Path3d;         //Here's where ther terrain is slightly wider than the road
        rtn.TerrainR = (KerbR - Path3d) * 1.3f + Path3d;         //Here's where ther terrain is slightly wider than the road
        rtn.KerbL    = KerbL;
        rtn.KerbR    = KerbR;
        rtn.MidPt    = Path3d;
        return(rtn);
    }
Пример #3
0
 public void Encode(XSec X)
 {
     Idx      = X.Idx;
     KerbL    = new Vector3Serial(X.KerbL);
     KerbR    = new Vector3Serial(X.KerbR);
     TerrainL = new Vector3Serial(X.TerrainL);
     TerrainR = new Vector3Serial(X.TerrainR);
     MidPt    = new Vector3Serial(X.MidPt);
 }
Пример #4
0
 public void AddXSecs(int segCount)
 {
     XSecs = new List <XSec>();
     for (int i = 0; i < segCount; i++)
     {
         XSec X = new XSec(Road.Instance.XSecs.Count);
         Road.Instance.XSecs.Add(X);
         //this.XSecs.Add(X);
     }
 }
Пример #5
0
    public XSec Decode()
    {
        XSec rtn = new XSec(Idx);

        rtn.KerbL    = KerbL.V3;
        rtn.KerbR    = KerbR.V3;
        rtn.TerrainL = TerrainL.V3;
        rtn.TerrainR = TerrainR.V3;
        rtn.MidPt    = MidPt.V3;
        return(rtn);
    }
Пример #6
0
    void CalcBrakePoint()
    {
        //Accel coeffs a,b,c Brake Coeffs f,g,h
        float a, b, c, f, g, h;
        float St           = _nextBend.Speed;
        float DistToTurnin = Vector3.Distance(transform.position, AdjustedTurninPt);

        switch (_gps.RoadMat)
        {
        case "Dirt": a = 0.125f; b = 0f; break;

        case "DirtyRoad": a = 0.2764f; b = -2.4993f; break;

        case "Washboard": a = 0.1606f; b = -1.0945f; break;

        case "Tarmac": a = 0.1070f; b = -0.2337f; break;

        default: a = 0.3236f; b = -2.1428f; break;
        }
        switch (Rd.Segments[_nextBend.TurninSegIdx].roadMaterial)
        {
        case "Dirt": f = -0.0832f; g = 0f; break;

        case "DirtyRoad": f = -0.05432f; g = -0.1585f; break;

        case "Washboard": f = -0.04990f; g = -0.2070f; break;

        case "Tarmac": f = -0.04776f; g = -0.2191f; break;

        default: f = -0.08367f; g = 0.02521f; break;
        }
        float _adjSpeed = _nextBend.Speed * SpeedAdj;

        c = -a * _speed * _speed - b * _speed;
        h = DistToTurnin - f * _adjSpeed * _adjSpeed - g * _adjSpeed;
        //Sl is the liftoff speed
        LiftOffSpeed = (-(b - g) + Mathf.Sqrt((b - g) * (b - g) - 4 * (a - f) * (c - h))) / (2 * (a - f));
        //Dl is the liftoff dist
        DistToBrakePt = a * LiftOffSpeed * LiftOffSpeed + b * LiftOffSpeed + c;
        if (DistToBrakePt < DistToTurnin)
        {   //Enough time to accelerate before braking
            int SegsToBrakePt = Mathf.RoundToInt(DistToBrakePt * Rd.XSecs.Diff(_currXSec, AdjustedTurninXSec) / DistToTurnin);
            BrakeXSec   = Rd.XSecs[_currXSec.Idx + SegsToBrakePt];
            TurnInSpeed = _adjSpeed;
        }
        else
        //going too slow. No need to brake
        {
            DistToBrakePt = DistToTurnin;
            TurnInSpeed   = Mathf.Sqrt(_speed * _speed + 2 * a * DistToTurnin);
            BrakeXSec     = AdjustedTurninXSec;
        }
    }
Пример #7
0
    public XSec XSecPlusOne(XSec XS)
    {
        int Idx = XS.Idx + 1;

        if (Idx == _XSecs.Count)
        {
            return(_XSecs[0]);
        }
        else
        {
            return(_XSecs[Idx]);
        }
    }
Пример #8
0
    public void Init(bool LerpToStart)
    {
        if (_replayer.State == "Playing" || _replayer.State == "PlayingSloMo")
        {
            FutureFrame = Recrdng.Current.CurrFrame + 200; EndFrame = FutureFrame + 50;
        }
        if (_replayer.State == "Rewind" || _replayer.State == "Reverse")
        {
            FutureFrame = Recrdng.Current.CurrFrame - 200; EndFrame = FutureFrame - 50;
        }
        FutureFrame = Mathf.Clamp(FutureFrame, 0, Recrdng.Current.FrameCount - 1);
        EndFrame    = Mathf.Clamp(EndFrame, 0, Recrdng.Current.FrameCount - 1);
        List <RecFrameData> FrameData = Recrdng.Current.Data[FutureFrame];

        CamStartPos = FrameData[Recrdng.Current.PlayerCarId].Pos;
        Ray        _r        = new Ray(CamStartPos + Vector3.up * 0.2f, Vector3.down);
        int        LayerMask = ~((1 << 8) + (1 << 10) + (1 << 13));
        RaycastHit hit;

        if (Physics.Raycast(_r, out hit, 2, LayerMask))
        {
            if (hit.collider.name.StartsWith("Road"))
            {
                XSec xs = Road.Instance.XSecs[System.Convert.ToInt16(hit.collider.name.Substring(7))];
                if (Vector3.Distance(CamStartPos, xs.KerbR) > Vector3.Distance(CamStartPos, xs.KerbL))
                {
                    CamEndPos   = CamStartPos + (xs.MidLeft - CamStartPos).normalized * 2f + Vector3.up * 0.2f;
                    CamStartPos = xs.KerbR + Vector3.up * 0.2f;
                }
                else
                {
                    CamEndPos   = CamStartPos + (xs.MidRight - CamStartPos).normalized * 2f + Vector3.up * 0.2f;
                    CamStartPos = xs.KerbL + Vector3.up * 0.2f;
                }
            }
            else
            {
                CamEndPos = CamStartPos + Vector3.right * 2;
            }
        }
        else
        {
            CamEndPos = CamStartPos + Vector3.right * 2;
        }
    }
Пример #9
0
    private void AnalyseTurnin()
    {
        return;

        int Adj = Mathf.RoundToInt(Mathf.Abs(RacelineAnglePerSeg) * 5 - 5); // for hairpins, shift the turnin earlier so it doesnt hit the fence

        switch (Rd.Segments[TurninSegIdx].roadMaterial)
        {
        case "Tarmac": Adj = Mathf.RoundToInt(Mathf.Abs(RacelineAnglePerSeg) * 5 - 5); break;

        case "Washboard": Adj = Mathf.RoundToInt(Mathf.Abs(RacelineAnglePerSeg) * 5 - 5); break;

        case "DirtyRoad": Adj = Mathf.RoundToInt(Mathf.Abs(RacelineAnglePerSeg) * 5 - 5); break;

        case "Dirt": Adj = Mathf.RoundToInt(Mathf.Abs(RacelineAnglePerSeg) * 5 - 7); break;
        }
        TurninXSec   = Rd.XSecs[TurninSegIdx - Adj];
        TurninSegIdx = TurninXSec.Idx;
    }
Пример #10
0
 private void PopulateXSecCurrBends()
 {
     foreach (Bend _bend in Bends)
     {
         //These two saved a massive performance hit
         Bend _nb = Bends.Next(_bend);
         for (XSec x = _bend.TurninXSec; x != _bend.ExitXSec; x = XSecs.Next(x))
         {
             x.CurrBend = _bend;
         }
         if (_nb.TurninXSec == null)
         {
             Debug.Log("BendId" + _bend.BendId + " no turnin");
         }
         else
         {
             for (XSec x = _bend.TurninXSec; x != _nb.TurninXSec; x = XSecs.Next(x))
             {
                 x.NextBend = _nb;
             }
         }
     }
 }
Пример #11
0
    /// <summary>
    /// Calculates the Kerb positions for the segments leading up to the controlpoint
    /// <para>Ascertains if its possible first so it never crashes</para>
    /// </summary>
    public static void CalcXSecs(int CtrlPtIdx, int RoadWidth, bool FrstHlf = true, bool SecndHlf = true)
    {
        BezierLine Bez = BezierLine.Instance;
        Road       Rd  = Road.Instance;

        //If this is Idx1 then calculate the last visible one
        if (CtrlPtIdx == 1 && Rd.IsCircular)
        {
            CtrlPtIdx = Bez.CtrlPts.Count - 2;
        }
        //if (CtrlPtIdx == Bez.CtrlPts.Count-1 && Rd.IsCircular) CtrlPtIdx = 1;   //doesnt work
        if (CtrlPtIdx < 2)
        {
            return;
        }
        if (CtrlPtIdx > Bez.CtrlPts.Count - 2)
        {
            return;
        }
        int CP1XId = Bez.CtrlPts[CtrlPtIdx - 2].SegStartIdx;
        int CP2XId = Bez.CtrlPts[CtrlPtIdx - 1].SegStartIdx;
        int CP3XId = Bez.CtrlPts[CtrlPtIdx].SegStartIdx;
        int CP4XId = Bez.CtrlPts[CtrlPtIdx + 1].SegStartIdx;

        if (Bez.CtrlPts[CtrlPtIdx - 1].SegCount == 0)
        {
            CP2XId = CP3XId;
        }
        if (Bez.CtrlPts[CtrlPtIdx - 2].SegCount == 0)
        {
            CP1XId = CP2XId;
        }
        if (Rd.IsCircular && CP2XId == Rd.XSecs.Count)
        {
            CP2XId = Bez.CtrlPts[2].SegStartIdx; CP3XId = Bez.CtrlPts[2].SegStartIdx; CP4XId = Bez.CtrlPts[3].SegStartIdx;
        }                                                                                                                                                                 //because of the overlap
        if (Rd.IsCircular && CP3XId == Rd.XSecs.Count)
        {
            CP3XId = Bez.CtrlPts[1].SegStartIdx; CP4XId = Bez.CtrlPts[2].SegStartIdx;
        }                                                                                                                            //because of the overlap
        if (Rd.IsCircular && CtrlPtIdx == 2)
        {
            CP1XId = Bez.CtrlPts[Rd.Sectns.Count - 2].SegStartIdx;
        }
        //if (Bez.CtrlPts[CtrlPtIdx + 1].SegCount == 0) CP4XId = CP3XId;

        XSec XSec1 = CalcXSecPerp(CP1XId, RoadWidth);
        XSec XSec2 = CalcXSecPerp(CP2XId, RoadWidth);
        XSec XSec3 = CalcXSecPerp(CP3XId, RoadWidth);
        XSec XSec4 = CalcXSecPerp(CP4XId, RoadWidth);

        Vector3 RKerb1;
        Vector3 RKerb2;
        Vector3 RKerb3;
        Vector3 RKerb4;
        Vector3 LKerb1;
        Vector3 LKerb2;
        Vector3 LKerb3;
        Vector3 LKerb4;

        RKerb1 = XSec1.KerbR;
        RKerb2 = XSec2.KerbR;
        RKerb3 = XSec3.KerbR;
        RKerb4 = XSec4.KerbR;

        LKerb1 = XSec1.KerbL;
        LKerb2 = XSec2.KerbL;
        LKerb3 = XSec3.KerbL;
        LKerb4 = XSec4.KerbL;


        //this worked on the flat road. Now we have to bank the road
        Vector3 _bankDirection;

        try
        {
            //This will fail at some point if you are moving a cone at the end - its OK tho
            _bankDirection = (Bez.PathPlusOne(CP1XId) - Bez.Path[CP1XId]).normalized * Bez.CtrlPts[CtrlPtIdx - 2].BankAngle;
            if (Bez.CtrlPts[CtrlPtIdx - 2].BankAngle < 0)
            {
                LKerb1 = VectGeom.RotatePointAroundPivot(LKerb1, Bez.Path[CP1XId], _bankDirection);
            }
            else
            {
                RKerb1 = VectGeom.RotatePointAroundPivot(RKerb1, Bez.Path[CP1XId], _bankDirection);
            }
            _bankDirection = (Bez.PathPlusOne(CP2XId) - Bez.Path[CP2XId]).normalized * Bez.CtrlPts[CtrlPtIdx - 1].BankAngle;
            if (Bez.CtrlPts[CtrlPtIdx - 1].BankAngle < 0)
            {
                LKerb2 = VectGeom.RotatePointAroundPivot(LKerb2, Bez.Path[CP2XId], _bankDirection);
            }
            else
            {
                RKerb2 = VectGeom.RotatePointAroundPivot(RKerb2, Bez.Path[CP2XId], _bankDirection);
            }
            _bankDirection = (Bez.PathPlusOne(CP3XId) - Bez.Path[CP3XId]).normalized * Bez.CtrlPts[CtrlPtIdx].BankAngle;
            if (Bez.CtrlPts[CtrlPtIdx].BankAngle < 0)
            {
                LKerb3 = VectGeom.RotatePointAroundPivot(LKerb3, Bez.Path[CP3XId], _bankDirection);
            }
            else
            {
                RKerb3 = VectGeom.RotatePointAroundPivot(RKerb3, Bez.Path[CP3XId], _bankDirection);
            }
            _bankDirection = (Bez.PathPlusOne(CP4XId) - Bez.Path[CP4XId]).normalized * Bez.CtrlPts[CtrlPtIdx + 1].BankAngle;
            if (Bez.CtrlPts[CtrlPtIdx + 1].BankAngle < 0)
            {
                LKerb4 = VectGeom.RotatePointAroundPivot(LKerb4, Bez.Path[CP4XId], _bankDirection);
            }
            else
            {
                RKerb4 = VectGeom.RotatePointAroundPivot(RKerb4, Bez.Path[CP4XId], _bankDirection);
            }
        }
        catch (System.Exception e) { Debug.Log(e.ToString()); }


        int NumXSecsToAdjust;

        //Catmull Rom up to the control pt
        //RIGHT KERB
        try { NumXSecsToAdjust = Bez.CtrlPts[CtrlPtIdx - 1].SegCount; }
        catch (System.Exception e) { NumXSecsToAdjust = 0; }
        int     AdjustStartIdx = CP2XId;
        Vector3 a = RKerb1;
        Vector3 b = RKerb2;
        Vector3 c = RKerb3;
        Vector3 d = RKerb4;

        float t = 0.5f;

        //if (Vector3.Angle(c - b, d - c) > 135 || Vector3.Angle(b - a, c - b) > 135) t = 2.5f;
        for (int p = 0; p < NumXSecsToAdjust; p++)
        {
            float u = (float)p / NumXSecsToAdjust;

            //Coeffs for the catmullrom equation
            Vector3 c0   = b;
            Vector3 c1   = -t * a + t * c;
            Vector3 c2   = 2f * t * a + (t - 3f) * b + (3f - 2f * t) * c - t * d;
            Vector3 c3   = -t * a + (2f - t) * b + (t - 2f) * c + t * d;
            Vector3 temp = c0 + c1 * u + c2 * u * u + c3 * u * u * u;
            //Vector3 temp = .5f * ((-a + 3f * b - 3f * c + d) * (u * u * u) + (2f * a - 5f * b + 4f * c - d) * (u * u) + (-a + c) * u + 2f * b);
            Vector3 newKerb = temp;
            //PlaceMarker(temp);
            Rd.XSecs[AdjustStartIdx + p].KerbR = temp;
        }

        //Catmull Rom up to the control pt
        //LEFT KERB
        a = LKerb1;
        b = LKerb2;
        c = LKerb3;
        d = LKerb4;

        //if (Vector3.Angle(c - b, d - c) > 135 || Vector3.Angle(b - a, c - b) > 135) t = 2.5f;
        for (int p = 0; p < NumXSecsToAdjust; p++)
        {
            float u = (float)p / NumXSecsToAdjust;

            //Coeffs for the catmullrom equation
            Vector3 c0   = b;
            Vector3 c1   = -t * a + t * c;
            Vector3 c2   = 2f * t * a + (t - 3f) * b + (3f - 2f * t) * c - t * d;
            Vector3 c3   = -t * a + (2f - t) * b + (t - 2f) * c + t * d;
            Vector3 temp = c0 + c1 * u + c2 * u * u + c3 * u * u * u;
            //Vector3 temp = .5f * ((-a + 3f * b - 3f * c + d) * (u * u * u) + (2f * a - 5f * b + 4f * c - d) * (u * u) + (-a + c) * u + 2f * b);
            Vector3 newKerb = temp;
            //PlaceMarker(temp);
            Rd.XSecs[AdjustStartIdx + p].KerbL    = temp;
            Rd.XSecs[AdjustStartIdx + p].TerrainL = (Rd.XSecs[AdjustStartIdx + p].KerbL - Bez.Path[AdjustStartIdx + p]) * 1.3f + Bez.Path[AdjustStartIdx + p];
            Rd.XSecs[AdjustStartIdx + p].TerrainR = (Rd.XSecs[AdjustStartIdx + p].KerbR - Bez.Path[AdjustStartIdx + p]) * 1.3f + Bez.Path[AdjustStartIdx + p];

            Rd.XSecs[AdjustStartIdx + p].MidPt = (Rd.XSecs[AdjustStartIdx + p].KerbL + Rd.XSecs[AdjustStartIdx + p].KerbR) / 2;
            Rd.XSecs[AdjustStartIdx + p].MidPt = new Vector3(Rd.XSecs[AdjustStartIdx + p].MidPt.x, Bez.Path[AdjustStartIdx + p].y, Rd.XSecs[AdjustStartIdx + p].MidPt.z);
        }
    }
Пример #12
0
    void Update()
    {
        if (CR_Running)
        {
            return;
        }
        if (Timer == 0)
        {
            Timer = 10;
        }
        Timer--;
        if (Timer != 0)
        {
            return;
        }
        Accel      = 0.9f;
        BrakeForce = 0;
        Steer      = 0;
        SegIdx     = _gps.CurrSegIdx;
        _currXSec  = _gps.CurrXSec;
        _nextBend  = _gps.NextBend;
        _currBend  = _gps.CurrBend;
        bool FirstHalfOfBend = _currBend != null && _currXSec.IsBefore(_currBend.ApexXSec);
        //Vector3 B = Road.Instance.Segments[SegIdx].verts[4];
        Vector3 SegFwdDir = Road.Instance.XSecs[SegIdx].Forward;
        Vector3 Heading   = transform.forward;

        HeadingAngle = Vector3.Angle(Heading, SegFwdDir);
        Vector3 cross = Vector3.Cross(Heading, SegFwdDir);

        if (cross.y > 0)
        {
            HeadingAngle = -HeadingAngle;
        }
        //Postition across the cross sec
        Vector3 L             = Road.Instance.XSecs[SegIdx].KerbL;
        Vector3 R             = Road.Instance.XSecs[SegIdx].KerbR;
        float   DistFromLKerb = Vector3.Distance(L, transform.position);
        float   DistFromRKerb = Vector3.Distance(R, transform.position);
        //Calculate entry speed for next bend
        float _entrySpeed = Mathf.Abs(50 / _nextBend.AnglePerSeg);

        //Coming into a sharp bend too fast slow down
        if (_gps.SegsPerSec - _entrySpeed > (_nextBend.StartSegIdx > _gps.CurrSegIdx?_nextBend.StartSegIdx - _gps.CurrSegIdx: _nextBend.StartSegIdx + Rd.Segments.Count - _gps.CurrSegIdx))
        {
            Accel = 0; BrakeForce = 1f;
        }
        else
        {
            Accel = 1; BrakeForce = 0;
        }


        //Aim for the middle of the 10th segment in front
        XSec    AimSec   = Road.Instance.XSecCircular(SegIdx + 20);
        Vector3 AimPoint = AimSec.MidPt;

        if (FirstHalfOfBend)
        {
            if (_currBend.AnglePerSeg > 1)
            {
                if (_currBend.Type == BendType.Left)
                {
                    AimPoint = AimSec.MidLeft;
                }
                if (_currBend.Type == BendType.Right)
                {
                    AimPoint = AimSec.MidRight;
                }
            }
        }
        Vector3 LongAimPoint = Road.Instance.XSecCircular(SegIdx + 40).MidPt;

        //steer round the car in front
        Vector3 FrontOfCar = transform.position + transform.up * 0.5f + transform.forward * 2.5f;

        _collisionRay = new Ray(FrontOfCar, AimPoint + Vector3.up - FrontOfCar);
        int layerMask = (1 << 8);

        if (Physics.Raycast(_collisionRay, out CollisionHit, 50, layerMask))
        {
            if (CollisionHit.collider.name != this.name)
            {
                if (CollisionHit.rigidbody.velocity.sqrMagnitude < 1)
                {
                    StartCoroutine(ThreePointTurn("R"));
                }
                else
                {
                    AimPoint = (Road.Instance.XSecCircular(SegIdx + 10).MidPt + Road.Instance.XSecCircular(SegIdx + 10).KerbR) / 2;
                }
            }
        }
        //Debug.DrawRay(FrontOfCar, AimPoint + Vector3.up - FrontOfCar, Color.red);

        //***********************************************************************************
        //Steer towards the aim point
        float   DesiredHeadingAngle = Vector3.Angle(AimPoint - transform.position, SegFwdDir);
        Vector3 crossDes            = Vector3.Cross(AimPoint - transform.position, SegFwdDir);

        if (crossDes.y > 0)
        {
            DesiredHeadingAngle = -DesiredHeadingAngle;
        }

        // Pointing towards kerb - do a 3 point turn
        if (HeadingAngle > -100 && HeadingAngle < -80 && DistFromLKerb < 3)
        {
            StartCoroutine(ThreePointTurn("L"));
            return;
        }
        if (HeadingAngle < 100 && HeadingAngle > 80 && DistFromRKerb < 3)
        {
            StartCoroutine(ThreePointTurn("R"));
            return;
        }

        //Coming up to a hill, put your foot down
        if (LongAimPoint.y - SegFwdDir.y > 0)
        {
            Accel = ((LongAimPoint.y - SegFwdDir.y) * 0.005f) + 0.9f;
        }


        //coming up to a hill bend slow down
        if (Mathf.Abs(_nextBend.Angle) > 10 && _gps.NextHill > 2 && _gps.Speed > 10)
        {
            Accel = 0; BrakeForce = 0.5f;
        }

        //Positive steer = right
        Steer = (DesiredHeadingAngle - HeadingAngle);

        //Start of bend - flick the wheel
        //copied from CarAIInput

        /*
         * //Slide the Adjusted turnin point along the gate
         * SlideFrac = Mathf.Sqrt(Mathf.Clamp01(TurnInSpeed / _nextBend.Speed)); // - Mathf.Abs(Mathf.Sin(DriftAngle)) * 1.5f); //SlideFrac=1 for a big swingout
         * //Debug.Log("SlideFrac=" + TurnInSpeed  + "/" + _nextBend.Speed + "=" + SlideFrac);
         * AdjustedTurninPt = Vector3.Lerp(_nextBend.MinTurninPos, _nextBend.TurninPos, SlideFrac);
         * AdjustedTurninXSec = Rd.XSecs[Mathf.RoundToInt(Mathf.Lerp(_nextBend.StartSegIdx, _nextBend.TurninSegIdx, SlideFrac))];
         */

        if (_opponentCollisionDirec == CollisionDirection.Left && Steer < 10)
        {
            Steer = 10;
        }
        if (_opponentCollisionDirec == CollisionDirection.Right && Steer > -10)
        {
            Steer = -10;
        }
    }
Пример #13
0
    internal void CalcTurnin()
    {
        //GameObject goCirc;

        //CapsuleCollider Circ;
        //goCirc = GameObject.CreatePrimitive(PrimitiveType.Cube);
        //goCirc.GetComponent<BoxCollider>().enabled = false;
        //Circ = goCirc.AddComponent<CapsuleCollider>();
        //goCirc.name = "CircColl" + BendId;
        //Circ.height = 100;
        Radius = SqrtRad * SqrtRad;
        Vector3        Centre         = new Vector3(0, 0, 0);
        Vector3        C              = new Vector3(0, 0, 0);
        Vector3        AP             = VectGeom.Convert2d(ApexPos);
        Vector3        TP             = new Vector3(0, 0, 0);
        Vector3        EP             = new Vector3(0, 0, 0);
        int            e              = 0;
        float          ExitFrac       = 1;//1 is a wide turn, 0 is tight
        float          SmallestRadErr = 1000;
        PossBendCircle bbc            = new PossBendCircle();
        Vector3        ApexPos2d      = VectGeom.Convert2d(ApexPos);
        float          NxtBndDist     = Rd.XSecs.Diff(ApexXSec, NextBend.ApexXSec);

        //Method:
        //Try a range of turnin segs
        //For each Turnin seg, draw a line perpendicular to the fwd direction
        //and find the turninPt (TP)
        //Find the midpoint (MP) of the line from apex to turninPoint and draw a line perpendicular to this (MPerp)
        //Where MPerp crosses TPerp is the centre of the circle, C
        /// <image url="$(SolutionDir)\CommonImages\CalcTurninAlgorithm.png" scale="1.2"/>
        if (Type == BendType.Right)
        {
            if (NextBend.Type == BendType.Left && NxtBndDist < 200)
            {
                ExitFrac = NxtBndDist / 200;
            }
            for (XSec tx = Rd.XSecs[StartSegIdx - 70]; tx.IsBefore(Rd.XSecs[StartSegIdx]); tx = Rd.XSecs.Next(tx))    //removed circlebug
            {
                Vector2 TPerp = VectGeom.Convert2d(Vector3.Cross(Vector3.up, tx.Forward));
                TP = VectGeom.Convert2d(tx.KerbL + (tx.KerbR - tx.KerbL).normalized * TurninGap);
                Vector2 MP    = (ApexPos2d + TP) / 2;
                Vector2 MPerp = new Vector2((ApexPos2d - TP).y, -(ApexPos2d - TP).x);
                if (VectGeom.LineLineIntersection(out C, TP, TPerp, MP, MPerp)) //these vars are all Vector3(x,0,y)
                {
                    float          biggestCos = 0;
                    float          R          = Vector2.Distance(TP, C);
                    PossBendCircle pbc        = new PossBendCircle();
                    float          RadErr     = 1000;
                    for (e = EndXSec.Idx + 70; e > EndXSec.Idx; e--) //bugbugbug circlebug
                    {
                        Vector2 WideExitPt     = VectGeom.Convert2d(Rd.XSecs[e].KerbL + (Rd.XSecs[e].KerbR - Rd.XSecs[e].KerbL).normalized * 2);
                        Vector2 TightExitPoint = VectGeom.Convert2d(Rd.XSecs[e].KerbR + (Rd.XSecs[e].KerbL - Rd.XSecs[e].KerbR).normalized * 2);
                        EP = Vector2.Lerp(TightExitPoint, WideExitPt, ExitFrac);
                        Vector3 EPerp = VectGeom.Convert2d(-Rd.XSecs[e].Right).normalized;
                        float   cos   = Mathf.Abs(Vector2.Dot((EP - C).normalized, EPerp));
                        if (cos > biggestCos)
                        {
                            RadErr = Mathf.Abs(Vector3.Distance(EP, C) - R);
                            pbc    = new PossBendCircle {
                                C = C, RSq = 0, RadErr = RadErr, EP = EP, EX = Rd.XSecs[e], TP = TP, TX = tx
                            };
                            biggestCos = cos;
                        }
                    }
                    if (RadErr < SmallestRadErr)
                    {
                        bbc = new PossBendCircle {
                            C = pbc.C, RSq = 0, RadErr = pbc.RadErr, EP = pbc.EP, EX = pbc.EX, TP = pbc.TP, TX = pbc.TX
                        };
                        SmallestRadErr = pbc.RadErr;
                    }
                }
            }
            Centre       = new Vector3(bbc.C.x, ApexPos.y, bbc.C.y);
            Radius       = Vector2.Distance(bbc.TP, bbc.C);
            TurninXSec   = bbc.TX;
            TurninSegIdx = TurninXSec.Idx;
            TurninPos    = new Vector3(bbc.TP.x, ApexPos.y, bbc.TP.y);
            ExitXSec     = bbc.EX;
            ExitPos      = new Vector3(bbc.EP.x, ApexPos.y, bbc.EP.y);
            goto FoundCentre;
            //Not found Centre
            Debug.Log("No Centre for Bend" + BendId);
            ExitXSec = Rd.XSecs[e];
            Debug.Break();
        }
        if (Type == BendType.Left)
        {
            if (NextBend.Type == BendType.Right && NxtBndDist < 200)
            {
                ExitFrac = NxtBndDist / 200;
            }
            for (int t = StartSegIdx - 70; t < StartSegIdx; t++)    //bugbugbug circlebug
            {
                Vector2 TPerp = VectGeom.Convert2d(Vector3.Cross(Vector3.up, Rd.XSecs[t].Forward));
                TP = VectGeom.Convert2d(Rd.XSecs[t].KerbR + (Rd.XSecs[t].KerbL - Rd.XSecs[t].KerbR).normalized * TurninGap);
                Vector2 MP    = (ApexPos2d + TP) / 2;
                Vector2 MPerp = new Vector2((ApexPos2d - TP).y, -(ApexPos2d - TP).x);
                if (VectGeom.LineLineIntersection(out C, TP, TPerp, MP, MPerp)) //these vars are all Vector3(x,0,y)
                {
                    float          biggestCos = 0;
                    float          R          = Vector2.Distance(TP, C);
                    PossBendCircle pbc        = new PossBendCircle();
                    float          RadErr     = 1000;
                    for (e = EndXSec.Idx + 70; e > EndXSec.Idx; e--) //bugbugbug circlebug
                    {
                        Vector2 WideExitPt     = VectGeom.Convert2d(Rd.XSecs[e].KerbR + (Rd.XSecs[e].KerbL - Rd.XSecs[e].KerbR).normalized * 2);
                        Vector2 TightExitPoint = VectGeom.Convert2d(Rd.XSecs[e].KerbL + (Rd.XSecs[e].KerbR - Rd.XSecs[e].KerbL).normalized * 2);
                        EP = Vector2.Lerp(TightExitPoint, WideExitPt, ExitFrac);
                        Vector3 EPerp = VectGeom.Convert2d(Rd.XSecs[e].Right).normalized;
                        float   cos   = Mathf.Abs(Vector2.Dot((EP - C).normalized, EPerp));
                        if (cos > biggestCos)
                        {
                            RadErr = Mathf.Abs(Vector3.Distance(EP, C) - R);
                            pbc    = new PossBendCircle {
                                C = C, RSq = 0, RadErr = RadErr, EP = EP, EX = Rd.XSecs[e], TP = TP, TX = Rd.XSecs[t]
                            };
                            biggestCos = cos;
                        }
                    }
                    if (RadErr < SmallestRadErr)
                    {
                        bbc = new PossBendCircle {
                            C = pbc.C, RSq = 0, RadErr = pbc.RadErr, EP = pbc.EP, EX = pbc.EX, TP = pbc.TP, TX = pbc.TX
                        };
                        SmallestRadErr = pbc.RadErr;
                    }
                }
            }
            Centre       = new Vector3(bbc.C.x, ApexPos.y, bbc.C.y);
            Radius       = Vector2.Distance(bbc.TP, bbc.C);
            TurninXSec   = bbc.TX;
            TurninSegIdx = TurninXSec.Idx;
            TurninPos    = new Vector3(bbc.TP.x, ApexPos.y, bbc.TP.y);
            ExitXSec     = bbc.EX;
            ExitPos      = new Vector3(bbc.EP.x, ApexPos.y, bbc.EP.y);
            goto FoundCentre;
            //Not found Centre
            Debug.Log("No Centre for Bend" + BendId);
            ExitXSec = Rd.XSecs[e];
            Debug.Break();
        }
FoundCentre:
        //goCirc.transform.position = Centre;
        //Circ.radius = Radius;
        Angle = VectGeom.SignedAngle(TurninXSec.Forward, ExitXSec.Forward);
        float RacelineSegCount = Rd.XSecs.Diff(TurninXSec, ExitXSec);;

        RacelineAnglePerSeg = Angle / RacelineSegCount;
        RacelineSegLength   = Angle * Mathf.Deg2Rad * Radius / RacelineSegCount;
        CalculateSpeed();
        //Circ.enabled = false; //cos the gameobject doesnt get destroyed till end of frame
        //GameObject.Destroy(goCirc);
        return;

NoTurnin:
        if (TurninXSec == null)
        {
            TurninXSec = Rd.XSecs[ApexSegIdx - 50]; TurninSegIdx = TurninXSec.Idx;
            ExitXSec   = Rd.XSecs[ApexSegIdx + (ApexSegIdx - TurninSegIdx)];
            if (Type == BendType.Right)
            {
                TurninPos = TurninXSec.KerbL + (TurninXSec.KerbR - TurninXSec.KerbL).normalized * 4f;
            }
            else
            {
                TurninPos = TurninXSec.KerbR + (TurninXSec.KerbL - TurninXSec.KerbR).normalized * 4f;
            }
            Radius = 100;
            AnalyseTurnin();
            CalculateSpeed();
        }
        //Circ.enabled = false; //cos the gameobject doesnt get destroyed till end of frame
        //GameObject.Destroy(goCirc);
    }
Пример #14
0
    public void UpdateSegIdx()
    {
        //raycast to see which segment is underneath us
        if (Physics.Raycast(_goVehicle.transform.position + Vector3.up * 3 + _goVehicle.transform.forward, Vector3.down, out hit, 8, layerMask))
        {
            RaycastHitPos = hit.point;
            if (hit.collider.name.Contains("Seg"))
            {
                CurrSegIdx = System.Convert.ToInt16(hit.collider.name.Substring(7));
                CurrXSec   = Rd.XSecs[CurrSegIdx];
                CurrBend   = CurrXSec.CurrBend;
                RoadMat    = Rd.Segments[CurrSegIdx].roadMaterial;
                IsOnRoad   = true;
            }
            else
            {
                IsOnRoad = false;
            }
        }
        else
        {
            IsOnRoad = false;
        }

        //Calculate How long to change segments
        if (PrevSegIdx != CurrSegIdx)
        {
            _segsPerSec = (CurrSegIdx - PrevSegIdx) / (Time.time - SegTime); SegTime = Time.time;
        }
        PrevSegIdx = CurrSegIdx;
        if (Time.time - SegTime > 5 && Player == true && RecoveryAllowed)
        {
            //SHOW THE RECOVERY PANEL
            RecoveryAllowed = false;
            MusicPlayer.Instance.StepDown();
            Transform  canv       = GameObject.FindObjectOfType <Canvas>().transform;
            GameObject pnlRecover = (GameObject)GameObject.Instantiate(Resources.Load("Prefabs/pnlRecover"), canv);
            //pnlRecover.transform.localScale = Vector3.one;
            //pnlRecover.GetComponent<RectTransform>().anchoredPosition = Vector2.up;
            //pnlRecover.GetComponent<RectTransform>().offsetMin = new Vector2(0, 350);
            //pnlRecover.GetComponent<RectTransform>().offsetMax = Vector2.zero;
            pnlRecover.GetComponent <RecoverPanel>().Init(this, _goVehicle, CurrSegIdx);
        }

        //See if we are in the air - raycast to see if there is anything at all below us by one metre
        if (Physics.Raycast(_goVehicle.transform.position + Vector3.up + _goVehicle.transform.forward, Vector3.down, out hit, 2, airLayerMask))
        {
            if (IsInAir)
            {
                Land();
            }
            IsInAir = false;
            if (hit.collider.name.Contains("Terrain"))
            {
                RoadMat = "Dirt";
            }
        }
        else
        {
            if (!IsInAir)
            {
                TakeOff();
            }
            IsInAir = true;
        }

        if (JustLanded)
        {
            AirRecoveryTimer++;
            Vector3 RoadVector = Road.Instance.XSecs[CurrSegIdx].Forward;
            Vector3 VehVector  = _goVehicle.transform.forward;
            float   Angl       = Vector3.Angle(RoadVector, VehVector);
            float   DiffAngl   = Angl - PrevAngle;

            if (AirRecoveryTimer > 30 && Angl < 20 && DiffAngl > -30 && DiffAngl < 30)
            {
                Recovery();
                JustLanded = false;
            }
            PrevAngle = Angl;
        }

        //Drift measurement
        if (IsOnRoad && _rb.velocity.sqrMagnitude > 0.2f)
        {
            float _driftAngle = Vector3.Angle(_goVehicle.transform.forward, _rb.velocity);
            if (_drifting && _driftAngle > 90)
            {
                DriftFail();
            }

            if (_driftAngle > 20 && !IsInAir)
            {
                Vector3 SegFwd         = Rd.XSecs[CurrSegIdx].Forward;
                int     _segIdxPlusOne = CurrSegIdx + 1;
                if (_segIdxPlusOne > Rd.Segments.Count - 1)
                {
                    _segIdxPlusOne = _segIdxPlusOne - Rd.Segments.Count;
                }
                Vector3 SegPlusOneFwd = Rd.XSecs[_segIdxPlusOne].Forward;
                Vector3 cross         = Vector3.Cross(SegPlusOneFwd, SegFwd);
                Vector3 vehcross      = Vector3.Cross(_goVehicle.transform.forward, _rb.velocity);
                if (Mathf.Sign(vehcross.y) == Mathf.Sign(cross.y)) // { Debug.Log("OK"); } else { Debug.Log("Fail"); }
                {
                    if (!_drifting)
                    {
                        Drift();
                    }
                }
                else
                {
                    if (_drifting)
                    {
                        EndDrift();
                    }
                }
            }
            else if (_drifting)
            {
                EndDrift();
            }
        }
        else if (_drifting)
        {
            DriftFail();
        }


        /*
         * if (_drifting)
         * {
         *  _driftRecoveryTimer++;
         *  Vector3 RoadVector = Road.Instance.XSecs[SegIdx].Forward;
         *  Vector3 VehVector = _goVehicle.transform.forward;
         *  float Angl = Vector3.Angle(RoadVector, VehVector);
         *  float DiffAngl = Angl - PrevAngle;
         *
         *  if (_driftRecoveryTimer > 100 && Angl < 10 && DiffAngl > 0 && DiffAngl < 10)
         *  {
         *      DriftRecovery();
         *      _drifting = false;
         *  }
         *  PrevAngle = Angl;
         * }
         */
    }
Пример #15
0
    public void Decode()
    {
        Road Rd = Road.Instance;

        Rd.Segments.Clear();
        Rd.XSecs.Clear();
        Rd.Sectns.Clear();
        if (XSecs == null)
        {  //in case we are loading a blank track
            Rd.Init();
        }
        else
        {
            Rd.StartingLineSegIdx = StartingLineSegIdx;
            if (BuilderPos != null)
            {
                Rd.BuilderPos = BuilderPos.V3;
            }
            else
            {
                Rd.BuilderPos = new Vector3(0, 50f, 0);
            }
            if (BuilderRot != null)
            {
                Rd.BuilderRot = BuilderRot.Decode;
            }
            Rd.IsCircular = IsCircular;
            foreach (XSecSerial XS in XSecs)
            {
                XSec X = XS.Decode();
                Rd.XSecs.Add(X);
            }

            foreach (RoadSectionSerial RSS in Sectns)
            {
                RoadSectn RS = RSS.Decode();
                Rd.Sectns.Add(RS);
            }


            foreach (RoadSegmentSerial SegS in Segs)
            {
                RoadSegment Seg = SegS.Decode();
                Rd.Segments.Add(Seg);
            }

            //Build the meshes for all the segments
            for (int Idx = 0; Idx < Segs.Length; Idx++)
            {
                RoadSegment seg = Road.Instance.Segments[Idx];
                if (seg.HasMesh)
                {
                    SegVerts Verts = XSecCalculator.SegmentVertices(Idx);
                    seg.BuildMeshes(Verts);
                }
                //seg.GetTerrainHeights();
                //seg.AdjustTerrain();
                //seg.SetMaterial();
                //seg.DeleteFence();
                //seg.CreateFence();
            }
            Rd.CalculateBends();
        }
    }
Пример #16
0
    public static void AdjustHairpin(BezierLine Bez, int CtlPtIdx)
    {
        return;

        if (CtlPtIdx < 2)
        {
            return;
        }
        //Adjusts the Road.Instance.XSecs around the controlpoint
        string Hand;
        Road   Rd = Road.Instance;
        //SegAdj=new List<SegVerts>();
        Vector2 PivotStart2d    = Vector2.zero;
        Vector2 PivotEnd2d      = Vector2.zero;
        int     PrevCtrlPtSegId = Bez.CtrlPts[CtlPtIdx - 1].SegStartIdx;
        int     PivotStartIdx   = Bez.CtrlPts[CtlPtIdx].SegStartIdx;
        int     PivotEndIdx     = Bez.CtrlPts[CtlPtIdx].SegStartIdx;
        int     NxtCtrlPtSegId  = Bez.CtrlPts[CtlPtIdx + 1].SegStartIdx;

        if (CtlPtIdx < 2)
        {
            return;
        }
        //See if its a right or a left hand curve
        Vector2 Path2d    = Convert2d(Rd.XSecs[PivotStartIdx].MidPt);
        Vector2 PrvPath2d = Convert2d(Rd.XSecs[PivotStartIdx - 1].MidPt);
        Vector2 NxtPath2d = Convert2d(Rd.XSecs[PivotStartIdx + 1].MidPt);
        Vector3 cross     = Vector3.Cross(PrvPath2d - Path2d, NxtPath2d - Path2d);

        if (cross.z > 0)
        {
            Hand = "R";
        }
        else
        {
            Hand = "L";
        }

        //Right Edge
        if (Hand == "R")
        {
            //Catmull Rom up to the control pt
            int     NumXSecsToAdjust = Bez.CtrlPts[CtlPtIdx - 1].SegCount / 2;
            int     AdjustStartIdx   = (PrevCtrlPtSegId + PivotStartIdx) / 2;
            Vector3 a = Rd.XSecs[PrevCtrlPtSegId].KerbR;
            Vector3 b = Rd.XSecs[(PrevCtrlPtSegId + PivotStartIdx) / 2].KerbR;
            Vector3 c = Rd.XSecs[PivotStartIdx].KerbR;
            Vector3 d = Rd.XSecs[(PivotStartIdx + NxtCtrlPtSegId) / 2].KerbR;
            c = new Vector3(c.x, (b.y + d.y) / 2, c.z);
            float t = 0.5f;
            //if (Vector3.Angle(c - b, d - c) > 135 || Vector3.Angle(b - a, c - b) > 135) t = 2.5f;
            for (int p = 0; p < NumXSecsToAdjust; p++)
            {
                float u = (float)p / NumXSecsToAdjust;

                //Coeffs for the catmullrom equation
                Vector3 c0   = b;
                Vector3 c1   = -t * a + t * c;
                Vector3 c2   = 2f * t * a + (t - 3f) * b + (3f - 2f * t) * c - t * d;
                Vector3 c3   = -t * a + (2f - t) * b + (t - 2f) * c + t * d;
                Vector3 temp = c0 + c1 * u + c2 * u * u + c3 * u * u * u;
                //Vector3 temp = .5f * ((-a + 3f * b - 3f * c + d) * (u * u * u) + (2f * a - 5f * b + 4f * c - d) * (u * u) + (-a + c) * u + 2f * b);
                Vector3 newKerb = temp;
                XSec    X       = new XSec((CtlPtIdx - 1) * 20 - 10 + p);
                X.KerbR = temp - Rd.XSecs[AdjustStartIdx + p].KerbR;
                Road.Instance.XSecs[AdjustStartIdx + p].Adjust(X);
            }

            //Catmull ROm after the control point
            NumXSecsToAdjust = Bez.CtrlPts[CtlPtIdx].SegCount / 2;
            AdjustStartIdx   = (PivotStartIdx) / 2;
            a = b;
            b = c;
            c = d;
            d = Rd.XSecs[NxtCtrlPtSegId].KerbR;
            //if (Vector3.Angle(c - b, d - c) > 135 || Vector3.Angle(b - a, c - b) > 135) t = 2.5f;
            for (int p = 0; p < NumXSecsToAdjust; p++)
            {
                float u = (float)p / NumXSecsToAdjust;

                //Coeffs for the catmullrom equation
                Vector3 c0   = b;
                Vector3 c1   = -t * a + t * c;
                Vector3 c2   = 2f * t * a + (t - 3f) * b + (3f - 2f * t) * c - t * d;
                Vector3 c3   = -t * a + (2f - t) * b + (t - 2f) * c + t * d;
                Vector3 temp = c0 + c1 * u + c2 * u * u + c3 * u * u * u;
                //Vector3 temp = .5f * ((-a + 3f * b - 3f * c + d) * (u * u * u) + (2f * a - 5f * b + 4f * c - d) * (u * u) + (-a + c) * u + 2f * b);
                Vector3 newKerb = temp;
                XSec    X       = new XSec((CtlPtIdx - 1) * 20 + p);
                X.KerbR = temp - Rd.XSecs[AdjustStartIdx + p].KerbR;
                Road.Instance.XSecs[AdjustStartIdx + p].Adjust(X);
            }
        }
        if (Hand == "L")
        {
            for (int Idx1 = (CtlPtIdx - 2) * 20 + 1; Idx1 < (CtlPtIdx - 1) * 20 - 1; Idx1++)
            {
                for (int Idx2 = (CtlPtIdx) * 20 - 1; Idx2 > (CtlPtIdx - 1) * 20; Idx2--)
                {
                    Vector2 PrevKerb12d = Convert2d(XSecCalculator.CalcXSecPerp(Idx1 - 1, 8).KerbL);
                    Vector2 PrevKerb22d = Convert2d(XSecCalculator.CalcXSecPerp(Idx2 - 1, 8).KerbL);
                    Vector2 Kerb12d     = Convert2d(XSecCalculator.CalcXSecPerp(Idx1, 8).KerbL);
                    Vector2 Kerb22d     = Convert2d(XSecCalculator.CalcXSecPerp(Idx2, 8).KerbL);
                    if (VectGeom.LinesIntersect2d(PrevKerb12d, Kerb12d, PrevKerb22d, Kerb22d))
                    {
                        //We've found the crossing point
                        //                                                   where Hand = "L";
                        //Take 2 steps back cos the curve would be too tight
                        PivotStartIdx = Idx1 - 2;
                        PivotEndIdx   = Idx2 + 1;
                        PivotStart2d  = Convert2d(Road.Instance.XSecs[PivotStartIdx].KerbL);
                        PivotEnd2d    = Convert2d(Road.Instance.XSecs[PivotEndIdx].KerbL);
                        //Now move the closest pivot back so its the same distance from the control point
                        //Which is the closest?
                        Vector2 CtrlPt2d = Convert2d(Bez.CtrlPts[CtlPtIdx].Pos);
                        float   DistS    = Vector2.Distance(PivotStart2d, CtrlPt2d);
                        float   DistE    = Vector2.Distance(PivotEnd2d, CtrlPt2d);
                        PlaceMarker(CtrlPt2d);
                        if (DistS > DistE)
                        {
                            //Debug.Log("ClosestPivotIdx = PivotEndIdx");
                            PivotEnd2d = Vector2.Lerp(CtrlPt2d, PivotEnd2d, DistS / DistE);
                            Rd.XSecs[PivotEndIdx].KerbL = new Vector3(PivotEnd2d.x, 0, PivotEnd2d.y);           //Todo1
                        }
                        else
                        {
                            //Debug.Log("ClosestPivotIdx = PivotStartIdx");
                            PivotStart2d = CtrlPt2d + (PivotStart2d - CtrlPt2d) * DistE / DistS;
                            Rd.XSecs[PivotStartIdx].KerbL = new Vector3(PivotStart2d.x, 0, PivotStart2d.y);     //Todo1
                        }
                        PlaceMarker(PivotStart2d);
                        PlaceMarker(PivotEnd2d);
                    }
                }
            }
        }
        if (PivotStartIdx != PivotEndIdx)
        {
            //Adjust all the right kerbs around the pivot
            //lets just lerp the kerb from pivotstart to pivotend
            //Todo: would be nice to do a catmul-rom curve around the pivot
            float TotLerp = (float)(PivotEndIdx - PivotStartIdx);
            for (int Idx = PivotStartIdx + 1; Idx < PivotEndIdx; Idx++)
            {
                float   LerpFrac = (float)(Idx - PivotStartIdx) / TotLerp;
                Vector2 Kerb2d;
                if (Hand == "R")
                {                                                                           //Todo1
                    Kerb2d = Vector2.Lerp(Convert2d(Road.Instance.XSecs[PivotStartIdx].KerbR), (Convert2d(Road.Instance.XSecs[PivotEndIdx].KerbR)), LerpFrac);
                    Rd.XSecs[Idx].KerbR = new Vector3(Kerb2d.x, Bez.Path[Idx].y, Kerb2d.y); //Todo1
                }
                else
                {                                                                           //Todo1
                    Kerb2d = Vector2.Lerp(Convert2d(Road.Instance.XSecs[PivotStartIdx].KerbL), (Convert2d(Road.Instance.XSecs[PivotEndIdx].KerbL)), LerpFrac);
                    Rd.XSecs[Idx].KerbL = new Vector3(Kerb2d.x, Bez.Path[Idx].y, Kerb2d.y); //Todo1
                }
            }
        }
        //Even if there is no hairpin we still might have a steep inner slope
        //So find where the steepness starts and finishes
        if (PivotStartIdx == PivotEndIdx)
        {
            Vector3 K1;
            Vector3 K2;
            bool    PivotStarted = false;
            for (int i = (CtlPtIdx - 1) * 20 - 5; i < (CtlPtIdx - 1) * 20 + 5; i++)
            {
                if (Hand == "L")
                {
                    K1 = Road.Instance.XSecs[i].KerbL;
                    K2 = Road.Instance.XSecs[i + 1].KerbL;
                }
                else
                {
                    K1 = Road.Instance.XSecs[i].KerbR;
                    K2 = Road.Instance.XSecs[i + 1].KerbR;
                }
                if ((K2.y - K1.y) / Vector2.Distance(Convert2d(K2), Convert2d(K1)) > 0.4f)
                {
                    if (PivotStarted == false)
                    {
                        PivotStartIdx = i;
                        PivotStarted  = true;
                    }
                    if (PivotStarted == true)
                    {
                        PivotEndIdx = i;
                    }
                }
                else
                {
                    if (PivotStarted == true)
                    {
                        break;
                    }
                }
            }
        }
        //Adjust the heights so we don't get steps in the road
        //we adjust the inner slope before and after the pivot uaing a smoothstep function
        int NoOfSegmentsToAdjust = Mathf.CeilToInt(Mathf.Abs((Bez.Path[PivotEndIdx].y - Bez.Path[PivotStartIdx].y) / 2));
        int AdjStartIdx          = PivotStartIdx - NoOfSegmentsToAdjust;

        if (AdjStartIdx < 0)
        {
            AdjStartIdx = 0;
        }
        int   AdjEndIdx = PivotEndIdx + NoOfSegmentsToAdjust;
        float AdjStarty;
        float AdjEndy;
        float TotAdjDist = 0;

        if (Hand == "L")
        {
            AdjStarty = Road.Instance.XSecs[AdjStartIdx].KerbL.y;
            AdjEndy   = Road.Instance.XSecs[AdjEndIdx].KerbL.y;
            for (int i = AdjStartIdx + 1; i <= AdjEndIdx; i++)
            {
                TotAdjDist += Vector2.Distance(Convert2d(Road.Instance.XSecs[i].KerbL), Convert2d(Road.Instance.XSecs[i - 1].KerbL));
            }
            float delta = 0;
            for (int i = AdjStartIdx + 1; i <= AdjEndIdx; i++)
            {
                delta += Vector2.Distance(Convert2d(Road.Instance.XSecs[i].KerbL), Convert2d(Road.Instance.XSecs[i - 1].KerbL));
                float NewY = Mathf.SmoothStep(AdjStarty, AdjEndy, delta / TotAdjDist);
                float AdjY = NewY - Road.Instance.XSecs[i].KerbL.y;
                XSec  X    = new XSec(i);
                X.KerbL = new Vector3(0, AdjY, 0);
                Road.Instance.XSecs[i].Adjust(X);
            }
        }
        if (Hand == "R")
        {
            AdjStarty = Road.Instance.XSecs[AdjStartIdx].KerbR.y;
            AdjEndy   = Road.Instance.XSecs[AdjEndIdx].KerbR.y;
            for (int i = AdjStartIdx + 1; i <= AdjEndIdx; i++)
            {
                TotAdjDist += Vector2.Distance(Convert2d(Road.Instance.XSecs[i].KerbR), Convert2d(Road.Instance.XSecs[i - 1].KerbR));
            }
            float delta = 0;
            for (int i = AdjStartIdx + 1; i <= AdjEndIdx; i++)
            {
                delta += Vector2.Distance(Convert2d(Road.Instance.XSecs[i].KerbR), Convert2d(Road.Instance.XSecs[i - 1].KerbR));
                float NewY = Mathf.SmoothStep(AdjStarty, AdjEndy, delta / TotAdjDist);
                float AdjY = NewY - Road.Instance.XSecs[i].KerbR.y;
                XSec  X    = new XSec(i);
                X.KerbR = new Vector3(0, AdjY, 0);
                Road.Instance.XSecs[i].Adjust(X);
            }
        }
    }
Пример #17
0
    void Update()
    {
        _speed     = _gps.Speed;
        _currXSec  = _gps.CurrXSec;
        PrevSegIdx = SegIdx;
        SegIdx     = _currXSec.Idx;
        if (CR_Running)
        {
            return;
        }
        if (Timer == 0)
        {
            Timer = 5;
        }
        Timer--;
        if (Timer != 4)
        {
            goto DoThisEveryFrame;
        }
        //This bit only runs every 5 frames
        _currBend         = _gps.CurrBend;
        _nextBend         = _gps.NextBend;
        _gpsNextBendAngle = _nextBend.Angle;
        SegFwdDir         = _currXSec.Forward;
        Vector3 Heading = transform.forward;

        HeadingAngle = Vector3.Angle(Heading, SegFwdDir);
        Vector3 cross = Vector3.Cross(Heading, SegFwdDir);

        if (cross.y > 0)
        {
            HeadingAngle = -HeadingAngle;
        }
        //Postition across the cross sec
        Vector3 L = Road.Instance.XSecs[SegIdx].KerbL;
        Vector3 R = Road.Instance.XSecs[SegIdx].KerbR;

        DistFromLKerb = Vector3.Distance(_currXSec.KerbL, transform.position);
        DistFromRKerb = Vector3.Distance(_currXSec.KerbR, transform.position);

        _bendPhase = BendPhase.Straight;

        int  ApproachSegs    = Mathf.RoundToInt(0.5f * _speed * _speed + _speed / 2);
        XSec _approachXSec   = Rd.XSecs[SegIdx + ApproachSegs];
        XSec _decisionXSec   = Rd.XSecs[SegIdx + Mathf.RoundToInt(_speed * 2)];
        bool FirstHalfOfBend = _currBend != null && _currXSec.IsBefore(_currBend.ApexXSec);

        if (!FirstHalfOfBend)
        {
            _approachBend = _nextBend;

            if (_approachBend.TurninXSec.IsBefore(_approachXSec))
            {
                _bendPhase = BendPhase.Approach;
                SpeedAdj   = 1f;
                DriftAngle = _approachBend.DriftAngle * Mathf.Pow(TurnInSpeed / _approachBend.Speed, 2.8f) * _approachBend.Sign; //this is cool

                //Slide the Adjusted turnin point along the gate
                SlideFrac = Mathf.Sqrt(Mathf.Clamp01(TurnInSpeed / _nextBend.Speed)); // - Mathf.Abs(Mathf.Sin(DriftAngle)) * 1.5f); //SlideFrac=1 for a big swingout
                //Debug.Log("SlideFrac=" + TurnInSpeed  + "/" + _nextBend.Speed + "=" + SlideFrac);
                AdjustedTurninPt   = Vector3.Lerp(_nextBend.MinTurninPos, _nextBend.TurninPos, SlideFrac);
                AdjustedTurninXSec = Rd.XSecs[Mathf.RoundToInt(Mathf.Lerp(_nextBend.StartSegIdx, _nextBend.TurninSegIdx, SlideFrac))];

                CalcBrakePoint();

                //Have we reached the decision point? We only decide the flickSegs once we reach the decision point
                if ((_approachBend.TurninXSec.IsBefore(_decisionXSec) && FlickXSec == null) || (FlickXSec != null && _currXSec.IsOnOrBefore(FlickXSec)))
                {
                    FlickSegs       = 0;
                    ReachedFlickEnd = false;
                    //This is the basic flickseg pre-calculation = 150/Radius*FlickSegMultiplier
                    FlickSegs = _approachBend.FlickSegs;
                    //Are we approaching at an angle or spinning?
                    float FlickSegAdj = Rd.XSecs.Diff(AdjustedTurninXSec, _approachBend.ApexXSec) * (TurnInSpeed - _approachBend.Speed) / _approachBend.Speed; // (HeadingAngle + _rb.angularVelocity.y * 20) * _approachBend.FlickSegsMultiplier * -_approachBend.Sign;
                    //if (_approachBend.Type == BendType.Right) FlickSegAdj = -FlickSegAdj;
                    //Debug.Log("FlickSegs = " + FlickSegs + "   FlickSegAdj=(" + Rd.XSecs.Diff(AdjustedTurninXSec, _approachBend.ApexXSec) + " * " + (TurnInSpeed - _approachBend.Speed) / _approachBend.Speed + " = " + FlickSegAdj + "\nTotal=" + (FlickSegs + FlickSegAdj));
                    FlickSegs += FlickSegAdj;
                    //Too slow, the flick will be too harsh
                    //Debug.Log("FlickSegs*=" + TurnInSpeed + "^2/225=" + FlickSegs);
                    //Wrong siede of the road
                    if (_approachBend.Type == BendType.Right ? (DistFromLKerb > DistFromRKerb) : (DistFromRKerb > DistFromLKerb))
                    {
                        FlickSegs = 0;
                    }
                    //Is there a long curve on the turnin?
                    //Debug.Log("TurninCurve=" + Vector3.Angle(_approachBend.StartXSec.Forward, _approachBend.TurninXSec.Forward) + "\nFlickSegs=" + FlickSegs);
                    //RequiredRotation worked ok but didnt take into account the initial rotation
                    //float RequiredRotation = Vector3.Angle(transform.forward, _approachBend.ApexXSec.Forward);
                    //FlickXSec = Rd.XSecs[Mathf.RoundToInt(_approachBend.TurninSegIdx - Mathf.Abs(RequiredRotation) / 2.8f)];
                    FlickXSec = Rd.XSecs[AdjustedTurninXSec.Idx - Mathf.RoundToInt(FlickSegs)];
                } //End of Decision

                if (_currXSec.IsAfter(BrakeXSec) && _currXSec.IsBefore(FlickXSec))
                {
                    _bendPhase = BendPhase.Brake;
                }
                if (FlickXSec != null && _currXSec.IsAfter(FlickXSec))
                {
                    _bendPhase = BendPhase.Turnin;
                }

                PrevFrac = SlideFrac; //used in the turnin
            }//end if Approach
        }                             //end if !FirstHalfOfBend
        else
        {                             //if FIrstHalfOfBend
            _approachBend = _currBend;
            _bendPhase    = BendPhase.Turnin;
        }
        if (_currBend != null && !FirstHalfOfBend)
        {
            if (_bendPhase != BendPhase.Approach)
            {
                _bendPhase = BendPhase.Exit; FlickXSec = null;
            }
        }

        if (_bendPhase == BendPhase.Straight)
        {
            Vector3 _apprXSecFwd = _approachXSec.Forward;
            float   _curveAngle  = Vector3.Angle(SegFwdDir, _apprXSecFwd);
            if (Vector3.Cross(SegFwdDir, _apprXSecFwd).y > 0)
            {
                _curveAngle = -_curveAngle;
            }
            if (_curveAngle > 15)
            {
                _bendPhase = BendPhase.LCurve;
            }
            if (_curveAngle < -15)
            {
                _bendPhase = BendPhase.RCurve;
            }
        }
        //************************************************************************************************
DoThisEveryFrame:

        AimPoint      = Rd.XSecs[SegIdx + 20].MidPt;
        SteerOverride = null;

        if (_bendPhase == BendPhase.Approach)
        {
            Accel = 1; BrakeForce = 0;
            float AvgApprSpeed  = (_speed + LiftOffSpeed) / 2;
            float TimeToBrakePt = DistToBrakePt / AvgApprSpeed;

            //Aim for half the dist to the turnin
            XSec    AimXSec = Rd.XSecs[_currXSec.Idx + Rd.XSecs.Diff(_currXSec, AdjustedTurninXSec) / 2];
            Vector3 T       = (AimXSec.KerbR - AimXSec.KerbL).normalized * _approachBend.TurninGap;

            if (_approachBend.Type == BendType.Right)
            {
                if (TimeToBrakePt < 1)
                {
                    SlideFrac = DistFromRKerb / (DistFromLKerb + DistFromRKerb - _approachBend.TurninGap);
                }
                AimPoint = Vector3.Lerp(AimXSec.KerbR, AimXSec.KerbL + T, SlideFrac);
            }
            else
            {
                if (TimeToBrakePt < 1)
                {
                    SlideFrac = DistFromLKerb / (DistFromLKerb + DistFromRKerb - _approachBend.TurninGap);
                }
                AimPoint = Vector3.Lerp(AimXSec.KerbL, AimXSec.KerbR - T, SlideFrac);
            }

            //I abandoned this because it never had time to straighten up
            /// <image url="$(SolutionDir)\CommonImages\SCurve.png" scale="0.7"/>
        }

        if (_bendPhase == BendPhase.Brake)
        {
            Accel    = 0; BrakeForce = 1;
            AimPoint = (AdjustedTurninPt + transform.position + transform.forward) / 2;
        }

        int   SegsToApex = 0;
        float diff       = 0;


        if (_bendPhase == BendPhase.Turnin)
        {
            float TotSegsToApex = Rd.XSecs.Diff(AdjustedTurninXSec, _approachBend.ApexXSec);
            float SegFrac       = 1 - SegsToApex / TotSegsToApex;
            //SegFrac starts at 0 at the turninPt and ends at 1 at the apex
            float TotalRequiredRotation = VectGeom.SignedAngle(AdjustedTurninXSec.Forward, _approachBend.ApexXSec.Forward) + DriftAngle;
            float CurrRotation          = VectGeom.SignedAngle(AdjustedTurninXSec.Forward, transform.forward);
            float da = (Mathf.Abs(DriftAngle) < 20 && SegFrac > 0.5f) ? DriftAngle / 2 : DriftAngle;
            float RequiredRotation = VectGeom.SignedAngle(transform.forward, _approachBend.ApexXSec.Forward) + DriftAngle;
            SegsToApex = Rd.XSecs.Diff(_currXSec, _approachBend.ApexXSec);
            float TimeToApex         = SegsToApex / _gps.SegsPerSec;
            float ProjectedRotation  = _rb.angularVelocity.y * 57.3f * TimeToApex;
            float ProjectedRotation2 = CurrRotation / SegFrac;
            diff = ProjectedRotation - RequiredRotation;

            Accel = 1; BrakeForce = 0;
            if (_speed < 8)
            {
                AimPoint = _approachBend.Type == BendType.Right ? Rd.XSecs[SegIdx + 10].MidRight : Rd.XSecs[SegIdx + 10].MidLeft; BrakeForce = 0;
            }
            else
            {
                AimPoint = _approachBend.ApexPos;

                //Debug.Log("rotdiff=" + ProjectedRotation + " - " + RequiredRotation + " = " + diff);
                if (_approachBend.Type == BendType.Right)
                {
                    /*
                     * //Manage the Fractional Distance
                     * if (PrevSegIdx != SegIdx)
                     * {
                     *  FracPerSeg = (Frac - PrevFrac) / (SegIdx - PrevSegIdx);
                     *  ProjectedFrac = Frac + FracPerSeg * SegsToApex;
                     *  //Debug.Log("ProjectedFrac=" + ProjectedFrac);
                     *  PrevFrac = Frac;
                     * }
                     */

                    //Stop understeer
                    if (diff < 0)
                    {
                        BrakeForce = Mathf.Clamp01(-diff / 80); Accel = 1 - BrakeForce; SteerOverride = 40;
                    }
                    if (diff < -40)
                    {
                        BrakeForce = Mathf.Clamp01(-diff / 40); Accel = 1;
                    }
                    if (_rb.angularVelocity.y < 0)
                    {
                        BrakeForce = 0; AimPoint = _approachBend.ApexPos;
                    }                                                                                    //stop the backskid
                }
                if (_approachBend.Type == BendType.Left)
                {
                    if (diff > 0)
                    {
                        BrakeForce = Mathf.Clamp01(diff / 80); Accel = 1 - BrakeForce; SteerOverride = -40;
                    }
                    if (diff > 40)
                    {
                        BrakeForce = Mathf.Clamp01(diff / 40); Accel = 1;
                    }
                    if (_rb.angularVelocity.y > 0)
                    {
                        BrakeForce = 0; AimPoint = _approachBend.ApexPos;
                    }                                                                                    //stop the backskid
                    //if (SegsToApex > 40) { BrakeForce = 0; Accel = 1; AimPoint = Rd.XSecs[SegIdx + 10].MidPt; }  //Stop the serious oversteer
                }
            }
        }
        if (_bendPhase == BendPhase.Exit)
        {
            Accel = 1;
            Vector3 _transverse   = (_currXSec.KerbR - _currXSec.KerbL).normalized;
            float   SpeedTwdRKerb = Vector3.Dot(_rb.velocity, _transverse);
            //Debug.Log("SpeedTwdKerb=" + SpeedTwdRKerb);
            AimPoint = _currBend.ExitPos; BrakeForce = 0;
            if (_currBend.Type == BendType.Right)
            {
                if (Rd.XSecs.Diff(_currXSec, _currBend.ExitXSec) > 5)
                {
                    AimPoint = _currBend.ExitXSec.MidRight;
                }
            }
            if (_currBend.Type == BendType.Left)
            {
                if (Rd.XSecs.Diff(_currXSec, _currBend.ExitXSec) > 5)
                {
                    AimPoint = _currBend.ExitXSec.MidLeft;
                }
            }
        }

        XSec    LongAimXSec  = Rd.XSecs[SegIdx + 40];
        Vector3 LongAimPoint = LongAimXSec.MidPt;

        if (_bendPhase == BendPhase.Straight)
        {
            Accel = 1; BrakeForce = 0;
            if (_nextBend == null)
            {
                Debug.Log("nbnull");
            }
            if (_nextBend.Type == BendType.Right)
            {
                AimPoint = Rd.XSecs[SegIdx + 20].MidLeft;
            }
            else
            {
                AimPoint = Rd.XSecs[SegIdx + 20].MidRight;
            }
        }
        if (_bendPhase == BendPhase.RCurve)
        {
            Accel = 1; BrakeForce = 0; AimPoint = Rd.XSecs[SegIdx + 20].MidRight;
        }
        if (_bendPhase == BendPhase.LCurve)
        {
            Accel = 1; BrakeForce = 0; AimPoint = Rd.XSecs[SegIdx + 20].MidLeft;
        }

        //steer round the car in front
        Vector3 FrontOfCar = transform.position + transform.up * 0.5f + transform.forward * 2.5f;

        CollisionRay = new Ray(FrontOfCar, AimPoint + Vector3.up - FrontOfCar);
        int layerMask = (1 << 8);

        if (Physics.Raycast(CollisionRay, out CollisionHit, 50, layerMask))
        {
            if (CollisionHit.collider.name != this.name && CollisionHit.collider.name != "ColldrF")
            {
                if (CollisionHit.rigidbody.velocity.sqrMagnitude < 1)
                {
                    StartCoroutine(ThreePointTurn("R"));
                }
                else
                {
                    AimPoint = Rd.XSecs[SegIdx + 10].MidRight;
                }
            }
        }
        //Debug.DrawRay(FrontOfCar, AimPoint + Vector3.up - FrontOfCar, Color.red);

        //**************************************************************************************
        //Coming up to a hill, put your foot down
        if (LongAimPoint.y - SegFwdDir.y > 0)
        {
            //Accel = ((LongAimPoint.y - SegFwdDir.y) * 0.005f) + 0.9f;
        }

        //coming up to a hill bend slow down
        if (Mathf.Abs(_gpsNextBendAngle) > 10 && _gps.NextHill > 2 && _gps.Speed > 10)
        {
            // Accel = 0; BrakeForce = 0.5f;
        }

        //***********************************************************************************


        // Pointing towards kerb - do a 3 point turn
        if (HeadingAngle > -100 && HeadingAngle < -80 && DistFromLKerb < 3)
        {
            StartCoroutine(ThreePointTurn("L"));
            return;
        }
        if (HeadingAngle < 100 && HeadingAngle > 80 && DistFromRKerb < 3)
        {
            StartCoroutine(ThreePointTurn("R"));
            return;
        }

        if (SteerOverride == null)
        {
            //Steer towards the aim point
            float   DesiredHeadingAngle = Vector3.Angle(AimPoint - transform.position, SegFwdDir);
            Vector3 crossDes            = Vector3.Cross(AimPoint - transform.position, SegFwdDir);
            if (crossDes.y > 0)
            {
                DesiredHeadingAngle = -DesiredHeadingAngle;
            }

            //Positive steer = right
            Steer = (DesiredHeadingAngle - HeadingAngle);
        }
        else
        {
            Steer = (float)SteerOverride;
        }

        //if (_bendPhase == BendPhase.Flick) Steer = _gpsNextBendAngle > 0 ? 40 : -40;
        if (_opponentCollisionDirec == CollisionDirection.Left && Steer < 0)
        {
            Steer = 10;
        }
        if (_opponentCollisionDirec == CollisionDirection.Right && Steer > 0)
        {
            Steer = -10;
        }

        if (_playerCollision)
        {
            if (Time.time - _playerCollisionTime > 3)
            {
                if (_playerGPS.IsOnRoad)
                {
                    if (!_gps.IsOnRoad)
                    {
                        Main.Instance.PopupMsg("Road Rage Bonus\n$20", Color.red);
                        Race.Current.HogBonus += 20;
                        UserDataManager.Instance.Data.Coins += 10;
                    }
                    else if (_playerGPS.CurrSegIdx - _gps.CurrSegIdx > 12 && _playerGPS.CurrSegIdx - _gps.CurrSegIdx < 100)
                    {
                        int pts = (_playerGPS.CurrSegIdx - _gps.CurrSegIdx) / 6;
                        Race.Current.HogBonus += pts;
                        Main.Instance.PopupMsg("Road Hog Bonus\n$" + pts.ToString(), Color.red);
                        UserDataManager.Instance.Data.Coins += pts;
                    }
                }
                _playerCollision = false;
            }
        }

        _inputBuffer.RecordInput(Accel, BrakeForce, Steer, Time.time);
    }
Пример #18
0
    /// <summary>
    /// Used for ChaseCamera to stop it flying upwards
    /// </summary>

    /// <summary>
    /// Calculate the fence vertices after the control point
    /// </summary>
    public void CalcVisibleFenceVerts()
    {
        //This uses the XSecs to fill the two lists LFenceVerts and RFenceVerts
        //These are used to create the two gameobjects, LFence and RFence
        //The verts are always 3m apart.
        RaycastHit _hit;

        if (Segments.Count > 1)
        {
            Road Rd = Road.Instance;
            LFenceVerts.Clear();
            RFenceVerts.Clear();


            List <Vector3> LKerbs = (from x in Rd.XSecs
                                     where x.Idx >= Segments[0].Idx && x.Idx <= Segments.Last().Idx + 1
                                     select x.KerbL).ToList <Vector3>();
            if (RoadMaterial == "Air")
            {
                LKerbs = LKerbs.Select(k => Gnd(k)).ToList();
            }
            //See I added the first xsec of the next section
            //if (Rd.Sectns[Idx + 1].Segments.Count==0) return;                              //So we don't try to calculate for the last section
            Vector3 CurrPos = LKerbs[0];
            LFenceVerts.Add(CurrPos);
            int   NxtKerbIdx = 1;
            float SegLength;
            float TotDist;
            float Bckdist;
            float DistRem = Vector3.Distance(CurrPos, LKerbs.Last());
            while (DistRem > 3.0f)
            {
                //Find the next kerb point 3 meters along
                SegLength = 0;
                TotDist   = Vector3.Distance(CurrPos, LKerbs[NxtKerbIdx]);
                if (TotDist > 3)
                {
                    SegLength = Vector3.Distance(CurrPos, LKerbs[NxtKerbIdx]);
                }
                while (TotDist < 3)
                {
                    CurrPos = LKerbs[NxtKerbIdx];
                    //Yeah but the air road fences should be on the ground

                    NxtKerbIdx++;
                    SegLength = Vector3.Distance(CurrPos, LKerbs[NxtKerbIdx]);
                    TotDist  += SegLength;
                } //Now we've got to the KerbPoint after the 3m mark.
                //We have to go backward to the 3m mark
                Bckdist = TotDist - 3;
                CurrPos = Vector3.Lerp(LKerbs[NxtKerbIdx], CurrPos, Bckdist / SegLength);
                LFenceVerts.Add(CurrPos);
                DistRem = Vector3.Distance(CurrPos, LKerbs.Last());
            }
            //Add the first kerb point of the next section
            XSec LastXSec = Rd.XSecs[Segments.Last().Idx];
            LFenceVerts.Add(RoadMaterial == "Air"? Gnd(Rd.XSecPlusOne(LastXSec).KerbL): Rd.XSecPlusOne(LastXSec).KerbL);

//Right Kerbs
            List <Vector3> RKerbs = (from x in Rd.XSecs
                                     where x.Idx >= Segments[0].Idx && x.Idx <= Segments.Last().Idx + 1 //See I added the first xsec of the next section
                                     select x.KerbR).ToList <Vector3>();
            if (RoadMaterial == "Air")
            {
                RKerbs = RKerbs.Select(k => Gnd(k)).ToList();
            }

            CurrPos = RKerbs[0];
            RFenceVerts.Add(CurrPos);
            NxtKerbIdx = 1;
            DistRem    = Vector3.Distance(CurrPos, RKerbs.Last());
            while (DistRem > 3.0f)
            {
                //Find the next kerb point 3 meters along
                SegLength = 0;
                TotDist   = Vector3.Distance(CurrPos, RKerbs[NxtKerbIdx]);
                if (TotDist > 3)
                {
                    SegLength = Vector3.Distance(CurrPos, RKerbs[NxtKerbIdx]);
                }
                while (TotDist < 3)
                {
                    CurrPos = RKerbs[NxtKerbIdx];
                    NxtKerbIdx++;
                    SegLength = Vector3.Distance(CurrPos, RKerbs[NxtKerbIdx]);
                    TotDist  += SegLength;
                } //Now we've got to the KerbPoint after the 3m mark.
                //We have to go backward to the 3m mark
                Bckdist = TotDist - 3;
                CurrPos = Vector3.Lerp(RKerbs[NxtKerbIdx], CurrPos, Bckdist / SegLength);
                RFenceVerts.Add(CurrPos);
                DistRem = Vector3.Distance(CurrPos, RKerbs.Last());
            }
            RFenceVerts.Add(RoadMaterial == "Air" ? Gnd(Rd.XSecPlusOne(LastXSec).KerbR): Rd.XSecPlusOne(LastXSec).KerbR);
        }
    }
Пример #19
0
    void Update()
    {
        if (CR_Running)
        {
            return;
        }
        if (Timer == 0)
        {
            Timer = 10;
        }
        Timer--;
        if (Timer != 0)
        {
            return;
        }
        Accel           = 0.9f;
        BrakeForce      = 0;
        Steer           = 0;
        SegIdx          = _gps.CurrSegIdx;
        _gpsNextBend    = _gps.NextBend;
        _gpsCurrentBend = _gps.CurrBend;
        //Vector3 B = Road.Instance.Segments[SegIdx].verts[4];
        Vector3 SegFwdDir = Road.Instance.XSecs[SegIdx].Forward;
        Vector3 Heading   = transform.forward;

        HeadingAngle = Vector3.Angle(Heading, SegFwdDir);
        Vector3 cross = Vector3.Cross(Heading, SegFwdDir);

        if (cross.y > 0)
        {
            HeadingAngle = -HeadingAngle;
        }
        //Postition across the cross sec
        Vector3 L             = Road.Instance.XSecs[SegIdx].KerbL;
        Vector3 R             = Road.Instance.XSecs[SegIdx].KerbR;
        float   DistFromLKerb = Vector3.Distance(L, transform.position);
        float   DistFromRKerb = Vector3.Distance(R, transform.position);
        //Calculate entry speed for next bend
        float _entrySpeed = Mathf.Abs(50 / _gpsNextBend.AnglePerSeg);

        //Coming into a sharp bend too fast slow down
        if (_gps.SegsPerSec - _entrySpeed > (_gpsNextBend.StartSegIdx > _gps.CurrSegIdx?_gpsNextBend.StartSegIdx - _gps.CurrSegIdx: _gpsNextBend.StartSegIdx + Rd.Segments.Count - _gps.CurrSegIdx))
        {
            Accel = 0; BrakeForce = 1f;
        }
        else
        {
            Accel = 1; BrakeForce = 0;
        }


        //Aim for the middle of the 10th segment in front
        XSec    AimSec   = Road.Instance.XSecCircular(SegIdx + 20);
        Vector3 AimPoint = AimSec.MidPt;

        Vector3 LongAimPoint = Road.Instance.XSecCircular(SegIdx + 40).MidPt;

        //steer round the car in front
        Vector3 FrontOfCar = transform.position + transform.up * 0.5f + transform.forward * 2.5f;

        _collisionRay = new Ray(FrontOfCar, AimPoint + Vector3.up - FrontOfCar);
        int layerMask = (1 << 8);

        if (Physics.Raycast(_collisionRay, out CollisionHit, 50, layerMask))
        {
            if (CollisionHit.collider.name != this.name)
            {
                if (CollisionHit.rigidbody.velocity.sqrMagnitude < 1)
                {
                    StartCoroutine(ThreePointTurn("R"));
                }
                else
                {
                    AimPoint = (Road.Instance.XSecCircular(SegIdx + 10).MidPt + Road.Instance.XSecCircular(SegIdx + 10).KerbR) / 2;
                }
            }
        }
        //Debug.DrawRay(FrontOfCar, AimPoint + Vector3.up - FrontOfCar, Color.red);

        //***********************************************************************************
        //Steer towards the aim point
        float   DesiredHeadingAngle = Vector3.Angle(AimPoint - transform.position, SegFwdDir);
        Vector3 crossDes            = Vector3.Cross(AimPoint - transform.position, SegFwdDir);

        if (crossDes.y > 0)
        {
            DesiredHeadingAngle = -DesiredHeadingAngle;
        }

        // Pointing towards kerb - do a 3 point turn
        if (HeadingAngle > -100 && HeadingAngle < -80 && DistFromLKerb < 3)
        {
            StartCoroutine(ThreePointTurn("L"));
            return;
        }
        if (HeadingAngle < 100 && HeadingAngle > 80 && DistFromRKerb < 3)
        {
            StartCoroutine(ThreePointTurn("R"));
            return;
        }

        //Coming up to a hill, put your foot down
        if (LongAimPoint.y - AimPoint.y > 0)
        {
            Accel = ((LongAimPoint.y - AimPoint.y) * 0.005f) + 0.9f;
        }


        //coming up to a hill bend slow down
        if (Mathf.Abs(_gpsNextBend.Angle) > 10 && _gps.NextHill > 2 && _gps.Speed > 10)
        {
            Accel = 0; BrakeForce = 0.5f;
        }

        //Positive steer = right
        Steer = (DesiredHeadingAngle - HeadingAngle) * 1.5f;

        //Start of bend - flick the wheel

        /*if ((_gpsNextBend.StartSegIdx - _gps.SegIdx) / _gps.SegsPerSec < 0.5f)
         * {
         *  Steer += (1.5f * _gpsNextBend.AnglePerSeg * _gps.SegsPerSec);
         * }
         * if ((_gps.SegIdx - _gpsCurrentBend.StartSegIdx) / _gps.SegsPerSec < 5f)
         * {
         *  Steer += (_gpsCurrentBend.AnglePerSeg * _gps.SegsPerSec);
         * }*/

        if (_opponentCollisionDirec == CollisionDirection.Left && Steer < 10)
        {
            Steer = 10;
        }
        if (_opponentCollisionDirec == CollisionDirection.Right && Steer > -10)
        {
            Steer = -10;
        }
    }