- Home /
The question is answered, right answer was accepted
Topdown Zelda-esque character controller help c#
I'm trying to have a fixed topdown camera that does not rotate with the character, which is what I want, but I can't get the character to rotate without rotating the character controller too. That would be bad, as then the character wouldn't move relative to the camera, which is what I'm trying to accomplish. Transform.Rotate doesn't do anything, and trying to modify the value of transform.rotation returns one of several errors. I'm at my wits end; how do I get the character to face the direction they're moving relative to the camera?
Answer by Darmouth · Oct 23, 2013 at 07:17 AM
Thanks for your help. I got something working pretty well. Here's the code for anyone interested:
using UnityEngine; using System.Collections;
public class CharacterMovement : MonoBehaviour {
//Variables
public GameObject player;
public float turnspeed=180f;
public float speed = 6.0F;
public float jumpSpeed = 8.0F;
public float gravity = 20.0F;
private Vector3 moveDirection = Vector3.zero;
void Update() {
CharacterController controller = GetComponent<CharacterController>();
// is the controller on the ground?
if (controller.isGrounded) {
//Feed moveDirection with input.
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
//Multiply it by speed.
moveDirection *= speed;
//Jumping
if (moveDirection != Vector3.zero){
if(Vector3.Angle (transform.forward, moveDirection) > 179){
moveDirection = transform.TransformDirection (new Vector3(.01f, 0, -1));
}
player.transform.rotation = Quaternion.RotateTowards(player.transform.rotation, Quaternion.LookRotation (moveDirection), turnspeed * Time.deltaTime);
}
if (Input.GetButton("Jump"))
moveDirection.y = jumpSpeed;
}
//Applying gravity to the controller
moveDirection.y -= gravity * Time.deltaTime;
//Making the character move
controller.Move(moveDirection * speed * Time.deltaTime);
}
}
Answer by gooongalooo · Nov 22, 2013 at 01:17 AM
The Legend of Zelda: A Link Between Worlds-style Controller Unity C# works really cool with a xbox controller thumbstick. didn´t test it with playstation controller...
using UnityEngine;
[RequireComponent(typeof(CharacterController))]
public class LinkController : MonoBehaviour
{
public float RunSpeed = 9;
// public float JumpSpeed = 9;
public float TurnSpeed = 25f;
public float Gravity = 20;
public float ThumbStickDeadZone = 0.1f;
// [HideInInspector]
public float Speed = 0;
[HideInInspector]
public Vector3 MoveDirection = Vector3.zero;
[HideInInspector]
public Transform Transform;
[HideInInspector]
public CharacterController Controller;
public float X = 0f;
public float Y = 0f;
public virtual void Awake()
{
Controller = GetComponent<CharacterController>();
Transform = transform;
}
public virtual void Update()
{
X = Input.GetAxis("Horizontal");
Y = Input.GetAxis("Vertical");
}
public virtual void FixedUpdate()
{
Move(X, Y);
}
public void SetSpeed(float rs, float ts)
{
RunSpeed = rs;
TurnSpeed = ts;
}
public void Move(float h, float v)
{
Speed = 0;
MoveDirection.y -= Gravity * Time.deltaTime;
if (Mathf.Abs(v) > ThumbStickDeadZone || (Mathf.Abs(h) > ThumbStickDeadZone))
{
var lookRotation = new Vector3();
lookRotation.Set(h, 0, v);
lookRotation = lookRotation.normalized;
var rotation = Quaternion.LookRotation(lookRotation, Vector3.up);
if (lookRotation.magnitude > ThumbStickDeadZone)
{
Speed = RunSpeed;
transform.rotation = Quaternion.Slerp(Transform.rotation, rotation, Time.deltaTime * TurnSpeed);
}
}
if (Controller.isGrounded)
{
MoveDirection = Transform.TransformDirection(Vector3.forward).normalized;
MoveDirection *= Speed * Time.deltaTime;
//if (Input.GetButton("Fire1"))
// MovementProperties.MoveDirection.y = JumpSpeed;
}
Controller.Move(MoveDirection);
}
}
Good sir, you are missing the script GameSettings. If you can upload it here, that would do us all a great deal; though the script seems okay. I upvoted you :D
Thanks, I was having a hard time trying to make the Char rotate and look to the way he was going to, I spent some time to understand how you did id, but i Think I got it. In my other code I was using Rigidbody ins$$anonymous$$d of CharacterController, now I'm thinking if I stay with a Ridigbody or switch with a CharacterController, for a Zelda type of game, is there much difference between those two?
Answer by Azrapse · Oct 20, 2013 at 11:12 AM
Maybe you are attempting something similar to what I'm doing in this little project:
http://azrapse.es/windofthewest/
Move the character with WASD and rotate the camera with Q and E. The character movement depends of the direction the camera is looking at. So for example, D always moves character to the right in the screen.
For doing that, I have the character being followed by the camera with a script that updates the camera position every frame. The input is controlled in this way: - Get the front direction and right direction of the camera, projected over the flat 2D floor. This sounds harder that it is. Just make a
Vector2 cameraForward = new Vector2(camera.forward.x, camera.forward.z);
Vector2 cameraRight = new Vector2(camera.right.x, camera.right.z);
With those two, you have the 2D direction 'Up' and 'Right' should move the character object. The directions for 'Down' and 'Left' are just the negative of those vectors.
To make the character move, I do something like this:
var movement = new Vector3(Input.GetAxis(horizontalAxisName)*cameraRight, 0, Input.GetAxis(verticalAxisName)*cameraForward);
And then I move the character by that amount. For the character model to face the direction of the movement, you can do it manually by rotating the character model depending on the movement.
That's a lot of good information, but the main issue I'm having is that I'm unable to rotate the character model. Does it have a vector variable for its movement direction that I could use to rotate it? or how would I do it?
What if your character model is a child of the gameobject that has the controller component? You could move the parent with up, down, left, right, and you could rotate the child model's transform locally as you wished depending on the overall movement, the last key pressed, or any other criteria.
That's the way I have it set up already, I guess I'm just having some problems with my arguments. I don't know how to use input.getaxis or input.getbuttondown or when to use either.
You use them in an Update or FixedUdate event handler. Input.GetAxis("Vertical") returns a float value between -1 and 1 representing a virtual joystick that can be in a totally "down" position (-1) all the way to a totally "up" position (1). The same for Input.GetAxis("Horizontal") for left and right.
If you aren't interested on such an analog input, but prefer normal keys, just try with Input.Get$$anonymous$$ey() or a combination of Get$$anonymous$$eyDown and Get$$anonymous$$eyUp.
In any case, when you detect that the player wants to go "up", for example, what you need to do is:
Calculate what direction the camera is looking at. Of course the camera is looking at the character, but we are interested only on the 2D components of that direction that are parallel to the ground. That is, the X and Z components (as Y is towards the sky and towards the ground and we don't want that).
Calculate how much the character should move in that direction. For that, I am multiplying the Input axis times the camera pointing direction, because I want the character to go faster or slower depending on how much the joystick is tilted. But if you aren't interested on that, just multiply the 2D forward vector times 1 or -1 for up and down, and the right vector times 1 or -1 for right or left, depending on the keypress.
$$anonymous$$ove the character's position by adding the calculated movement vector times some speed in m/s times Time.deltaTime.
Update the rotation of the character model depending on the direction of the movement, for example, or the last key press. $$anonymous$$aking it "look at" the direction of the movement is simple with the available Transform methods.
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Change rotation way of instantiated object 1 Answer
Lookat player 2 Answers