- Home /
Face to direction, in a Mario Galaxy style game?
Hello guys, I'm developing a game that uses the mechanics of planets similar to Mario Galaxy.
But I'm having trouble to set a character's face in his direction. I'm trying hundreds of ways, but they all reset values of the X and Z axes, leaving the character in a plan, when in reality it is over a sphere (planet) and its Y axis is always recalculated.
Follow what I'm trying right now, for example, direct face-to-left:
private void MovementUpdate () {
var _hor = Input.GetAxis("Horizontal");
var _ver = Input.GetAxis("Vertical");
var _localUp = transform.worldToLocalMatrix.MultiplyVector(transform.up);
var _localRight = transform.worldToLocalMatrix.MultiplyVector(transform.right);
var _localForward = transform.worldToLocalMatrix.MultiplyVector(transform.forward);
//Face to left
if (_hor < 0) {
var _rotation = Quaternion.LookRotation(-_localRight, _localUp).eulerAngles;
transform.rotation.SetLookRotation(_rotation);
transform.Translate(_localForward * Speed * Time.deltaTime, Space.Self);
}
}
Any help is very welcome, and sorry for my english...
Answer by robertbu · Jul 03, 2013 at 02:50 PM
A number of issues here. In order to move forward on a sphere, you want to rotate around an axis through the sphere, not Translate(). Also Local coordinates for Up, Right, and Forward will always be (0,1,0), (1,0,0), and (0,0,1) respectively. So you don't have to do the calculation to bring world to local coordinates using the world up/right/forward. Here is a simple script that walks an object along the surface of a sphere:
#pragma strict
var planet : Transform;
var speed = 25.0;
var rotateSpeed = 45.0;
function Update() {
var horz = Input.GetAxis("Horizontal");
var vert = -Input.GetAxis("Vertical");
Debug.Log(horz+","+vert);
transform.RotateAround(planet.position, transform.right,speed * Time.deltaTime * vert);
transform.Rotate(0.0, rotateSpeed * Time.deltaTime * horz, 0.0);
}
The character this script is attached to should be setup so that it is standing on the sphere with it's forward facing along the surface of the sphere.
The correct position on the surface of the sphere is already calculated in another script which works very well, not only for spherical planets, but for any type of surface, and with this script, i can take a translate forward without any problem, the character circumvents the planet. The problem is precisely direct the character's face to the direction:
public class Gravity : $$anonymous$$onoBehaviour {
public bool Enable = true;
void FixedUpdate () {
if (Enable)
Attract();
}
public void Attract() {
Ray _ray = new Ray(transform.position, -transform.up);
RaycastHit hit;
if (Physics.Raycast(_ray, out hit, 50f)) {
if (hit.transform != null && hit.transform.gameObject.layer == 8) {
transform.position = new Vector3(transform.position.x, hit.point.y, transform.position.z);
Quaternion quatern = Quaternion.FromToRotation(transform.up, hit.normal);
quatern = quatern * transform.rotation;
transform.rotation = quatern;
}
}
}
}
Just do as I've done in the updated example above:
transform.Rotate(0.0, rotateSpeed * Time.deltaTime * _horz, 0.0);
Saying "Dont work" does not help me understand the problem. So I took your Gravity code and added some movement into it. This script works for me:
using UnityEngine;
using System.Collections;
public class Gravity : $$anonymous$$onoBehaviour {
public float forwardSpeed = 1.0f;
public float rotateSpeed = 55.0f;
void Update() {
$$anonymous$$ovement();
}
void $$anonymous$$ovement() {
float horz = Input.GetAxis("Horizontal");
float vert = Input.GetAxis("Vertical");
transform.Translate(Vector3.forward * forwardSpeed * Time.deltaTime * -vert);
Attract();
transform.Rotate(0.0f, rotateSpeed * Time.deltaTime * horz, 0.0f);
}
public void Attract() {
Ray _ray = new Ray(transform.position, -transform.up);
RaycastHit hit;
if (Physics.Raycast(_ray, out hit, 50.0f)) {
transform.position = hit.point;
transform.Translate (Vector3.up * 0.5f); // Bring character up off surface
//transform.position = new Vector3(transform.position.x, hit.point.y, transform.position.z);
Quaternion quatern = Quaternion.FromToRotation(transform.up, hit.normal);
quatern = quatern * transform.rotation;
transform.rotation = quatern;
}
}
}
Note I had to change your Gravity code to make it work for a spherical surface. There was an issue if you get beyond the top of the sphere's surface.
Okay, your code handles the movement. I was doing the movement in another script, but okay, this was not the problem. The question is: in this scenario, with this kind of "physics" being applied, how the character turn with his face to the direction it is moving. This is my doubt! For example, pressing "left", the character turns round to the "left" and moves. With your code, it does not happen...