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.
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.
How do I use Cos and Sin animation, and at the same time follow the target(Player)?
I'm not seeing how to do that. I'm a beginner in programming.
public class Spirit : MonoBehaviour
{
//target player
private bool isFollowing;
public float followSpeed;
public Transform followTarget;
//Sin & Con animation
[SerializeField] private float frequency;
[SerializeField] private float amplitude;
[SerializeField] private float _frequency;
[SerializeField] private float _amplitude;
private void FixedUpdate()
{
if (isFollowing)
{
//This is used to follow the player
transform.position = Vector3.Lerp(transform.position, followTarget.position, followSpeed * Time.deltaTime);
//This is the animation with Cos and Sin.
float x = Mathf.Cos(Time.time * _frequency) * _amplitude;
float y = Mathf.Sin(Time.time * frequency) * amplitude;
float z = transform.position.z;
transform.position = new Vector3(x, y, z);
}
}
}
Making a spirit ball follow the player and animating it using Cos and Sin using the frequency and amplitude of both X and Y coordinates.
Your code is actually very close but you are overwriting the transform.position later so your previous lerp is not working. Just include your cos and sin calculations while you are handling the lerp. Here is how you can modify your code to make it work.
//target player
private bool isFollowing = true; // for testing
[SerializeField] private float _followSpeed = 1f;
[SerializeField] private Transform _followTarget;
//Sin & Con animation
[SerializeField] private float _frequency = 1f;
[SerializeField] private float _amplitude = 1f;
private void Update()
{
if (!isFollowing) return;
// including cos to target position.x and sin to target position.y
Vector3 targetPosition = new Vector3(_followTarget.position.x + Mathf.Cos(Time.time * _frequency) * _amplitude,
_followTarget.position.y + Mathf.Sin(Time.time * _frequency) * _amplitude,
_followTarget.position.z);
//now put above calculation into lerp
transform.position = Vector3.Lerp(transform.position, targetPosition, _followSpeed * Time.deltaTime);
}
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.
I have a player-object, and a player and a camera attached to it as childs.
I would like to rotate the camera in a circle around the player so that it always faces the player (which is centered at 0,0,0).
I have a 2D approach which I need to convert 3D.
What would this script look like for 3D?
Thank you.
using UnityEngine;
using System.Collections;
public class circularMotion : MonoBehaviour {
public float RotateSpeed;
public float Radius;
public Vector2 centre;
public float angle;
private void Start()
{
centre = transform.localPosition;
}
private void Update()
{
angle += RotateSpeed * Time.deltaTime;
var offset = new Vector2(Mathf.Sin(angle), Mathf.Cos(angle)) * Radius;
transform.localPosition = centre + offset;
}
}
Well, one approach could be to define an upwards vector and then rotate around the corresponding axis.
using UnityEngine;
public class circularMotion : MonoBehaviour
{
public float RotateSpeed = 1;
public float Radius = 1;
public Vector3 centre;
public float angle;
public Vector3 upDirection = Vector3.up; // upwards direction of the axis to rotate around
private void Start()
{
centre = transform.localPosition;
}
private void Update()
{
transform.up = Vector3.up;
angle += RotateSpeed * Time.deltaTime;
Quaternion axisRotation = Quaternion.FromToRotation(Vector3.up, upDirection);
// position camera
Vector3 offset = axisRotation * new Vector3(Mathf.Sin(angle), 0, Mathf.Cos(angle)) * Radius;
transform.localPosition = centre + offset;
// look towards center
transform.localRotation = axisRotation * Quaternion.Euler(0, 180 + angle * 180 / Mathf.PI, 0);
}
}
My code below rotates an object and moves them based on the angle of the joystick on the controller:
using UnityEngine;
using System.Collections;
public class PlayerControllerTEST : MonoBehaviour
{
public float moveSpeed;
public float h;
public float v;
public float moveX;
public float moveZ;
public Rigidbody rb;
// Use this for initialization
void Start()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
h = Input.GetAxis("Horizontal");
v = Input.GetAxis("Vertical");
moveX = (h * moveSpeed) * Time.deltaTime;
moveZ = (v * moveSpeed) * Time.deltaTime;
transform.Translate(moveX, 0f, moveZ, Space.World);
Quaternion rotate = Quaternion.Euler(0f, (Mathf.Atan2(h, v) * Mathf.Rad2Deg), 0f);
Debug.Log(rotate);
rb.MoveRotation(rotate);
}
}
However when I let go of the joystick, the object is snapping back to an angle of 0 degrees. I'm not sure how I would get it to keep the angle before the joystick is essentially let go.