I was making a game where there is a plane which I control using the wasd keys, it rotates and translates. Up-to that its fine, but I would like the plane to re-align to its original rotation when I lift the key. The code I made up is this but it doesn't work. The plane realigns for only one frame and then "misaligned" again . This is the code -**
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class planemovement : MonoBehaviour
{
public int fspeed = 10;
float horizontal; float zrot;
float vertical; float yrot;
public float sense; public int lim = 0;
void Start()
{
}
// Update is called once per frame
void Update()
{
float rotz = Input.GetAxis("Vertical"); float roty = Input.GetAxis("Horizontal");
horizontal = Input.GetAxis("Horizontal");
vertical = Input.GetAxis("Vertical");
transform.Translate(Vector3.forward * fspeed * Time.deltaTime);
transform.Translate(Vector3.right * sense * Time.deltaTime * horizontal*20f);
transform.Translate(Vector3.up * sense * Time.deltaTime * vertical);
zrot -= rotz;
yrot -= roty;
zrot = Mathf.Clamp(zrot, -lim, lim);
yrot = Mathf.Clamp(yrot, -lim, lim);
transform.localRotation = Quaternion.Euler(zrot, 0f, yrot);
}
}
Rotation in Unity C# is usually quite wonky, the only time it is exact is when you use Quaternions properly.
public Quaternion startQuaternion;
void Start() {
startQuaternion = transform.rotation;
}
//when you want to reset to original
transform.rotation = startQuaternion;
https://docs.unity3d.com/ScriptReference/Quaternion.html
I don't quite understand, but if you using a rigidbody, you can try using "Quaternion.Lerp" and MoveRotation.
Quaternion.Lerp has three parameters and creates a rotation from point A to B, with a speed ugual to T (T goes from 0 to 1).
var currentRot = transform.rotation
var desired Rot = rotation on which the plane must be aligned
Quaternion RotPlane = Quaternion.Lerp (currentRot, desiredRot, 0.5)
MoveRotation(RotPlane)
You can use an if (Input.GetKeyUp) and put the script underneath it, so every time you release the buttons the plane returns to the desired rotation.
Related
I recently started on unity and I wanted to make simple movement which can be seen below.
using System.Collections.Generic;
using UnityEngine;
public class movement : MonoBehaviour
{
//Variables
float speed = 5.0f;
public float turnSpeed = 4.0f;
public float moveSpeed = 2.0f;
public float minTurnAngle = -90.0f;
public float maxTurnAngle = 90.0f;
private float rotX;
//Other
Vector3 Char_velocity;
Rigidbody Physics;
void Start()
{
Physics = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
//Get axis on which we want to move
if (Input.GetButton("Vertical"))
{
//Creating vector which velocity is calculated based on vect3, speed and gets FPS compensation via fixed
//delta time
Char_velocity = new Vector3(Input.GetAxis("Horizontal"), 0.0f, Input.GetAxis("Vertical"));
Physics.MovePosition(transform.position + Char_velocity * speed * Time.fixedDeltaTime);
}
if (Input.GetButton("Horizontal"))
{
Char_velocity = new Vector3(Input.GetAxis("Horizontal"), 0.0f, Input.GetAxis("Vertical"));
Physics.MovePosition(transform.position + Char_velocity * speed * Time.deltaTime);
}
float y = Input.GetAxis("Mouse X") * turnSpeed;
rotX += Input.GetAxis("Mouse Y") * turnSpeed;
rotX = Mathf.Clamp(rotX, minTurnAngle, maxTurnAngle);
transform.eulerAngles = new Vector2(-rotX, transform.eulerAngles.y + y);
}
}
Mouse movement has been the problem for me. I got it to somewhat work but I have 2 issues. The camera should move the whole body while rotating from side to side but instead rotates the body when moving along the Y axis.
hello. I'm making a mobile joystick game where I should fly a plane. So I wrote a script that works but the plane does not turn as I wanted. for example I want to turn completely to the right to do 90 degrees but the plane continues straight by moving a little to the rightyour text
here is the script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlaneController : MonoBehaviour
{
public Joystick joystick;
public float forwardSpeed = 15f;
public float horizontalSpeed = 4f;
public float verticalSpeed = 4f;
public float smoothness = 5f;
public float maxHorizontalRotation=0.1f;
public float maxVerticalRotation = 0.06f;
public float rotationSmoothness=5f;
public Rigidbody rb;
private float horizontalInput;
private float verticalInput;
public float forwardSpeedMultiplier= 100f;
private float speedMultiplier=1000f;
// Start is called before the first frame update
void Start()
{
rb.GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButton(0) || Input.touches.Length !=0) {//celui la pour jouer avec le téléphone
horizontalInput = joystick.Horizontal;
verticalInput= joystick.Vertical;
}
else // pour le pc
{
horizontalInput=Input.GetAxisRaw("Horizontal");
verticalInput=Input.GetAxisRaw("Vertical");
}
HandlePlaneRotation();
}
private void FixedUpdate(){
HandlePlaneMovement();
}
private void HandlePlaneMovement(){
rb.velocity=new Vector3(
rb.velocity.x,
rb.velocity.y,
forwardSpeed * forwardSpeedMultiplier * Time.deltaTime);
float xVelocity= horizontalInput * speedMultiplier * horizontalSpeed*Time.deltaTime;
float yVelocity= -verticalInput * speedMultiplier * verticalSpeed*Time.deltaTime;
rb.velocity= Vector3.Lerp(
rb.velocity,
new Vector3(xVelocity,yVelocity, rb.velocity.z),
Time.deltaTime * smoothness);
}
private void HandlePlaneRotation(){
float horizontalRotation = horizontalInput * maxHorizontalRotation;
float verticalRotation = verticalInput *maxVerticalRotation ;
transform.rotation = Quaternion.Lerp(
transform.rotation,
new Quaternion
(verticalRotation,
transform.rotation.y,
horizontalRotation,
transform.rotation.w),Time.deltaTime*rotationSmoothness
);
}
}
*Thank you*
I want you to tell me what I should do to fix this problem.
I already tried several things but I couldn't.
Thank.
Well, as I see in your code you are having a bit problem with how plane movement works.
first planes always have forward velocity so you don't need a joystick for handling that :
rb.AddForce(transform.forward * speed, ForceMode.Impulse);
But you can use the JoyStick joyStick for changing the forward vector of your plane (changing y Euler angle) and here is an example of doing that :
x = joyStick.Horizontal;
y = joyStick.Vertical;
yRot = Quaternion.LookRotation(Vector3.forward * y + Vector3.right * x, Vector3.up).eulerAngles.y;
It's a similar code as Assets/Joystick Pack/Examples/JoystickPlayer.cs but here we convert that force to a forward vector and use that for setting the Euler angle of an object.
Note: You can add some extra movement waves or noises to add more feeling to your plane movement.
Hope it was helpful.
This is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
// Tweekable move speed
public float MoveSpeed = 4;
// Set what distance it should be from the target
int MaxDist = 10;
int MinDist = 5;
// This is the target
public Transform Mouse;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
// Keep looking at an object
transform.LookAt();
// Turn off gravity
Physics2D.gravity = Vector2.zero;
// When distance is over minimun
if (Vector3.Distance(Mouse.position, Mouse.position) >= MinDist)
{
// Keep distance
transform.position += transform.forward * MoveSpeed * Time.deltaTime;
// When it's between max and minimun
if (Vector3.Distance(transform.position, Mouse.position) <= MaxDist)
{
}
}
}
// I imported this code from another project so the enemy keeps looking at the player, and keeps his distance. it was a 3D project, so there may be more errors, and this is also my first time creating a game. Be gentle
I am working on a similar project right now.
Here is the code I use to rotate the player (first part) and then move it into that direction (second part):
public Rigidbody2D rb;
public float speed;
void Update()
{
//get mouse position
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
//calculating the angle
float AngleRad = Mathf.Atan2(mousePos.y - transform.position.y, mousePos.x -
transform.position.x);
float AngleDeg = (180 / Mathf.PI) * AngleRad;
//rotating the player
Player.transform.rotation = Quaternion.Euler(0, 0, AngleDeg);
//second part
Vector3 mouseDir = mousePos - transform.position;
mouseDir.z = 0f;
mouseDir = mouseDir.normalized;
rb.AddForce(mouseDir * speed);
}
If the player rotates, but it is looking in the wrong way (in my case), then play around with the the last line of the first part. The following code worked fine for me:
transform.rotation = Quaternion.Euler(0, 0, AngleDeg - 90);
If you want the player to move at a constant speed, then you can use
rb.velocity = mouseDir * speed;
instead of
rb.AddForce(mouseDir * speed);
in the last line of the second part.
Your Player-Gameobject needs a Rigidbody2D component. I also added an if-statement around the second part, so the player only moves to the wanted direction when (for example) space is pressed, but always looks to the mouse.
I have this script below and I want my player to always move towards the rotation angle, which doesn't happen. It only changes direction when I click.
My purpose is for the player to move at all times and towards the rotation which should be controlled by mouse position/mouse x axis (kind of like auto-run, but always change rotation based on mouse, not just move right or left).
I've tried about 10 different methods, nothing worked so far...
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MovementController : MonoBehaviour
{
public float speed = 4;
public float rot = 0f;
public float rotSpeed = 80;
public float gravity = 8;
private Camera cam;
Vector3 moveDir = Vector3.zero;
CharacterController controller;
Animator anim;
// Start is called before the first frame update
void Start()
{
controller = GetComponent<CharacterController> ();
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
float horizontalSpeed = 8.0f;
//Get the mouse delta. This is not in the range -1...1
float h = horizontalSpeed * Input.GetAxis("Mouse X");
float z = horizontalSpeed * Input.GetAxis("Mouse Y");
transform.Rotate(0, h, 0);
//Move Input
if(controller.isGrounded){
if(Input.GetMouseButtonUp(1))
{
anim.SetInteger ("condition", 1);
moveDir = new Vector3 (0,0,1) * speed;
// moveDir *= speed;
moveDir = transform.TransformDirection(moveDir);
}
if(Input.GetMouseButtonDown(1))
{
anim.SetInteger("condition", 0);
moveDir = Vector3.zero;
}
}
moveDir.y -= gravity * Time.deltaTime;
controller.Move(moveDir * Time.deltaTime);
}
}
Transform.LookAt
Just get a cursor position and that's it
Vector3 direction = target.position - player.transform.position;
Quaternion finalPlayerRotation = Quaternion.LookRotation(direction);
player.transform.rotation = finalPlayerRotation;
This also works in some cases:
Vector3 direction = target.position - player.transform.position;
player.transform.right /*You may need to change the Right to upper, -upper, -Right depend on the player rotation and the target position*/ = direction;
I made a simple racing game. The camera follows the car (player) and its position and rotation is based on car's Y rotation. I want to smooth the camera rotation, but when it crosses 0 degree point, it rotates 360 degrees.
Here's the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Camera : MonoBehaviour {
public Transform camera, player;
void Update() {
Vector3 cameraPosition = camera.transform.position;
float cameraRotation = camera.eulerAngles.y;
float playerRotation = player.eulerAngles.y;
Vector3 playerPosition = player.transform.position;
cameraPosition.x = (Mathf.Sin((playerRotation / 180) * Mathf.PI) * -6 + player.position.x);
cameraPosition.y = playerPosition.y + 2.5f;
cameraPosition.z = (Mathf.Cos((playerRotation / 180) * Mathf.PI) * -6 + player.position.z);
camera.transform.position = cameraPosition;
cameraRotation = cameraRotation + (playerRotation-cameraRotation)/2;
camera.localRotation = Quaternion.Euler(20f, cameraRotation, 0f);
}
}
I figured out that this rotation is caused by smoothing script:
cameraRotation = cameraRotation + (playerRotation-cameraRotation)/2;
How to prevent this unwanted rotation?
This is how I would do it:
public int smoothSpeed = 1f; // Change accordingly to increase/decrease smooth speed.
Then in update:
Vector3 directionToCar = player.position - camera.position;
Quaternion desiredRotation = Quaternion.LookRotation(directionToCar);
camera.rotation = Quaternion.Slerp(camera.rotation, desiredRotation, Time.deltaTime * smoothSpeed);
On a side node, if this camera script is attached to the camera, you don't have to make a field referencing the camera's transform. You can simply do transform.position instead of camera.transform.position.
A simpler solution to using the Slerp is to use Mathf.SmoothDamp, which has a variant called Mathf.SmoothDampAngle which handles the looping correctly. I've also had success doing the wraparound by hand but its not a very rewarding experience
using UnityEngine;
public class RotFollow : MonoBehaviour
{
[SerializeField] Transform carTransform;
[SerializeField] float smoothTime = .4f;
float currentYAngle;
float targetYAngle;
float angleVel;
void Update()
{
targetYAngle = carTransform.rotation.eulerAngles.y;
currentYAngle = Mathf.SmoothDampAngle(currentYAngle, targetYAngle, ref angleVel, smoothTime);
transform.rotation = Quaternion.Euler(
transform.rotation.eulerAngles.x,
currentYAngle,
transform.rotation.eulerAngles.z);
}
}