Altering Gravity

Hi all,

Some of you may remember the loop-de-loop I want to get working in my game. I want to try and crack that next time I can work on a mac. I’m probably going to alter the character to be rigid body rather than character controller for now (I believe that will be better with moving platforms, right?).

Now, I figured I need to alter the way gravity works on the inside of the loop in three parts, like so:


So, the question is, how do I do that? I’d guess that I’d be best to cut those three pieces out in Maya and have them as seperate objects to the rest of the loop to make adding the attributes easier?

I was thinking of adding a gravity script:

Physics.gravity = Vector3(0, -1.0, 0);

and altering the direction to be 0,0,-1.0 or something. But then I realised I don’t want to add gravity to the geometry itself, just the character.

Ooh! Wait! Brainstorm! I don’t need to cut the loop into three bits, do I? If I add in three colliders to the loop where I want them, I could do a:

function OnCollisionEnter() {
// alter gravity 
Physics.gravity = Vector3(0, 0, -0.1);
}

And then create a fourth collider that will bring the gravity back to normal???

Am I getting close, or totally off the ball?

Mike

Why don’t you just apply forces to the object? Gravity is basically just a force applied to all objects, so you should be able to just apply a force that’s the inverse of the gravity vector and then add a force that pulls outwards in the loop-de-loop.

I attached a rigidbody based character controller to the post, you can start modifying that.

I think keli’s suggestion of applying gravity yourself is very good.

In OnCollisionStay you want to figure out what the current normal of the ground below you is and remember it in a variable.

You probably need to go through all contacts. check if they are at the lower part of the capsule, then they should modify a current ground normal. Then you apply gravity along the ground normal. Or you could make it simpler by having a trigger area only around the loop, and when inside the trigger area, the first contact normal given in OnCollisionStay will be your new ground normal, along which you apply gravity.

But do you really want to support loops? You know, it’s a lot harder than in 2D. Eg. Where do you place the camera so it won’t feel totally weird? If it is behind, you need some kind of special rotation that makes sure it won’t just flip around when looking upside down. Could also just add all kinds of jump pads, power ups, and tune the controls of the character instead.

18362–602–$rigidbodyfirstpersoncontroller_353.js (1.48 KB)

Thanks! :slight_smile:

Right, so I select the inside of the loop and:

// Null Gravity inside the loop. 
function FixedUpdate () {
rigidbody.AddForce (0, 0, 0);
}

And then, I add a force that will pull outwards from the center of the loop? Which I do by, uh…

Sorry I’m lost! :frowning:

This would probably make more sense to me if I had a mac in front of me but all this is just hypothesis on my part with no way to test it till next week.

Can you elaborate a little more? Sorry! My knowledge is still far too vague on stuff like this!

Mike

Oh wow, thanks! :smile:
Can’t wait to have a play with that controller!
I think I understand what you mean, I’ll keep reasearching through the script reference and manual until I get on a mac!

I probably wouldn’t have chosen to include loops if it was a game of my own making, but you can’t have Sonic without loops so I’ve got to! It’ll be a challenge, but it’ll be great once it’s figured out!

As for the camera, good point! My initial guess would be to have a collision object around the loop so when the character enters it, either the camera moves to a point ouside the loop so you can see the whole thing or the camera moves in closer and lower to the character to avoid the control vectors changing? Then once the character leaves the collision object the camera returns to normal?

Mike

Er… no that adds no force. You will have to cancel out the gravity

   rigidbody.AddForce ( - Physics.gravity);

But ignore that, because I just discovered that is even easier. Every rigidbody has a useGravity flag.
You should just be able to set it to false:

// call when you enable the loop-de-loop code:
rigidbody.useGravity=false;

// and when done:
rigidbody.useGravity=true;

You could use the surface normal as suggested by Joe.
Or even just fixed directions for each segment of the loop as in your original suggestion. Juse don’t assign them to Physics.gravity, bu apply them using AddForce:

var artificialGravity = Vector3(0,0,0); // Set this vector when entering the loop sections.

function FixedUpdate () {

   // only apply artifivial gravity if we are not using the "real" one
   if( ! rigidbody.useGravity) {
     rigidbody.AddForce (artificialGravity); 
   }
}

rigidbodies have a checkbox called useGravity which you want to use for this.

Ah just away from the center. That might even be better.
So you have a trigger zone, when you enter it you need to do 3 things:

  • Calculate direction from capsule to loop center
var offset = transform.position - loopCenter;
  • Align capsule with loop:

theLoopAxis = theLooping.TransformDirection(Vector.right);
This is the axis around which the loop goes.

Most likely just
var forward = Vector3.Cross(theLoopAxis, offset);
transform.rotation = Quaternion.LookRotation (, offset);

  • apply gravity along offset:
    rigidbody.AddForce(-offset.normalized * 9 * rigidbody.mass);

I tested none of this, and i am sure it will not feel good or might not work at all without some more tweaking. One thing i learned from gooball was that allowing players to crawl on arbitrary surface, sticking to it, getting the camera right and so on is really hard. So if it’s not really critical to you, leave loops out.

IMO i would definitly go closer lower - possibly to the point where he almost fills the screen. one of the things that made sonic cool was the sense of crazy speed - pulling the camera away i think you’d have the reverse effect.

great work ; )

The problem with changing the camera position is of course that the user gets confused by the change of the camera, so you also need to adjust the controls.

Eg. While it feels a bit weird when coding it, if the user doesn’t let go of the forward button while he is in the loop, the player should continue running forward through the loop although the new camera direction would usually make him run in another direction.

What happens if the player lets go of all controls in the middle of the loop?
I guess jumping in the loop is disabled.

Yeah, that’s how it works in the official 3D Sonic games I think. Though sometimes it feels like there’s some kind of preset path the character sticks to as you always seem to stick to the center…

So, I’d be altering this bit:

// Forward vector relative to the camera along the x-z plane	
	var forward = cameraTransform.TransformDirection(Vector3.forward);
	forward.y = 0;
	forward = forward.normalized;
	// Right vector relative to the camera
	// Always orthogonal to the forward vector
	var right = Vector3(forward.z, 0, -forward.x);

	// Target direction relative to the camera
	var targetDirection = Input.GetAxis("Horizontal") * right + Input.GetAxis("Vertical") * forward;

Or would it be a case of breaking the link to the camera for the duration of the loop?

Or possibly creating a second camera with the same settings as the main camera, and having that set to move to the new position outside of the loop and render that camera for the duration, yet keeping the controls tied to the main camera so the player doesn’t need to alter the direction they’re pressing on the joystick?

In the official games you just drop, lol! Maybe there could be a variable in the script that says something along the lines of

function OnCollisionEnter() {
if (!animation.IsPlaying("jump"))
rigidbody.useGravity=true;
}

Which would make the character drop back to the ground?

Anyway, I’ve just called work to see if I can borrow a mac for the week while I’m off so from tomorrow I should actually be able to try and implement all this stuff!

Thanks again!
Mike :slight_smile:

So whats gonna happen, when he is jumping while inside the loop. He falls down on his head? Just disable jumping.

Ah, I see what you mean. I was guessing/hoping he’s just flip back to the normal upright position! :sweat_smile:

Mike

If I were you, I would just zoom out a little bit from the character (like you said), and change the cameras follow/look target to the loop instead of sonic during the loop. Then of course change it back to normal after sonic has completed the loop. That wouldn’t be too disorienting.

You could also take a look at Sega’s 3D Sonic games: Sonic Adventure 12, Sonic Heroes. They’re available on the current-gen systems, so it could at least give you some ideas!

Sorry for the thread bump, has anyone worked out a solution for this?