- Home /
How do I change character direction without messing up the controls?
So, I've got my Character Controls working, as well as the rotation. However, they don't seem to like each other, and if I go left, my Character faces left, but moves forward (like a crab, lol). If I press down, the character seems to walk backwards. This is what I have:
if (controller.isGrounded) {
moveDirection = new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= speed;
if (Winp.GetButtonDown(WiiUGamePadButton.ButtonA) || Input.GetKeyDown(KeyCode.Space)) {
moveDirection.y = jumpSpeed;
}
if (Input.GetAxis("Horizontal") < 0) {
transform.eulerAngles = new Vector3(0,-90,0);
}
if (Input.GetAxis("Horizontal") > 0) {
transform.eulerAngles = new Vector3(0,90,0);
}
if (Input.GetAxis("Vertical") < 0) {
transform.eulerAngles = new Vector3(0,180,0);
}
if (Input.GetAxis("Vertical") > 0) {
transform.eulerAngles = new Vector3(0,0,0);
}
}
So my question is, if I want to go left, the Character needs to face left, and go left. How can I accomplish this?
Update I've Updated my Code to this:
if (controller.isGrounded) {
transform.forward = Vector3.Normalize(new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical")));
moveDirection = transform.forward;
moveDirection *= speed;
if (Winp.GetButtonDown(WiiUGamePadButton.ButtonA) || Input.GetKeyDown(KeyCode.Space)) {
moveDirection.y = jumpSpeed;
}
Debug.Log(moveDirection);
}
At first, it looked like it worked, but since it's "transformer.forward", it will always go forward.
Update 2 I think I'm getting closer now, as I've managed to make Vertical Controls work perfectly.
if (controller.isGrounded) {
transform.forward = Vector3.Normalize(new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical")));
moveDirection = transform.forward;
if (Input.GetAxis("Vertical") == 0) {
moveDirection *= 0;
}
else {
moveDirection *= speed;
}
if (Winp.GetButtonDown(WiiUGamePadButton.ButtonA) || Input.GetKeyDown(KeyCode.Space)) {
moveDirection.y = jumpSpeed;
}
Debug.Log(moveDirection);
}
However, the Horizontal movement is now always 0, unless I use the Vertical Axis while using the Horizontal Axis. So, any quick solution to this one?
Answer by Yamilla · Jul 30, 2013 at 09:43 PM
Okay, it got resolved now. Here's the final Code, for other people struggling with this:
if (controller.isGrounded) {
transform.forward = Vector3.Normalize(new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical")));
moveDirection = transform.forward;
if (Input.GetAxis("Vertical") == 0 && Input.GetAxis("Horizontal") == 0) {
moveDirection *= 0;
}
else {
moveDirection *= speed;
}
if (Winp.GetButtonDown(WiiUGamePadButton.ButtonA) || Input.GetKeyDown(KeyCode.Space)) {
moveDirection.y = jumpSpeed;
}
Debug.Log(moveDirection);
}
Answer by robertbu · Jul 30, 2013 at 04:47 AM
I can see why you are having problems, but it is hard to know the best way to fix it. The way your code is written now, 'Vertical' trumps. That is, if you are using a joystick, then giving it a lot of horizontal and just a bit of vertical will still result in looking in the 'Vertical' direction (which means it should move in the 'Vertical' direction). Here is a guess at what you want. You may still need to figure out if your rotation code works like you want in all situations:
if (controller.isGrounded) {
var moveMag = new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical")).magnitude;
moveMag *= speed;
if (Input.GetAxis("Horizontal") < 0) {
transform.eulerAngles = new Vector3(0,-90,0);
}
if (Input.GetAxis("Horizontal") > 0) {
transform.eulerAngles = new Vector3(0,90,0);
}
if (Input.GetAxis("Vertical") < 0) {
transform.eulerAngles = new Vector3(0,180,0);
}
if (Input.GetAxis("Vertical") > 0) {
transform.eulerAngles = new Vector3(0,0,0);
}
moveDirection = transform.forward * moveMag;
if (Winp.GetButtonDown(WiiUGamePadButton.ButtonA) || Input.GetKeyDown(KeyCode.Space)) {
moveDirection.y = jumpSpeed;
}
}
After changing "var" into "float", it looks like it works. I currently can only go into 4 directions because of this change, but the Character is meant to be controlled by an Analog Stick, making it very unconfty. Changing "transform.forward" into "transform.TransformDirection(move$$anonymous$$ag)" gave me another error.
In order to accomplish that, I have to change "float" into "Vector3", but Unity3D gives me yet another error for that.
Sorry about the mixup in your name. I didn't know 'Yamilla' was a girls name, and I jumped to conclusion since most of the people on this list are male. As for your code, @Jamora's approach of using Atan2() will work. Here is a script based on the example script in the reference for CharacterController.$$anonymous$$ove(). It is Javascript. I now see you wrote in C#. If you needed it converted, let me know:
var speed : float = 6.0;
var jumpSpeed : float = 8.0;
var gravity : float = 20.0;
private var controller : CharacterController;
private var moveDirection : Vector3 = Vector3.zero;
function Start() {
controller = GetComponent(CharacterController);
}
function Update() {
if (controller.isGrounded) {
moveDir = Vector2(Input.GetAxis("Horizontal"),Input.GetAxis("Vertical"));
var move$$anonymous$$ag = moveDir.magnitude;
move$$anonymous$$ag *= speed;
if (Winp.GetButtonDown(WiiUGamePadButton.ButtonA) || Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.Space)) {
moveDirection.y = jumpSpeed;
}
var angle;
if (moveDir.magnitude > 0.01)
angle = $$anonymous$$athf.Atan2(moveDir.y, moveDir.x) * $$anonymous$$athf.Rad2Deg + 90;
transform.rotation = Quaternion.Euler(0.0, angle, 0.0);
moveDirection = transform.forward * move$$anonymous$$ag;
}
moveDirection.y -= gravity * Time.deltaTime;
controller.$$anonymous$$ove(moveDirection * Time.deltaTime);
}
Answer by Jamora · Jul 30, 2013 at 10:01 AM
You mentioned you don't want to do a lot of changes, so you might end up not implementing my suggestion. But the best way, in my opinion, is to divide the possible analog stick movement space into four areas, each 45 degrees wide.
Imagine a big circle, let's say it has a radius of one. Now imagine an X at the center which touches the circle at four points. Let's call the newly created uppermost sector 'up', the one on the left, 'left' etc.
What you need to do is determine which sector the analog stick is currently in. Because Unity gives the analog input between 0 and 1 in both vertical and horizontal, our analog stick input can be considered a vector within our circle. This is exactly what you're doing in line 2.
Instead of then comparing the length of the individual axes, you should be using a reference forward direction - in third person games it's usually the camera's forward - and computing the angle of the analog stick vector and our reference forward. Our reference direction is at angle 0 and pointing straight up.
If the angle is between 0 and +/- 45, look forward
if between +/- 45 and +/- 135 than look left or right, depending on sign
if between +/- 135 and +/- 180 look backwards.
Moving should of course be done in the direction and speed of the analog stick vector.
I can't remember if it's possible to get a (+/-1,+/-1) out of Unity's input system. if it is, then instead of a circle, use a box.
EDIT: for some reason I had divided everything by two in my math. Fixed now.
EDIT: I cobbled together what I meant in code:
Vector2 inputVector = new Vector3(Input.GetAxis("Horizontal"),Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(new Vector3(inputVector.x,0f,inputVector.y));
float angle = Mathf.Atan2(inputVector.x,inputVector.y)*Mathf.Rad2Deg;
if(angle>=0){//the right side
if(angle<45f){
//rotate character facing forward
}
if(angle<135f){
//rotate character facing right
}if(angle<=180f){
//rotate character facing right
}
}else{
if(angle>-45f){
//rotate character facing forward
}
if(angle>-135f){
//rotate character facing right
}if(angle>=-180f){
//rotate character facing right
}
}
@Jamora - your concept is a workable one, but you need to tweak it a bit. The angles meaning you will get back from the Atan2 will not match your comments, and your movement code will not cause the player to move in the direction he is facing. But this is a good approach for the OP to fix his axis issues. If "Horizontal" and "Vertical" are buttons or keys rather than a joystick, then her current code is probably fine.
It's mapped to Analog Sticks, as I said before (Wii U Analog Sticks, to be more specific). By the way, I don't know from which country you are, but here in the West, "Yamilla" is a girls name, and I'm a female (just in case you didn't know that).
@Jamora, your Code didn't work out for me.
Your answer
Follow this Question
Related Questions
Flip over an object (smooth transition) 3 Answers
Making a bubble level (not a game but work tool) 1 Answer
Multiple Cars not working 1 Answer
Why the player is not rotating and moving at the same time ? 0 Answers
Roll a ball camera problem? 1 Answer