protected void UpdateTrackSlider(out SimpleTransform trackTangent) { //number of times we've "recursed" (emulated with a goto) int iterations = 0; Transform cartTransform = transform; // Transform cartTransform = guide.transform; //Estimate where we'll be in about a frame or so - this allows us to "lead" //the constraint's position and minimize error Vector3 tickMovement = cartTransform.GetComponent <Rigidbody>().velocity *leadFactor *Time.deltaTime; SimpleTransform carSoonPos = new SimpleTransform(cartTransform); carSoonPos.position += tickMovement; if (DebugDrawTracking) { Debug.DrawRay(carSoonPos.position, Vector3.up, Color.yellow); Debug.DrawRay(cartTransform.position, Vector3.up, Color.white); } //DEBUG("now: " << m_rbB.getWorldTransform().position << " mv: " << tickMovement << " predicted: " << (carSoonPos.position + tickMovement)); //goto label used to emulate a stateful tail-end recursion //todo: cars shouldn't be jumping far enough to need tail-end recursion, switch to a closure Profiler.BeginSample("Find position"); calculate: Track track = _currentTrack; //Position of cart var localCartPos = track.transform.InverseTransformPoint(carSoonPos.position); Profiler.BeginSample("Get current point"); float pos = track.Curve.GetFraction(localCartPos); Profiler.EndSample(); if (pos < 0) { //before the start //DEBUG("Before the start"); if (track.PrevTrack && iterations == 0) { //Move to the next track and run as that track RollToNextTrack(false); ++iterations; goto calculate; } else if (track.PrevTrack) { //we've hit the iteration limit, just go straight until next frame pos = 0; } else { //We're past the start with no previous. if (_currentTrack.outOfTrack == Track.EndOfLineBehavior.FallOffTrack) { //wait until it's clear of the track (so it doesn't intersect with it), then drop it off //(note that we use the cart's actual instead of projected position here) if (Vector3.Distance(track.transform.position, cartTransform.position) >= clearingDistance) { RemoveFromTrack(); } } else if (_currentTrack.outOfTrack == Track.EndOfLineBehavior.ContinueStraight) { //do nothing special here, just keep going } // In all cases, set our guide to line up with the start of the track. pos = 0; } } else if (pos > 1) { //past the end //DEBUG("After the end"); if (track.NextTrack && iterations == 0) { //Move to the next track and run as that track RollToNextTrack(true); ++iterations; goto calculate; } else if (track.NextTrack) { //we've hit the iteration limit, just go straight until next frame pos = 1; } else { //We're past the end with no next. if (_currentTrack.outOfTrack == Track.EndOfLineBehavior.FallOffTrack) { //wait until it's clear of the track (so it doesn't intersect with it), then drop it off if (Vector3.Distance(track.TrackAbsoluteEnd.position, cartTransform.position) >= clearingDistance) { RemoveFromTrack(); } } else if (_currentTrack.outOfTrack == Track.EndOfLineBehavior.ContinueStraight) { //do nothing special here, just keep going } // In all cases, set our guide to line up with the end of the track. pos = 1; } } else { //calculate position normally } Profiler.EndSample(); if (DebugDrawTracking) { var col = new Color(0, 0, 0, .3f); Debug.DrawLine(cartTransform.position, track.TrackAbsoluteEnd.position, col); Debug.DrawLine(cartTransform.position, track.transform.position, col); } //Debug.Log("d1: " + d1 + ", d2: " + d2 + " maxDist: " + maxDist); //Get position and direction at this point on the track Profiler.BeginSample("Get exact point"); trackTangent = track.Curve.GetPointAt(pos).LocalToAbsolute(track.transform); Profiler.EndSample(); if (cartReversed) { trackTangent.AboutFace(); } if (DebugDrawTracking && _currentTrack) { //(these two should be more-or-less on top of each other, if there's a big divergence we have an issue) Debug.DrawRay(guide.transform.position, guide.transform.rotation * Vector3.forward, Color.red); Debug.DrawRay(guide.transform.position, guide.transform.rotation * Vector3.up, Color.blue); Debug.DrawRay(trackTangent.position, trackTangent.rotation * Vector3.forward, Color.red); Debug.DrawRay(trackTangent.position, trackTangent.rotation * Vector3.up, Color.blue); } //We tell the joint what rotation we want by feeding it two (unit) vectors. if (trackJoint) { //to trick Unity into recalculating the targeted internal transformations, we'll switch the rigidbody on the joint Rigidbody differentRb = guideJoint.connectedBody ? null : GetComponent <Rigidbody>(); Rigidbody originalRb = guideJoint.connectedBody; //switch rb so we can change things without fear guideJoint.connectedBody = differentRb; //move the guide to where we want it to be now guide.transform.position = trackTangent.position; guide.transform.rotation = trackTangent.rotation; //put the rb back as it should, causing Unity to recalculate the desired position for the joint guideJoint.connectedBody = originalRb; } }
public void SwitchCurrentSectionTo(Track track) { CurrentTrack = track; }
/** Sets our next track to "next" and moves our end to line up with its start. (Alias for SnapTogether(next, true, true).) */ public void ConnectTo(Track next) { SnapTogether(next, true, true); }