EDIT: Problem in this post has changed. Please read the comments below.
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);
}
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()
{
var controller : CharacterController = GetComponent(CharacterController);
// You don't need to transform Vector3.up here; you can just use
// -transform.up.
var targetDir = transform.TransformDirection (-Vector3.up);
if (!Physics.Raycast (transform.position, targetDir, 1.2))
{
print ("No Collision.");
faux +=
(transform.position - Vector3.zero).normalized * -2 *
Time.deltaTime; //apply gravity
controller.Move(faux);
}
else
{
faux = Vector3.zero; // reset gravity
}
// 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):
Quaternion rotation = Quaternion.FromToRotation (
transform.up, transform.position.normalized);
transform.rotation = rotation * transform.rotation;
/*
transform.rotation = Quaternion.FromToRotation (
Vector3.up,
(transform.position - Vector3.zero).normalized
);
*/
// These lines can be combined into
// 'moveDirection =
// transform.forward * Input.GetAxis("Vertical") * speed'.
moveDirection = Vector3(0 ,0 , Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= speed;
// Now that you're not overwriting the orientation every update,
// this should work.
transform.Rotate(0, Input.GetAxis ("Horizontal") * rotateSpeed, 0);
controller.Move(moveDirection * Time.deltaTime);
}
I will note that I kept the vector3.zero in so that I could replace it with a target transform later. You’ve cleaned up my code perfectly. Looks like I have a lot to learn.
I’ve only got a small problem now, which is related to the smoothness of the movement. At the bottom of the planetiods… It appears that the player doesn’t like being upside down…
Yeah, it occurred to me after posting that that might be the case. I retract that comment
I tried the demo. There shouldn’t be any discontinuities or inconsistencies in movement of the type you’re seeing here (when the player is on the bottom of the sphere). Can you post your current code? I’m guessing there’s still something slightly off somewhere.
Thank you for replying again! Don’t worry. I figured it out. It’s a bit of a pain though. It appears that Unity doesn’t calculate CharacterController bounding boxes very well. Their top side interacts differently than their bottom. And as they don’t rotate this means that as the player reaches the bottom of the sphere he collides with it. Due to my odd gravity this causes problems.
I fixed it just by reducing the size of the Controller.
It’s not great but it will do…
My problem now is my Camera code. I have a camera that works, however I am unable to get the camera setup I want. I am trying to get a good third person camera working.
My code is:
var target : Transform;
var offset : Vector3;
function LateUpdate ()
{
if (!target)
return;
offset = -target.transform.forward * 8;
offset = offset + target.transform.up * 1;
transform.position = target.transform.position + offset;
transform.rotation = target.transform.rotation;
}
Basically. Right now the camera locks to the player (and slightly above) and looks in the same direction as the player. I want the camera to be a bit above. But looking downward so that you affectively see over the players shoulders (rather than look at him). I can’t get this to work with weird rotation code.
One option would be to position the camera as you’re doing currently, but orient it using Transform.LookAt(), which would allow you to specify the exact point you want the camera to look at.
I tried this… but unfortunatly due to the strange nature of quaternions and this type of all around upside down world it causes problems. Mainly to with the camera wanting to be the right way up.
The LookAt() function has a second, optional ‘worldUp’ argument. Try it again, but this time submit your object’s local up vector for that argument, i.e. (in your camera script):