- Home /
How do I make an object in game face the direction it's traveling while viewing from above?
I am using the below code to move my ship along the X and Y axis in my environment but I cannot get the ship to face the direction in which the ship is moving.
Every resource I have searched for suggests 'rotating' the ship to match the transform's rotation, but the transform does not rotate - everything simply moves along the X and Y axis (there is no rotation).
I think what I need to do is somehow extract the 'travel direction' from the below script and use that to rotate my ship in a way that makes the ship face the direction of travel - but I am at a loss as to how to accomplish this.
Any advice would be appreciated.
(possibly extraneous information) I could fix this by allowing the game object that has the ship attached to it to rotate, but then when i push 'left' on the joystick the ship will not move 'left' according to the user's point of view, it will move to the ship's left - but this is not the behavior I desire.
static var blackhole : Vector3 = Vector3.one;
@script RequireComponent( CharacterController )
var moveJoystick : Joystick;
var rotateJoystick : Joystick;
var forwardSpeed : float = 4;
var backwardSpeed : float = 4;
var sidestepSpeed : float = 4;
private var thisTransform : Transform;
private var character : CharacterController;
private var velocity : Vector3;
function Start()
{
// Cache component lookup at startup instead of doing this every frame
thisTransform = GetComponent( Transform );
character = GetComponent( CharacterController );
// Move the character to the correct start position in the level, if one exists
var spawn = GameObject.Find( "PlayerSpawn" );
if ( spawn )
thisTransform.position = spawn.transform.position;
}
function OnEndGame()
{
// Disable joystick when the game ends
moveJoystick.Disable();
rotateJoystick.Disable();
// Don't allow any more control changes when the game ends
this.enabled = false;
}
function Update()
{
//transform.LookAt(PlayerRelativeControl.blackhole, Vector3.forward);
var movement = thisTransform.TransformDirection( Vector3( 0, moveJoystick.position.y, moveJoystick.position.x ) );
//Only x and y movement
movement.z = 0;
movement.Normalize();
// Apply movement from move joystick
var absJoyPos = Vector2( Mathf.Abs( moveJoystick.position.x ), Mathf.Abs( moveJoystick.position.y ) );
if ( absJoyPos.y > absJoyPos.x )
{
if ( moveJoystick.position.y > 0 )
movement *= forwardSpeed * absJoyPos.y;
else
{
movement *= backwardSpeed * absJoyPos.y;
}
}
else
{
movement *= sidestepSpeed * absJoyPos.x;
}
//velocity = character.velocity;
movement += velocity;
movement *= Time.deltaTime;
// Actually move the character
character.Move( movement );
}
To recap, my ship is moving along the X and Y axis in my environment, I am viewing the ship from 'above' (from the Z axis), and the ship is currently always facing one direction while moving (literally the top of the screen) which is useless because it needs to look like it is traveling in the direction of movement.
How do I get the ship to look like it is traveling in the direction of its movement?
Update after some tweaking based on suggestions from Unity Forums, still not resolved
I believe I seem to be going in the right direction but I must have something messed up with my object that is causing it to behave incorrectly - I will post more information in an attempt to get assistance in finding the problem:
Here is the code I have added to the above script: var lookAt = movement;
lookAt.z = 0; // if z is the up direction
if(lookAt.magnitude > 0) transform.LookAt(transform.position + lookAt, transform.forward);
-The 'object' that I have the above script attached to is a character controller object with a Rotation of X:0 Y: 90 Z: 0 (If I have it 0,0,0 my ship doesn't move along the x/y window how I want it to)
-The actual 3d 'ship' model is then attached to the above object (for information's sake, this 'ship' has a Rotation of X:0 Y:0 Z:0)
When I made the most recent edit mentioned above, the behavior of the ship changed from flicking instantly to opposite facing directions to the following:
The ship appears to spin in circles most of the time (while the user is inputing a 'direction' for the ship to move).
Occasionally the ship flickers back and forth facing opposite directions (like it used to before this edit).
The ship occasionally locks in a direction (while using the joystick) and will drift in the direction indicated by the user.
I am not quite sure what is happening at this point.
Thank you for any assistance.
Edit:
Here are some things I've noticed in Unity itself while I'm running the game:
-The Y rotation of the game object appears to only change in increments of 90 when the user attempts to move the ship (actually, pretty much only 90 and 270 (or 89.99999 and 269.999)).
-The Z rotation of the game objects starts at 0 every time the game is 'played.' While issuing a command, with the joystick, the Z rotation switches to many different numbers, but always locks on "180" after the user ends the joystick command.
edit: http://www.youtube.com/watch?v=W2AnJNHpz8g
Here is a link to a video that shows how I want my ship to be moving around. It is a clip from Mass Effect, the biggest difference between this gameplay and mine is that mine is a view from straight above, while this is a view from an angle (keep in mind my movement is controlled by an on-screen touch-sensitive joystick.
General simple suggestion: look at the various CA$$anonymous$$ERA SCRIPTS which are freely included with Unity. You'll see just how to do that type of thing quite easily. Hope it helps!
Answer by simonmc · Oct 11, 2011 at 10:08 PM
Firstly, in Unity the Y axis is the vertical axis. I suspect you would save yourself a few headaches if you did things this way instead.
If you don't want to change things though, then I suspect a simple
transform.LookAt(transform.position + movement, Vector3(0,0,1));
inserted just before the call to Move() would do the trick. The second vector parameter is since you are using a non-standard vertical axis. If you change your system to use Y as up then just remove that parameter.
I can't tell exactly from your code whether this will work, since you are doing things in a fairly odd manner. You may need to remove the call to
thisTransform.TransformDirection(....)
transform.TransformDirection() transforms a vector from local space to world space, so when you rotate your object to face the way it's travelling, the movement directions might get bunged up.
I didn't realize I was doing things in such an odd manner. I should probably repair things to make things easier. Thank you for the insight, I will attempt your fix shortly.
edit: Does not work initially. The problem likely lies in the this.Transform.TransformDirection(. . .) section - however I am not quite sure how to address that situation exactly. If i just comment out the Transform.TransformDirection(. . .) section - my ship doesn't move.
-How does it not work? The ship still behaves very similarly as it did before, but ins$$anonymous$$d of occasionally swopping in motions that look like the ship is turning, it is only flickering back and forth and occasionally locking on a direct path of motion in one direction (although issuing a command to turn in another direction).
Your ship wont move after removing that because the movement var is zero, and you multiply this ins$$anonymous$$d of add, or set to.
Here is a basic outline of how I would go about doing what you are doing.
var speed = 4.0;
function Update() {
var direction;
if(moveJoystick.position.magnitude > 0.1) { //remove the jitter
if($$anonymous$$athf.Abs(moveJoystick.position.y) > $$anonymous$$athf.Abs(moveJoystick.position.x)){
direction = Vector3.forward * moveJoystick.position.y;
} else {
direction = Vector3.right * moveJoystick,position.x;
}
transform.LookAt(transform.position + 10*direction); //look the right way
character.$$anonymous$$ove(direction * speed * Time.deltaTime);
}
}
This is treating the Y-axis as up, so you will need to set the initial rotation, camera etc accordingly.
EDIT: changed moveJoystick.magnitude to moveJoystick.position.magnitude
Looks good, I will try it when I leave work (unable to test movement while at work). Thank you.
Finally able to test, here is the result. . .
Had to change the line: var direction; to var direction : Vector3;
and direction - Vector3.forward moveJoystick.position.y; to direction - Vector3.up moveJoystick.position.y;
The ship now appears to face semi-appropriate directions when moving - it clicks only at 90 degree increments, so the ship only ever faces directly up, down, left, and right.
Thank you sincerely for getting me this far!
Also, when facing up and down the ship is actually pointing up and down like I want it to (you can see the full shape, the ship is a triangle that is pointing up when going up, and down when going down)
But
When the ship faces left and right, the triangle flattens out into a plane, it is pointing left and right - but I need to rotate it along the Z. This is simply some logic I must fix, seems troubling - but not something I couldn't figure out.
The most pressing issue is the 90 degree increments the ship seems to want to face in. Any advice on how to approach that issue?
edit: http://www.youtube.com/watch?v=W2AnJNHpz8g Here is a link to a video that shows how I want my ship to be moving around. It is a clip from $$anonymous$$ass Effect, the biggest difference between this gameplay and $$anonymous$$e is that $$anonymous$$e is a view from straight above, while this is a view from an angle (keep in $$anonymous$$d my movement is controlled by an on-screen touch-sensitive joystick.
I assumed that you wanted movement constrained to 90 degree increments, sorry. The case where angled directions are possible too is even simpler:
var speed = 4.0;
function Update() {
var direction : Vector3;
if(moveJoystick.position.magnitude > 0.1) { //remove the jitter
direction = Vector3(moveJoystick.position.x, moveJoystick.position.y, 0);
transform.LookAt(transform.position + 10*direction); //look the right way
character.$$anonymous$$ove(direction * speed * Time.deltaTime);
}
}
This has taken into account the changes you made in your last comment
Your answer
Follow this Question
Related Questions
Moving while facing the camera 0 Answers
Transform.LookAt 2 Answers
How do I keep my character facing the direction of travel after movement stops? 1 Answer
tranform.TransformDirection not effecting spawned object 2 Answers
'jerking' movement... 1 Answer