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. ![]()
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.