- Home /
Changing the axes of a joystick based on the position of the camera?
Hey guys, just want to get a sense if this is possible and if so how to accomplish it. I have an augmented reality application which uses a mobile device's camera and a target to make a character appear on the floor. I have a joystick that controls that character. At the moment "up" on the joystick means "forward" to the character, no matter where the user is holding his camera. This feels natural when the character is facing directly away from the user's camera. However it gets very counter intuitive when the character faces to the left, right, or directly at the camera himself. Is there a way to have the joystick change axes so that when say, the character is facing "right" that "right" on the joystick will cause the character to go "forward." And then change dynamically should the user move his camera or the character faces another direction.
I hope that's made sense. In short I'm hoping to base the movement of a character using a joystick based on the relative position of the camera to the character. If I've made a mess of this I'm happy to clarify.
Thanks for any assistance!
Answer by robertbu · Oct 07, 2014 at 04:24 PM
I assume you are using Vuforia. I've not spent much time with Vuforia, but apparently the is an option to rotate the object rather than rotating the camera (found this out from a UA answer, not personal experience). If you want your approach with the current setup, then this may work.
dir = camera.transform.TransformDirection(dir);
dir.y = 0.0;
dir.Normalize;
'camera' is a reference to the Vuforia camera. 'dir' will be the movement vector as calculated from your joystick. I'm assuming you want to take the 'y' out of the movement, but maybe not.
Hey thanks, I really appreciate the help. I'm getting a vague sense of how this might work, but if I could trouble you for a slightly deeper explanation of what these three lines are accomplishing, I think it would be a great help.
Specifically transform.TransformDirection. It's taking in my Joystick's input, (say Vector3(1.0f, -1.0f, 0)) and doing what to it exactly? From the documentation I see it's converting from local space to world space. Does that mean it's converting the camera's local rotation into world space? If so, what is the "dir" parameter accomplishing? Is it making that conversion using "dir" as some sort of reference? If so , why not use the position of my object?
Thanks for your assistance.
EDIT: Removed a statement about me needing the 'y,' got confused for a second. Still getting used to Unity's coordinate orientation.
EDIT2: Oh, actually I think it's dawning on me now. The joystick direction is the "direction" in world space that the function is calculating for the camera. That must be it. Obviously that's what you've said, it's just taken a little bit to sink through my thick skull. Thanks!
Normalize doesn't seem to be working the way I'd expect it to. The values don't seem to adding up to 1.0. Did I do something wrong?
for example:
dir: (0.1, 0.2, 0.2) dirNormalized: (0.2, 0.7, 0.7)
Vector3.Normalize works that way. It's not the sum of the values that count, it's the length of the vector (Vector3.magnitude) that becomes 1.
The direction you pass to the TransformDirection() will be relative to the world axes if used without conversion. TransformDirection() takes the passed direction and treats it as a direction in the local space of the object. The resulting calculation transforms that direction from local space to world space. For example, say you have a Vector3 that is directly forward in world space (0,0,1 for example). After using TransformDirection() it would equal the camera's forward no matter which way the camera is facing.
The 'dir.y = 0.0' is only necessary if the camera is at an angle. For example, say in your app you are looking at a downward or upward angle (as happens with Vuforia) and you use TransformDirection(). The resulting vector will have a positive or negative 'y' component. If you use it for a move without setting the 'y' to 0, the move will try and drive your character into the ground or try and pop him up in the air.
The Normalize() is necessary to compensate for setting the 'y' to 0. Imagine you are looking almost straight down, and your world space vector is (0,0,1). The resulting vector after the Transform.Direction() will be something like (-0.9,0.1,0.1). After removing the 'y' we get a vector of (0.0, 0.1, 0.1). This is a very short vector. If you are using it for movement, then the steeper the angle, the slower your object will go. If you normalize it, then it will always move at a constant speed. If your joystick has values between 0.0 and 1.0, then you need to take an extra step:
var mag = dir.magnitude;
dir = camera.transform.TransformDirection(dir);
dir.y = 0.0;
dir = dir.nornalized * mag;
This will assure that the resulting vector after the TransformDirection() call will have the same length as the one before the call...even with the 'y' removed.
Note this code will 'fail' if the user manages to look absolutely straight down. They would have to produce a perfect Vector3.down to make it happen, but you might want to check dir against Vector3.down before doing the outlined calculations.