/// <summary> /// Get the rotation of a section. /// </summary> /// <param name="section"></param> /// <returns></returns> public static Quaternion SectionGetRotation(TrSection section) { // get positions Vector3 sectionPosition = section.SECTION_POSITION; Vector3 nextPosition = section.SECTION_NEXT.SECTION_POSITION; // get the forward direction from positions and then the normal Vector3 forward = (nextPosition - sectionPosition); Vector3 normal = section.SECTION_NORMAL; // return lookat return(Quaternion.LookRotation(forward.normalized, normal.normalized)); }
private void UpdateInitialSection() { // try to find track section using a raycast RaycastHit hit; if (Physics.Raycast(transform.position, -transform.up, out hit, 1000.0f, 1 << LayerMask.NameToLayer("TrackFloor"))) { int tri = hit.triangleIndex; TrTile tile = TrackDataHelper.TileFromTriangleIndex(hit.triangleIndex, E_TRACKMESH.FLOOR, RaceSettings.trackData.TRACK_DATA); TrSection section = tile.TILE_SECTION; bool canUpdate = true; if (section.SECTION_TYPE == E_SECTIONTYPE.JUMP_START) { onJump = true; expectedLandSection = section.SECTION_NEXT; } if (section.SECTION_TYPE == E_SECTIONTYPE.JUMP_END) { onJump = false; if (section != expectedLandSection) { canUpdate = false; } } if (canUpdate) { r.initialSection = section; iSectionIndex = section.SECTION_INDEX; r.currentSection = r.initialSection; cSectionIndex = section.SECTION_INDEX; } iSectionFound = true; } else { iSectionFound = false; } }
private void ShipGravity() { // get position and normal of current section TrSection current = r.currentSection; Vector3 trackPosition = current.SECTION_POSITION; Vector3 trackNormal = current.SECTION_NORMAL; if (r.position.onJump) { trackNormal = current.SECTION_NORMAL; } float ground = trackPosition.y; // reset grounded isShipGrounded = false; // get raycast origin (defaults to ship position unless on a jump) Vector3 raypos = transform.position; if (current.SECTION_TYPE == E_SECTIONTYPE.JUMP_START && r.input.ACTION_THRUST) { Vector3 landPos = current.SECTION_NEXT.SECTION_POSITION; raypos.x = landPos.x; raypos.z = landPos.z; } // do raycast RaycastHit hit; if (Physics.Raycast(raypos, -transform.up, out hit, r.settings.AG_HOVER_HEIGHT, 1 << LayerMask.NameToLayer("TrackFloor"))) { // return if not under hover height if (hit.distance > r.settings.AG_HOVER_HEIGHT) { return; } // set grounded isShipGrounded = true; // bottom out on track if (hit.distance < r.settings.AG_HOVER_HEIGHT * r.settings.AG_REBOUND_THRESHOLD && !hitTrack) { hitTrack = true; float hitForce = (Mathf.Abs(transform.InverseTransformDirection(r.body.velocity).y) * r.settings.AG_REBOUND_MULTIPLIER); if (hitForce >= 1) { r.body.AddForce(transform.up * hitForce, ForceMode.Impulse); r.PlayOneShot(r.settings.SFX_WALLHIT); } // Slow down ship very slightly Vector3 lv = transform.InverseTransformDirection(r.body.velocity); lv.z *= 0.95f; Vector3 wv = transform.TransformDirection(lv); r.body.velocity = wv; } // calculate hoverforce float compression = 1 - (hit.distance / r.settings.AG_HOVER_HEIGHT); float hoverForce = r.settings.AG_HOVER_HEIGHT - hit.distance; Vector3 spring = raypos - hit.point; float length = spring.magnitude; float displacement = length - r.settings.AG_HOVER_HEIGHT; Vector3 springN = spring / length; Vector3 restoreForce = springN * (displacement * (hoverForce * (r.settings.AG_HOVER_FORCE))); float force = transform.InverseTransformDirection(restoreForce).y; force -= transform.InverseTransformDirection(r.body.velocity).y *r.settings.AG_HOVER_DAMP; // apply hoverforce r.body.AddForce(-transform.up * force, ForceMode.Acceleration); } if (isShipGrounded) { // Apply Gravity gravityForce = r.settings.GRAVITY_FORCE / 2; r.body.AddForce(-Vector3.up * gravityForce); } else { float gravity = r.settings.GRAVITY_FORCE; gravityForce = Mathf.Lerp(gravityForce, gravity, Time.deltaTime * r.settings.GRAVITY_WEIGHT); // Apply Gravity r.body.AddForce(-Vector3.up * gravityForce); hitTrack = false; } // Respawn if under track if (transform.position.y < ground - r.settings.AG_HOVER_HEIGHT * 50) { r.isRespawning = true; } // Rotate Ship Quaternion wantedRotation = Quaternion.LookRotation(Vector3.Cross(transform.right, trackNormal), trackNormal); float rotationSpeed = r.settings.AG_ROTATION_SPEED; transform.rotation = Quaternion.Lerp(transform.rotation, wantedRotation, Time.deltaTime * rotationSpeed); transform.rotation = Quaternion.Euler(transform.eulerAngles.x, transform.eulerAngles.y, 0.0f); // Pitch pitchAmount = Mathf.Lerp(pitchAmount, r.input.AXIS_PITCH * r.settings.AG_PITCH_AMOUNT, Time.deltaTime * 3.0f); transform.Rotate(Vector3.right * (pitchAmount * Time.deltaTime)); }
private void FollowTrack() { // parent camera transform.parent = r.transform; // only follow track if current section exist if (r.currentSection == null) { return; } // position and rotate track helper (this is so we have a transform to work with) TrSection current = r.currentSection; Vector3 currentSegment = current.SECTION_POSITION; cameraHelper.transform.position = currentSegment; Quaternion currentRot = TrackDataHelper.SectionGetRotation(current); cameraHelper.transform.rotation = currentRot; // figure out the camera's offset to the track Vector3 cameraOffset = cameraHelper.transform.InverseTransformPoint(transform.position); // figure out which way the ship is facing and interpolate track direction dot product value to it Vector3 trackForward = cameraHelper.transform.forward; tcDirectionLag = Mathf.Lerp(tcDirectionLag, Vector3.Dot(transform.forward, trackForward), Time.deltaTime * (tcSpeed * 0.5f)); tcTrackOffset = Vector3.Lerp(tcTrackOffset, cameraOffset * tcDirectionLag, Time.deltaTime * (tcSpeed * 0.65f)); tcFinalOffset = Vector3.Lerp(tcFinalOffset, cameraOffset, Time.deltaTime * (tcSpeed * 0.65f)); // figure out which side of the track the camera is on (this is for positioning reasons) Vector3 trackSide = cameraHelper.transform.right; float sideDot = Vector3.Dot(transform.forward, trackSide); float sideFinal = Mathf.Sign(cameraOffset.x) * -Mathf.Sign(sideDot); // interpolate positions tcX = Mathf.Lerp(tcX, -tcTrackOffset.x * r.settings.CAMERA_OFFSET_SENSITIVITY.x, Time.deltaTime * (r.settings.CAMERA_OFFSET_SPEED.x)); tcY = Mathf.Lerp(tcY, Mathf.Abs(tcFinalOffset.x) * r.settings.CAMERA_OFFSET_SENSITIVITY.y, Time.deltaTime * (r.settings.CAMERA_OFFSET_SPEED.y * 0.15f)); tcZ = Mathf.Lerp(tcZ, (Mathf.Abs(cameraOffset.x) * r.settings.CAMERA_OFFSET_SENSITIVITY.z) * (sideFinal * (1 - Mathf.Abs(tcDirectionLag))), Time.deltaTime * (r.settings.CAMERA_OFFSET_SPEED.z * 0.4f)); // increase/decrease distance to ship on slopes float upDir = Vector3.Dot(Vector3.up, r.transform.forward); tcPitchOffset = Mathf.Lerp(tcPitchOffset, upDir * 0.2f, Time.deltaTime * tcSpeed); // fall Offsets if (r.sim.isShipGrounded) { tcFallTimer = 0; tcFallTimerGain = 0; } else { tcFallTimer += Time.deltaTime; } if (tcFallTimer > 0.2f) { tcFallTimerGain = Mathf.Lerp(tcFallTimerGain, 0.8f, Time.deltaTime); tcFallLagY = Mathf.Lerp(tcFallLagY, 0.4f, Time.deltaTime * tcFallTimerGain); tcFallLagZ = Mathf.Lerp(tcFallLagZ, -0.8f, Time.deltaTime * (tcFallTimerGain * 4)); } else { tcFallTimerGain = 0; tcFallLagY = Mathf.Lerp(tcFallLagY, 0.0f, Time.deltaTime * 4); tcFallLagZ = Mathf.Lerp(tcFallLagZ, 0.0f, Time.deltaTime * 4); } // apply camera offset transform.localPosition = new Vector3(r.settings.CAMERA_OFFSET_TRACK.x + tcX, r.settings.CAMERA_OFFSET_TRACK.y + tcY + tcFallLagY, r.settings.CAMERA_OFFSET_TRACK.z + tcZ + tcPitchOffset + tcFallLagZ); // update Rotation transform.rotation = r.transform.rotation; // update FoV r.cam.fieldOfView = 75.0f; }
/// <summary> /// Get all tiles in a section. /// </summary> /// <param name="section"></param> /// <returns></returns> public static TrTile[] SectionGetTiles(TrSection section) { return(section.SECTION_TILES); }