Faux Gravity making my brain spin... Help!

In the spirit of Mario Galaxy, I’m trying to replace the first person controller with a rigidbody that gravitates (and aligns) towards arbitrary objects.

Here’s what I’ve got so far (make a big sphere, stick something slightly above it, attach this script to it, and set its attractor to the sphere – you should be able to zoom around on the sphere):

Edit: the code posted here has been fixed – see below. I’ve removed the guts of this post so that no-one inadvertently uses the old, highly borked code.

Here’s where I’d like help:

Edit: note that these issues are all resolved in the code posted below.

  1. It’s very hard to move without jumping if the terrain isn’t smooth. How does the character controller overcome this without flying the rigidbody into space at rather slight provocations.

  2. This is subtler, but more annoying. I notice sometimes as I’m running around my little planet that my direction sometimes drifts slightly. But the WORST thing is that when I approach the south pole, I spin.

My knowledge of Quaternions is pretty poor, so I’m obviously doing something wrong.

  1. I’d really prefer to adjust my up vector more gradually in the face of sudden changes of gravity (it’s fine when the attractor doesn’t change, obviously, but it will suck if I switch attractors suddenly as in a certain Wii game). I’ve been messing with Slerp but … messing is the word and the result.

(I also want to be able to fly a spaceship to a planet, and have it “snap into” the gravitational field and behave like a plane while close to the planet.)

64558--2385--$picture_3_927.png

Edit: the code posted here has been fixed – see below. I’ve removed the guts of this post so that no-one inadvertently uses the old, highly borked code.

Another subtle issue.

When I start gameplay my object (currently a capsule) is slightly above the landscape and it falls to the ground and slightly through it, then suddenly corrects itself and is fine thereafter. Jumping does not cause this issue (so if I jump afterwards, there’s no problem.)

Any ideas why?

What if you used the built in function Rigidbody.AddExplosionForce

Just give it a negative force and center it at the planet’s core.

I’m not sure how you would handle orienting the character if they are jumping between 2 planets.

Actually I think my current code is probably less horrible than that :wink: But a neat idea.

I believe my code will work fine for jumping between planets … should have a demo soon.

In case you’re wondering …

I got all this working quite nicely, and then refactored it into:

FauxGravityAttractor – gizmo that exerts pull on objects; it resolves the pull and “upvector” stuff internally, so it could (theoretically) easily support non-spherical gravity (e.g. ring worlds, or local mono-directional gravity as seen in Mario Galaxy).

FauxGravityBody – objects that fall towards attractors. The simple version right now is that each body is only attached to one attractor at a time.

FauxGravitySwitch – objects that reassign objects to new attractors when a specific event (e.g. collision) occurs. The idea is to allow a spaceship fly up out of one planet’s gravity-field … into zero g … and then enter another gravity-field.

got it working!!!

I love this! Thanks for your work on it!
I’ll be changing it heavily, but what you’ve done here will help me a LOT!!!

most of the prefab camera scripts are -Y oriented, which breaks when you have a true orbital down direction.

I’ll be playing with the code to make a good third person camera.

trouble is, that the only thing I got working was a cube collider, so it tumbles over the sphere like dice. Which is fun. he he

I also made it ice, but then it just wouldn’t stop. ha ha

this is so cool, podperson!

This is going to be a lot of fun to tinker with.

ha ha ha!!!

this is a GREAT simulator. the box got tumbling fast enough to reach orbit! sooooo cool!

its still orbiting!

oh! the ideas I’m getting now!!!

Use a dummy-mediated camera, hai_ok.

not sre what you mean, but I’m all ears.

Attach a dummy (ie. empty game object) to the object that you want the camera to follow (ie. the player).

Position the dummy so as to look at the player from the distance and angle desired when standing still.

Program the camera to interpolate to the dummy’s position, using a fractional interpolation (eg. 5% per interpolation) so as to get a nice bit of lag and easing.

Works like a charm.

I was thinking like that, but I hadn’t got that together in my head just yet.

you’re right!

child the null (dummy) to the player.
mouse orbit the camera to the null.

I could even child a target out in front of the player for the camera to look at, so that the camera is always looking toward what the player is facing.

I know you are talking about doing this with code. I should try to think that way too.

Thanks!

podperson, can we see the new improved, refactored code please. :smile:

Thanks!

Here are my three gravity scripts – hopefully self-documenting :wink:

Basically, assign FauxGravityAttractor to each “planet” (or whatever) and assign FauxGravityBody to anything you want to move around on planets. I try to use the RigidBody properties where possible – so it respects mass, and makes objects with freezeRotation set self-righting. (So set freezeRotation to true for characters, but false for random objects.)

Note that I’ve got a “ground” layer set (10) for detecting whether an object is “grounded”.

/*
	FauxGravityBody.js
	Written by Tonio Loewald ©2008
	
	Attach this script to objects you want to be affected by FauxGravity
*/

// this is the thing we're gravitationally attracted to
var attractor : FauxGravityAttractor;

// are we touching the surface?
var grounded : int;

function Start () {
	rigidbody.WakeUp();
	rigidbody.useGravity = false;
}

// obviously this is crude since we might want to be able to stand on (and jump off) random objects
// should probably filter based on tag in future
function OnCollisionEnter (c : Collision) {
	if( c.gameObject.layer == 10 ){
		grounded ++;
	}
}

function OnCollisionExit (c : Collision) {
	if( c.gameObject.layer == 10  grounded > 0 ){
		grounded --;
	}
}

function FixedUpdate () {
	if(attractor){
		attractor.Attract(this);
	}
}

@script RequireComponent(Rigidbody)
/* 
	FauxGravityAttractor.js
	Written by Tonio Loewald a©2008
	
	Attach this script to objects you want to exert Faux Gravity
*/

// Set to true for mono-directional gravity
var useLocalUpVector : boolean = false;

// Force applied along gravity up-vector (negative = down)
var fauxGravity = -10.0;

function Attract ( body : FauxGravityBody ){
	var gravityUp : Vector3;
	var localUp: Vector3;
	var localForward : Vector3;
	
	var t : Transform = body.transform;
	var r : Rigidbody = body.rigidbody;

	// Figure out the body's up vector
	if(useLocalUpVector){
		gravityUp = transform.up;	
	} else {
		gravityUp = t.position - transform.position;
		gravityUp.Normalize();
	}
	
	// Accelerate the body along its up vector
	r.AddForce( gravityUp * fauxGravity * r.mass );
	r.drag = body.grounded ? 1 : 0.1;
	
	// If the object's freezerotation is set, we force the object upright
	if(r.freezeRotation){
		// Orient relatived to gravity
		localUp = t.up;
		var q = Quaternion.FromToRotation(localUp, gravityUp);
		q = q * t.rotation;
		t.rotation = Quaternion.Slerp(t.rotation, q, 0.1);
		localForward = t.forward;
	}
}
/*
	Faux Gravity Switch
	Written by Tonio Loewald ©2008
	
	This is a simple example of a script which switches Faux Gravity attractors
*/

var OnEnterActive : boolean = false;
var OnEnterSetAttractor : FauxGravityAttractor;
var OnExitActive : boolean = false;
var OnExitSetAttractor : FauxGravityAttractor;

function OnCollisionEnter( c : Collision ) {
	if( OnEnterActive ){
		var fg = c.gameObject.GetComponent(FauxGravityBody);
		if( fg ){
			fg.attractor = OnEnterSetAttractor;
		}
	}
}

function OnCollisionExit( c : Collision ) {
	if( OnExitActive ){
		var fg = c.gameObject.GetComponent(FauxGravityBody);
		if( fg ){
			fg.attractor = OnExitSetAttractor;
		}
	}
}

Thanks!

Obviously for a more realistic simulation gravity would decrease with distance via the inverse square law, and for even more realism, everything would be attracted to everything else … but this works very nicely for game play (and it’s not like the built-in gravity is realistic in this way)

Is this close?
AC

66432–2457–$faux_faux_gravity_149.unitypackage (8.62 KB)

I just saw this article on Gamasutra and I thought that anyone checking this thread out would also be interested in it. It’s called " Games Demystified: Super Mario Galaxy" and it is about the physics in that game.

Also, even cooler, it includes the code they used for the prototype of the game!

I developed a game in Shockwave3D that does this after noodling with it for a couple of years. I used more or less the same approach, buttressed with some raycasting trickery.

You can see that game right now at http://gigaplay.com/microbop

In fact, I’m working on a Unity game right now that uses the same approach, only to much better effect, thanks to Unity’s being about a gazillion times better than Director Shockwave. I should have some demos ready to post soon.

Marty, that’s really cool. And definitely impressive given the limitations of Shockwave. Looking forward to your Unity implementation.