- Home /
How to rotate a player when using Mario Galaxy style gravity?
I'm working on Mario Galaxy style walking and physics.
This code will attract the player (capsule with controller) towards the centre of the scene (0,0,0) and also rotate them so that they orient the right way up. It also stops the player from falling when they hit the planets surface. For my game I don't need to calculate rotations based upon the normal of the ground like they do in Mario. Just rotate towards a point.
This all works. However, now I need to rotate the player with the input controls. But I can't because the planet orientation code over rides this meaning that the player will not turn around when I press the keys!! How can I solve this???
Here is all my code so far:
/// This script moves the character controller forward /// and sideways based on the arrow keys. /// It also jumps when pressing space. /// Make sure to attach a character controller to the same game object. /// It is recommended that you make only one call to Move or SimpleMove per frame. var speed = 6.0; var rotateSpeed = 3.0; var faux = Vector3.zero; //gravity value
private var moveDirection = Vector3.zero; private var targetPos = Vector3.zero;
function FixedUpdate() {
// Obtain Controller var controller : CharacterController = GetComponent(CharacterController);
// Apply Gravity and Check to see if we have landed on planet (if so stop gravity) var targetDir = transform.TransformDirection (-Vector3.up); Debug.Log (targetDir); if (!Physics.Raycast (transform.position, targetDir, 1.2)) { print ("No Collision."); //Debug.Log ("No collision found."); faux += (transform.position - Vector3.zero).normalized -2 Time.deltaTime; //apply gravity controller.Move(faux);
} else { faux = Vector3.zero; // reset gravity }
//Rotate Player towards centre of planet transform.rotation = Quaternion.FromToRotation (Vector3.up, (transform.position - Vector3.zero).normalized);
//Apply movement from keys moveDirection = Vector3(0 ,0 , Input.GetAxis("Vertical")); moveDirection = transform.TransformDirection(moveDirection); moveDirection *= speed;
// Apply rotation from keys. DOESNT WORK!! transform.Rotate(0, Input.GetAxis ("Horizontal") * rotateSpeed, 0);
// Move the controller controller.Move(moveDirection * Time.deltaTime);
}
Answer by Sydan · Sep 08, 2011 at 02:07 PM
This isn't perfect, but this is what I used in the end (or at least a simple version of the final script):
var planet : Transform; // The planet to rotate around
var speed = 8.0; // move speed
var rotateSpeed = 10.0; // rotate speed for player
private var faux = Vector3.zero; //gravity value
var ground = 0; // if on the ground
var fauxMag = 0.0;
var gravMag = 20.0; // power of gravity
var jumpMag = 10.0; // power of jump
var hit : RaycastHit;
var groundHeight = 1.25; // offset that pushes the player up above the ground slightly
private var moveDirection = Vector3.zero;
function Update()
{
if (!planet)
return;
var controller : CharacterController = GetComponent(CharacterController);
var targetDir = transform.TransformDirection (-Vector3.up);
if (!Physics.Raycast (transform.position,-transform.up, hit, groundHeight))
{
ground = 0;
faux +=(transform.position - planet.transform.position).normalized * -gravMag *Time.deltaTime; //apply gravity
}
else
{
if(hit.distance < groundHeight-0.1)
{
transform.position = hit.point + transform.up*groundHeight;
}
ground = 1;
faux = Vector3.zero; // reset gravity
}
print ("Ground = " + ground);
// Here you're overwriting the current orientation (as you noted in
// your post). Instead, you want to apply a corrective rotation,
// something like (note that subtracting Vector3.zero isn't
// needed):
QuaternionRotation = Quaternion.FromToRotation (transform.up, (transform.position - planet.transform.position).normalized);
transform.rotation = QuaternionRotation * transform.rotation;
moveDirection = transform.forward * Input.GetAxis("Vertical") * speed;
if (Input.GetButton ("Jump"))
if (ground == 1)
{
//moveDirection += transform.up * 10;
faux = transform.up * jumpMag;
ground = 0;
}
// Now that you're not overwriting the orientation every update,
// this should work.
if (!Input.GetButton ("View1"))
{
transform.Rotate(0, Input.GetAxis ("Mouse X") * rotateSpeed, 0);
}
controller.Move((moveDirection + faux) * Time.deltaTime);
fauxMag = faux.magnitude;
planetScript = planet.GetComponent(PlanetBehaviourScript);
planetRotateSpd = planetScript.rotateSpd;
planetMoveVec = planetScript.moveVec;
transform.RotateAround(planet.transform.position, Vector3.up, planetRotateSpd * Time.deltaTime);
transform.position.x += planetMoveVec.x * Time.deltaTime;
transform.position.y += planetMoveVec.y * Time.deltaTime;
transform.position.z += planetMoveVec.z * Time.deltaTime;
}
Answer by Max Kaufmann · Dec 16, 2010 at 07:35 PM
Why reinvent PhysX?
var planet : Transform;
function FixedUpdate() { // could be optimized var direction = (planet.position - transform.position).normalized; rigidbody.AddForce( Physics.gravity.magnitude * direction, // pull towards planet center transform.position - transform.up, // pull from feet to orient character ForceMode.Acceleration // gravity is pure acceleration ); }
Answer by boomcrash · Nov 28, 2010 at 07:34 PM
Did you have any luck with this? I'm trying to do the same type of movement and having issues as well.
Hey, I managed it in the end, but I didn't take the answer from here. What I plan to do is write a tutorial on my website: http://www.sydan.co.uk/tutorials.html It should be there eventually (might have to wait because I'm about to head off to uni again). If you give me an email address though I can send you some source code :)
Answer by Mark 8 · Dec 28, 2010 at 04:13 PM
@Max Kaufmann: Sorry, I'm new to unity scripting. Do you apply this script to the character object and then create a sphere named 'planet'?
Your answer
Follow this Question
Related Questions
Can anyone tell me what I'm doing wrong here? 1 Answer
draw planet orbit on solar system 0 Answers
How to predict orbit based on time? 1 Answer
Translating Speed into rotation degress\sec 1 Answer
3D Planatary Gravity 2 Answers