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); }
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; } }
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); }