I'm totally new to Unity and game development...I made a 2D object of the car that can move to 8 directions....each direction with the specific animation of the car's movement...Now, how do I make my car move in such a way that if it's moving straight LEFT it shouldn't go immediately straight to RIGHT when turning RIGHT, so I want it to make a proper round turn or a "U TURN" to move towards its opposite direction and obviously the same with UP and DOWN turns....can anyone please help me in at least one way I can fix this?
or the other way to ask this question would be if I'm moving my object to x = -1 direction then on turning to x = 1 it should first go through x = 0 and then x = 1 so that it looks like a turn.
this is the code for my CAR so far..
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CARmovement : MonoBehaviour
{
public float speed;
private Rigidbody2D myRigidbody;
private Vector3 change;
private Animator animator;
private Vector3 lastMoveDirection;
// Start is called before the first frame update
void Start()
{
animator = GetComponent<Animator>();
myRigidbody = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
change = Vector3.zero;
change.x = Input.GetAxis("Horizontal");
change.y = Input.GetAxis("Vertical");
UpdateAnimationAndMove();
}
void UpdateAnimationAndMove()
{
if (change != Vector3.zero)
{
MoveCar();
animator.SetFloat("moveX", change.x);
animator.SetFloat("moveY", change.y);
animator.SetBool("driving", true);
}
else
{
animator.SetBool("driving", false);
}
}
void MoveCar()
{
myRigidbody.MovePosition(transform.position + change * speed * Time.deltaTime);
}
}
I try an example of rotating a car. We add an object (here I add a car as an example), select the object (car) to create a C# Script script, double-click to open, we define two variables Speed_move, Speed_rot to control the movement speed and Rotation speed and assign values to them. We use Translate to control the forward and backward movement of the cube through the W and S buttons, forward with forward, and back with back; use Rotate to control the rotation of the object through the A and D buttons, up is the Y-axis rotation. The following is the code for the specific rotation.
if (Input.GetKey(KeyCode.W))
{
this.transform.Translate(Vector3.forward * Time.deltaTime * Speed_move);
}
if (Input.GetKey(KeyCode.S))
{
this.transform.Translate(Vector3.back * Time.deltaTime * Speed_move);
}
if (Input.GetKey(KeyCode.A))
{
this.transform.Rotate(Vector3.up * Time.deltaTime * -Speed_rot);
}
if (Input.GetKey(KeyCode.D))
{
this.transform.Rotate(Vector3.up * Time.deltaTime * Speed_rot);
}
Related
Yes I know this question was asked before by SuperSonyk! That post is here:
Set rigidbody.velocity to direction of mouse in Unity2d
However- the link referenced in the answer to that post is now legacy material, and I can't bring myself to understand it in Unity's current version.
My Problem: In short, I want to make my player accelerate in the direction of my cursor. My game is currently a TOP-DOWN Space Shooter in 2D. My player already looks at my mouse correctly, using cam.ScreenToWorldPoint. But relentlessly trying to add force seems futile for me, since I am fairly new to coding.
If I have any other issues in my code, It would be great if anyone could point them out!
Here's my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
//================= MOVEMENT =====================
private float thrust = 0.5f;
private float maxSpeed = 10f;
public Rigidbody2D rb;
//================= AIMING =======================
public Camera cam;
Vector2 mousePos;
// Update is called once per frame: Good for INPUTS
void Update()
{
//aiming
mousePos = cam.ScreenToWorldPoint(Input.mousePosition);
}
// Called Set amount of times. Good for PHYSICS CALCULATIONS
void FixedUpdate()
{
Move();
speedLimiter();
//aim
Vector2 lookDirection = mousePos - rb.position;
float angle = Mathf.Atan2(lookDirection.y, lookDirection.x) * Mathf.Rad2Deg - 90f;
rb.rotation = angle;
}
//======= MY MOVE FUNCTION DOES NOT WORK. HELP? ======
void Move()
{
if (Input.GetButtonDown("Accelerate"))
{
rb.velocity = new Vector3(0, thrust, 0) * Time.deltaTime;
}
}
void speedLimiter()
{
if (rb.velocity.magnitude > maxSpeed)
{
rb.velocity = Vector3.ClampMagnitude(rb.velocity, maxSpeed);
}
}
}
Please summarize the edits clearly, thank you!
In general since this is a 2D rigidbody also the velocity is a Vector2 and you should probably rather use Vector2.ClampMagnitude
and then in
rb.velocity = new Vector3(0, thrust, 0) * Time.deltaTime;
do you only want to move in global Y direction? Also a velocity is already a "per second" value -> it makes no sense to multiply by Time.deltaTime if you reassign a new velocity. Since it says thrust I guess you rather wanted to add to the existing velocity.
What you would rather do is save your mouse direction you already have and do
public class PlayerController : MonoBehaviour
{
...
void FixedUpdate()
{
// I would update the aim BEFORE moving
// Use a NORMALIZED direction! Makes things easier later
Vector2 moveDirection = (mousePos - rb.position).normalized;
float angle = Mathf.Atan2(moveDirection.y, moveDirection.x) * Mathf.Rad2Deg - 90f;
rb.rotation = angle;
// OPTIONAL: Redirect the existing velocity into the new up direction
// without this after rotating you would still continue to move into the same global direction
rb.velocity = rb.velocity.magnitude * moveDirection;
Move(moveDirection);
speedLimiter();
}
void Move(Vector2 moveDirection)
{
if (Input.GetButtonDown("Accelerate"))
{
// Instead of re-assigning you would probably add to the existing velocity
// otherwise remove the "+" again
rb.velocity += moveDirection * thrust * Time.deltaTime;
}
}
void speedLimiter()
{
if (rb.velocity.magnitude > maxSpeed)
{
// You are working with Vector2 so use the correct method right away
rb.velocity = Vector2.ClampMagnitude(rb.velocity, maxSpeed);
}
}
}
You already have half of the work by having your player looking at the mouse. We will be using the vector lookDirection as the direction of the movement for the player, normalize it so its length is 1 and multiply it by thrust. This way, we have a vector in the direction of the mouse and of length thrust as intended.
void Move()
{
if (Input.GetButtonDown("Accelerate"))
{
Vector2 lookDirection = (mousePos - rb.position);
rb.AddForce(lookDirection.normalized * thrust);
}
}
Note that we work here with Vector2 since you are using a Rigidbody2D.
Also, I don't think that using Time.DeltaTime is relevant here. When you apply force to a physic object, you don't need to use it, by definition, the function FixedUpdate() has a fixed frequency. If you look at one of Unity's tutorial, you can see that they don't multiply it by Time.DeltaTime
Last tip: you may want to be playing around with the drag property of your Rigidbody2D to have your player slow down over time when not accelerating, otherwise, it will be sliding out of control and the player won't be able to stop it.
Don't hesitate to tell me if my answer is not clear for you or does not entirely satisfy you, it's my first answer here!
EDIT: I forgot to tell you but as derHugo mentioned, since you are using Rigidbody2D, you must use Vector2.ClampMagnitude to limit your speed in your speedLimiter function. Also, I don't think that you need your if since the function Vector2.ClampMagnitude will only change the value of the velocity if it exceeds the maximum.
Thanks to everyone who responded!
With the help of Brackeys community, I managed to solve this by using this method:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
//================= MOVEMENT =====================
private float thrust = 10f;
private float maxSpeed = 100f;
public Rigidbody2D rb;
//================= AIMING =======================
public Camera cam;
Vector2 mousePos;
// Update is called once per frame: Good for INPUTS
void Update()
{
//aiming
mousePos = cam.ScreenToWorldPoint(Input.mousePosition);
}
// Called Set amount of times. Good for PHYSICS CALCULATIONS
void FixedUpdate()
{
Move();
speedLimiter();
//aim
Vector2 lookDirection = mousePos - rb.position;
float angle = Mathf.Atan2(lookDirection.y, lookDirection.x) * Mathf.Rad2Deg - 90f;
rb.rotation = angle;
}
void Move()
{
if (Input.GetKey("up"))
{
rb.AddRelativeForce(Vector2.up*thrust);
}
}
void speedLimiter()
{
if (rb.velocity.magnitude > maxSpeed)
{
rb.velocity = Vector3.ClampMagnitude(rb.velocity, maxSpeed);
}
}
//rb.AddForce(new Vector3(0, thrust, 0));
}
I'm new to Unity and rigidbodies, and I thought I'd learn by trying to make a 3D Tron Light-cycle game. I've made my player vehicle using a combination of cylinders, spheres, and rectangles, seen below:
I used a rigid body on the elongated sphere, and used the following code:
public float accel = 1.0f;
// Use this for initialization
void Start () {
cycleSphere = GetComponent<Rigidbody>();
}
void FixedUpdate () {
cycleSphere.velocity = Vector3.forward * accel;
}
That moves the vehicle forwards. I'm not sure if there's a better way to do this, but if there is, please do say so.
I've attached the Main camera to the vehicle, and disabled X rotation to prevent it and the camera from rolling.
Now I would like to get it to turn by pressing the A and D buttons. Unlike the 90 degree turning of the original Tron light-cycles, I wanted it to turn like a regular vehicle.
So I tried this:
void Update () {
if (Input.GetKey (KeyCode.A)) {
turning = true;
turnAnglePerFixedUpdate -= turnRateAngle;
} else if (Input.GetKey (KeyCode.D)) {
turning = true;
turnAnglePerFixedUpdate += turnRateAngle;
} else {
turning = false;
}
}
void FixedUpdate () {
float mag = cycleSphere.velocity.magnitude;
if (!turning) {
Quaternion quat = Quaternion.AngleAxis (turnAnglePerFixedUpdate, transform.up);// * transform.rotation;
cycleSphere.MoveRotation (quat);
}
cycleSphere.velocity = Vector3.forward * accel;
}
While the above code does rotate the vehicle, it still moves in the last direction it was in - it behaves more like a tank turret. Worse, pressing either A or D too much would cause it to rotate in the desired direction and, after a short while, go nuts, rotating this way and that, taking the camera with it.
What did I do wrong and how can I fix it?
First of all I would recommend you to change from Input.GetKey to Input.GetAxis which will gracefully increase or decrease it's value when the key is pressed. This will give you the option to normalize the force vector applied as your velocity. Then based on that vector you have to adapt your force input so that the "front wheel" will "drag" the rest of the body to some other direction ( left or right ). This is not the ideal "real world physics behavior" because the forward force is slightly bigger than the side ( left or right ) force.
code example :
// member fields
float sideForceMultiplier = 1.0f;
float frontForceMultiplier = 2.0f;
Vector3 currentVeloticy = Vector3.zero;
void Update()
{
Vector3 sideForce = (sideForceMultiplier * Input.GetAxis("horizontal")) * Vector3.right;
Vector3 frontForce = frontForceMultiplier * Vector3.forward;
currentVelocity = (sideForce + fronForce).Normalize;
}
void FxedUpdate()
{
cycleSphere.velocity = currentVelocity * accel;
}
I'm creating a maze game and curently i am having delays with my android controls. I have lade the computer controls to move front and to turn left and right and to jump using input.getaxis. Now on android i created buttons that work but not how i want. It can jump and turn how i want but it doesnt move properly. There are 2 problems one is that when i click it moves a bit and then i need to click again but i want to hold and it will move continuously and second problem is that when i turn the character doesnt move the corect way it goes always on x axis with input.getaxis everything works perfectly but i need something that will work for androdid like that, here is my code:
using UnityEngine;
using System.Collections;
public class PlayerMovement : MonoBehaviour {
public float speed;
public float speedj;
Rigidbody rb;
static Animator anim;
void Start()
{
rb = GetComponent<Rigidbody>();
anim = GetComponent<Animator>();
}
public void Walk ()
{
anim.SetTrigger ("Walk");
rb.velocity = new Vector3 (0,0,7f);
}
public void Left ()
{
transform.Rotate(0,-90f,0);
}
public void Right ()
{
transform.Rotate(0,90f,0);
}
public void Jump ()
{
anim.SetTrigger ("Jump");
rb.velocity = new Vector3 (0,4f,0);
}
public void StopVelocity ()
{
rb.velocity = Vector3.zero;
transform.Translate(0,0,0);
}
void FixedUpdate ()
{
float x = Input.GetAxis ("Horizontal") * Time.deltaTime * speed;
float z = Input.GetAxis ("Vertical") * Time.deltaTime * speed;
transform.Translate (0,0,z);
transform.Rotate (0,x,0);
if(Input.GetKey(KeyCode.Space))
{
anim.SetTrigger ("Jump");
rb.velocity = new Vector3 (0,speedj,0);
}
}
}
So this is it the fixedUpdate functionis for the computer the others are for buttons for android i am using event trigger for pointer up and down events pleasehelp me to change the code so that it will work for android like it works with Input.getAxis for computer thanks!
"when i click it moves a bit and then i need to click again but i want to hold and it will move continuously."
Using the EventTrigger here should be the optimal way. Check out OnPointerDown(); the function should be called for every frame. You should attach the EventTrigger to the button for it to work on mobiles.
"when i turn the character doesnt move the corect way."
Try moving using your Local Transforms Forward. Namely Transform.Forward(). It will allow you to move forward into the direction you set before, the Forward is always a Normalized Vector3. Moving in the way you are will use the world axis, your rotation wont matter at all.
I am trying to practice making third person controllers in Unity 3D. I am a beginner, and I am completely baffled on how to make my controller functional. I have been doing hours of research, but no thread I can find seem to answer my question. I have two scripts, a CameraController, and a CharacterController. My code is below.
CameraController:
using UnityEngine;
using System.Collections;
public class CameraController : MonoBehaviour {
public GameObject target;
public float rotationSpeed;
Vector3 offset;
Vector3 CameraDestination;
// Use this for initialization
void Start () {
offset = transform.position - target.transform.position;
CameraDestination = offset + transform.position;
rotationSpeed = 50f;
transform.position = CameraDestination;
}
// Update is called once per frame
void Update () {
transform.LookAt (target.transform.position);
float h = Input.GetAxisRaw ("Horizontal");
transform.RotateAround (target.transform.position, Vector3.up, Time.deltaTime * h * rotationSpeed);
target.transform.Rotate (0f, Time.deltaTime * h * rotationSpeed, 0f);
}
}
CharacterController:
using UnityEngine;
using System.Collections;
public class CharController : MonoBehaviour {
public float playerSpeed = 10f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
float Vertical = Input.GetAxis("Vertical");
transform.position += transform.forward * Time.deltaTime * playerSpeed * Vertical;
}
}
When either the left or right arrow key is pressed, both the player and the camera rotates. If I try to attach the camera to the player as a children, the camera's rotation becomes messed up, but if I do not attach the camera to the player, the camera stops following the player. If I try to set the camera to a specific position relative to the player, it stops revolving around the player like it is intended to do. I simply can not come up with a method that works.Thank you for answering my question in advance!
When I go about this, I like to have an empty gameObject which has 2 children, the camera and then the mesh of the character.
> CharacterController
> Camera
> CharacterRig
When you want to rotate the character, rotate the CharacterController, then when you want to rotate the Camera around the character, change your code to:
transform.RotateAround (CharacterRig.transform.position, Vector3.up, Time.deltaTime * h * rotationSpeed);
This will allow your camera to rotate irrespective of any character animation and should solve your issue. This is very important if you want to implement animations later, as you don't want to parent the camera to the thing that is being animated because it will move with the animation.
P.s. Your code appears fine. Certain that it is purely the way you have set up the game objects.
So I got this code to instantiate my gameobject Cannon, witch has a child "ball" attached to it. I'm trying to rotate the "ball" around the "cannon" when I use my left/right arrow keys.
using UnityEngine;
using System.Collections;
public class NewBehaviourScript : MonoBehaviour {
public GameObject Cannon = null;
public float speed = 1.0f;
void Start () {
Cannon = Instantiate (Resources.Load ("Prefabs/Cannon")) as GameObject;
}
// Update is called once per frame
void Update () {
if (Input.GetKey(KeyCode.LeftArrow)){
Cannon.transform.Rotate(Vector3.left * speed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.RightArrow)){
Cannon.transform.Rotate(Vector3.right * speed * Time.deltaTime);
}
}
}
There is no Vector3.left, that would be an inverse of Vector3.right so you would just write that as "-Vector3.right". But regardless, you shouldnt be passing the vector3 of the direction you want to rotate in, but the axis in which you want to rotate around. in this case, you would use Vector3.up for both arguments, and use "* speed" for one, and "* -speed" for the other.