Anti gravity racing: the sequel

Good. As the saying goes, premature optimization is the root of all evil.

With regards to the script, I chose to do the multiple raycasts by using an array (of custom RayCastObject wrappers) instead of hard-coding individual passes. It’s easier to write, easier to extend, and harder to pass buoyancyCentreOffset1 to all four action points. :wink:

Now, as a reference for all the people who have asked, and all the people yet to ask, here’s the script that I used:

// Version 5 of the anti-gravity sctipt
// Fun.

var acceptUserInput = true;
var rayArray : RayCastObject[];
var speed = 1.0;

class RayCastObject
{
	var drawingColor : Color;
	var direction : Vector3;
	var origin : Vector3;
	var hitData : RaycastHit;
	var distance : float;
		
	function DrawRay (object : Transform)
	{
		Gizmos.color = drawingColor;
		//Gizmos.DrawLine(object.TransformPoint(direction+origin), object.TransformPoint(origin));
		Gizmos.DrawRay(object.TransformPoint(origin),object.TransformDirection(direction));
		//Debug.DrawLine((direction)+origin+object.position, origin+object.position, drawingColor);
	}
	
	function Raycast (object : Transform)
	{
		return Physics.Raycast(object.TransformPoint(origin),object.TransformDirection(direction), hitData, distance);
	}
}


function OnDrawGizmos ()
{
	for (var ray in rayArray)
		ray.DrawRay(transform);
}

function FixedUpdate ()
{
	var gravityUp : Vector3;
	var distanceFromTrack : float;
	for (var ray in rayArray)
	{
		if (ray.Raycast(transform))
		{
			gravityUp += InterpolateNormal(ray.hitData);
			
			distanceFromTrack += -ray.hitData.distance + (ray.distance/2);
			
			//distanceFromTrack += ray.hitData.distance;
			Debug.DrawRay(ray.hitData.point,InterpolateNormal(ray.hitData), Color.cyan);
		}
	}
	
	//Average
	gravityUp = gravityUp/rayArray.Length;
	gravityUp.Normalize(); //Is this really needed?
	distanceFromTrack = distanceFromTrack/rayArray.Length;
	
	//Rotate
	transform.rotation = Quaternion.FromToRotation(transform.up, gravityUp) * transform.rotation;
	if(acceptUserInput)
		transform.Rotate(0,1.5 * Mathf.Clamp(Input.GetAxis("Horizontal") + Input.GetAxis("Mouse X"),-1,1),0); //After previous statement to run slightly faster
	
	//Repel
	transform.position = transform.position + (distanceFromTrack * transform.up);
	
	if(acceptUserInput)
		rigidbody.AddRelativeForce(Vector3.forward * Input.GetAxis("Vertical") * (Input.GetAxis("Vertical") > 0 ? speed : (speed/2)), ForceMode.Impulse);
	
	//transform.Translate(Vector3.forward * Input.GetAxis("Vertical"));
	
}


function InterpolateNormal (hit : RaycastHit)
{
	var meshCollider = hit.collider as MeshCollider; 
	if (meshCollider == null || meshCollider.sharedMesh == null) 
		return; 
	
	var mesh : Mesh = meshCollider.sharedMesh; 
	var normals = mesh.normals; 
	var triangles = mesh.triangles; 
	
	// Extract local space normals of the triangle we hit 
	var n0 = normals[triangles[hit.triangleIndex * 3 + 0]]; 
	var n1 = normals[triangles[hit.triangleIndex * 3 + 1]];    
	var n2 = normals[triangles[hit.triangleIndex * 3 + 2]];    
    
	// interpolate using the barycentric coordinate of the hitpoint 
	var baryCenter = hit.barycentricCoordinate; 
	
	// Use barycentric coordinate to interpolate normal 
	var interpolatedNormal = n0 * baryCenter.x + n1 * baryCenter.y + n2 * baryCenter.z; 
	// normalize the interpolated normal 
	interpolatedNormal =  interpolatedNormal.normalized; 
    
	// Transform local space normals to world space 
	var hitTransform : Transform = hit.collider.transform; 
	interpolatedNormal = hitTransform.TransformDirection(interpolatedNormal);
	
	return interpolatedNormal;
}

I hope it helps.