(I'm relatively new to Unity) I'm making a scene where I want the camera to move in the opposite direction of the mouse movement when I hold down the right mouse button.
The scene is isotropic, which is why the camera is orthographic.
[SerializeField] private Camera cam;
private Vector3 dragOrigin = Vector3.zero;
public float speed = 10;
void Update(){
if(Input.GetMouseButtonDown(1)){
dragOrigin = cam.ScreenToWorldPoint(Input.mousePosition);
}
if(Input.GetMouseButton(1)){
Vector3 difference = cam.ScreenToWorldPoint(Input.mousePosition) - cam.transform.position;
Vector3 targetPosition = dragOrigin - difference;
//targetPosition.y = cam.transform.position.y;
cam.transform.position = Vector3.Lerp(cam.transform.position, targetPosition, speed * Time.deltaTime);
}
}
This works, but there is the problem that the y-value of the camera changes as well. It should always stay at the same height.
If I use
targetPosition.y = cam.transform.position.y;
the camera stays on the same y-position, but it moves slower when I move it up and down.
How can I rewrite the code so that only the x and z values change and that the camera moves with the same speed in all directions?
Thanks in advance.
Related
I made input joysticks for mobile game. One that moves the player and other one that changes it's rotation. Both are working fine but only problem is that when I change players rotation and release that joystick it jumps to it's original rotation. Here's my script:
public GameObject player;
private PlayerInput playerInput;
void Update()
{
Vector2 input = playerInput.actions["Move"].ReadValue<Vector2>();
Vector3 move = new Vector3(input.x, input.y, 0);
player.transform.position += move * speed * Time.deltaTime;
Vector2 look = playerInput.actions["Look"].ReadValue<Vector2>();
player.transform.rotation = Quaternion.LookRotation(Vector3.forward, look);
}
I typically solve this by ignoring rotation values of small magnitude and maintaining the last frame's orientation in said case. You might have to tune the threshold below to filter out the correct values.
public GameObject player;
private PlayerInput playerInput;
private Vector2 look;
void Update()
{
Vector2 input = playerInput.actions["Move"].ReadValue<Vector2>();
Vector3 move = new Vector3(input.x, input.y, 0);
player.transform.position += move * speed * Time.deltaTime;
var inputLook = playerInput.actions["Look"].ReadValue<Vector2>();
look = inputLook.magnitude > 0.1f ? inputLook : look;
player.transform.rotation = Quaternion.LookRotation(Vector3.forward, look);
}
I am making a puzzle game with drag-and-drop mechanics. Moving objects is implemented through Configurable Joint. When you click the left mouse button, I put the object attached to the player's body in the Conected body of the dragged object
Joint parameters
Player object hierarchy
RigidBody of the dragged object
Hand's location depends on the player's camera rotation, the rotation script:
[SerializeField] private GameObject _Body;
private float _SensitivityHor = 9.0f, _RotationX = 0, _SensitivityVert = 5.0f, _MinimumVert = -45.0f, _MaximumVert = 45.0f;
void FixedUpdate()
{
//Camera rotation
Vector3 CameraAngles = transform.localEulerAngles;
_RotationX -= Input.GetAxis("Mouse Y") * _SensitivityVert;
_RotationX = Mathf.Clamp(_RotationX, _MinimumVert, _MaximumVert);
float delta = Input.GetAxis("Mouse X") * _SensitivityHor;
float rotationY = CameraAngles.y + delta;
transform.localEulerAngles = new Vector3(_RotationX, rotationY, 0);
//Body rotation
Vector3 BodyAngles = _Body.transform.eulerAngles;
Vector3 _BodyrotationY = new Vector3(BodyAngles.x, CameraAngles.y, BodyAngles.z);
_Body.transform.eulerAngles = _BodyrotationY;
}
The problem is that when you rotate the camera objects move jerkily (https://www.youtube.com/watch?v=Gn4HS4NIndg), but on the scene all looks fine, I can not figure out what the problem is, please help.
The problem was in the rigidbody of the dragged object, after turning off the interpolation and changing the collision detection to discrete, the camera stopped moving jerkily:
Fixed Rigidbody
I have made a script for player movement in a 3D game in Unity.
I like how the movement works, but when I jump while moving, the player keeps moving in that direction at the same speed till it falls to the ground, which is the expected behavior for this script.
But I want to be able to move the player in the air slightly (not fully controllable.)
I'm imagining kinda like a minecraft like movement to be exact.
Any advice to improve this code would be greatly apprecciated.
This is my code.
using System.IO;
using UnityEngine;
public class VelocityMovement : MonoBehaviour
{
#region Variables
public float speed;
public float gravity;
public float maxVelocityChange;
public float jumpHeight;
public float raycastDistance;
public Rigidbody rb;
#endregion
private void Awake()
{
//gets rigidbody, freezes rotation of the rigidbody, disables unity's built in gravity system on rigidbody.
rb = GetComponent<Rigidbody>();
rb.freezeRotation = true;
rb.useGravity = false;
}
private void Update()
{
//Jump system
if(Grounded())
{
if (Input.GetKeyDown(KeyCode.Space))
{
rb.velocity = new Vector3(rb.velocity.x, CalculateJumpSpeed(), rb.velocity.z);
}
}
}
private void FixedUpdate()
{
//Moves the player when on the ground.
if (Grounded())
{
//Calculate how fast the player should be moving.
Vector3 targetVelocity = new Vector3(playerInputs.hAxis, 0, playerInputs.vAxis);
targetVelocity = transform.TransformDirection(targetVelocity);
targetVelocity *= speed ;
//Calculate what the velocity change should be
Vector3 velocity = rb.velocity;
Vector3 velocityChange = (targetVelocity - velocity);
velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
velocityChange.y = 0f;
//applies a force equal to the needed velocity change
rb.AddForce(velocityChange, ForceMode.VelocityChange);
}
//Adds gravity to the rigidbody
rb.AddForce(new Vector3(0, -gravity * rb.mass, 0));
}
//Checks if player is on the ground
private bool Grounded()
{
return Physics.Raycast(transform.position, Vector3.down, raycastDistance);
}
//calculates how high the player should be jumping
private float CalculateJumpSpeed()
{
return Mathf.Sqrt(2 * jumpHeight * gravity);
}
}
private void FixedUpdate()
{
//check how big the movement is. Swap SomeSmallValue with a float like 0.1f
float actualSpeed;
Vector3 velocity;
if(Grounded())
{
actualSpeed = speed;
//HERE IT IS NOT, THIS DOESN'T MATTER
velocity = rb.velocity
}
else{
actualSpeed = speed * SomeSmallValue;
//WITH THIS rb KEEPS THE SPEED IF ANY BUTTON IS PRESSED
velocity = 0;
}
//Moves the player ALWAYS.
//Calculate how fast the player should be moving.
Vector3 targetVelocity = new Vector3(playerInputs.hAxis, 0, playerInputs.vAxis);
targetVelocity = transform.TransformDirection(targetVelocity);
//if Grounded == true the movement is exactly the same than before, because actualSpeed = speed.
//If Grounded == false, the movement is so light
targetVelocity *= actualSpeed;
//Calculate what the velocity change should be
//I'VE PLACED THIS UP IN ORDER TO CALL Grounded() ONLY ONE TIME
//Vector3 velocity = rb.velocity;
Vector3 velocityChange = (targetVelocity - velocity);
velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
velocityChange.y = 0f;
//applies a force equal to the needed velocity change
rb.AddForce(velocityChange, ForceMode.VelocityChange);
//Adds gravity to the rigidbody
rb.AddForce(new Vector3(0, -gravity * rb.mass, 0));
}
If your code is working fine, try something like this. Just moved the grounded condition. Now the movement works also at air time. We check with that grounded bool how big the movement is.
If I understood you correctly you want to slow down what your movements do while mid air.
at least that is the case for left and right.
If I did undersand you correctly, you would make an else{} after the if(Grounded())
and go from there, may make some float variable that acts as a multiplier for you left/right control while mid air, aswell as another float variable for forward and backwards.
Inside that else you could just multiply you speed with the variables (depending on the axis) and you should get some form of slower movement there.
I hope that helped you out at least a bit.
I'm using this simple CameraFollow script to have my camera follow behind my player's movements. The problem is that my player can spin a full 360 degrees, and the camera has to rotate with it. This works well, except when completing a full turn. When the player transform goes from 359 degrees back to 0, the camera flickers as it does a full backwards 360 degree loop to catch up, instead of moving 1 degree to catch up. How can I fix this?
In the code below the 'target' is my player, and 'trans' is the transform of the camera. It's also worth noting that if the player stops at exactly 0 degrees it jumps back to 180 for some reason.
public class CameraFollow : MonoBehaviour {
[SerializeField] Transform target;
[SerializeField] Vector3 defaultDistance = new Vector3(0f, 3.5f, -12f);
[SerializeField] float distanceDamp = 0.05f;
[SerializeField] Vector3 velocity = Vector3.one;
Transform trans;
private void Awake()
{
trans = transform;
}
private void FixedUpdate()
{
Vector3 toPos = target.position + (target.rotation * defaultDistance);
Vector3 curPos = Vector3.SmoothDamp(trans.position, toPos, ref velocity, distanceDamp);
trans.position = curPos;
trans.up = target.up;
}
}
I solved my issue by changing the last line from
trans.up = target.up;
to
trans.rotation = target.rotation;
I am trying to make a simple game where I am shooting a projectile when the user touches the screen, I first spawn 8 projectiles (sprites) and when the user touches the screen I would like the top projectile to fly in the touch direction. I was able to do this; However, every time I shoot, the projectile goes in the wrong direction, here is an image which will illustrate the issue.
Obviously the image is still here but the object will continue flying until it goes out of the screen and then gets destroyed.
Here is the code snippet that handles this
GameplayController.cs
if (Input.GetMouseButtonDown(0))
{
Vector3 position = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0);
position = Camera.main.ScreenToWorldPoint(position);
GameObject target;
target = new GameObject();
target.transform.position = position;
Arrow comp = currentArrows[0].GetComponent<Arrow>();
comp.setTarget(target.transform);
comp.GetComponent<Arrow>().arrowSpeed = 12;
comp.GetComponent<Arrow>().shoot = true;
currentArrows.RemoveAt(0);
Destroy(target);
}
I know I am getting the mouse input here and not the phone touch and that's fine for me, later I will convert it to the touch input.
Arrow.cs
public bool shoot = false;
public float arrowSpeed = 0.0f;
public Vector3 myDir;
public float speed = 30.0f;
private Transform target;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if(shoot)
{
transform.position += transform.right * arrowSpeed * Time.deltaTime;
}
}
public void setTarget(Transform targetTransform)
{
this.target = targetTransform;
Vector3 vectorToTarget = target.position - transform.position;
float angle = Mathf.Atan2(vectorToTarget.y, vectorToTarget.x) * Mathf.Rad2Deg;
Quaternion q = Quaternion.AngleAxis(angle, Vector3.forward);
transform.rotation = Quaternion.Slerp(transform.rotation, q, Time.deltaTime * speed);
}
private void OnBecameInvisible()
{
print("Disappeared");
Destroy(gameObject);
Gameplay.instance.isShooting = false;
}
Vector3 position = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0);
I think that your problem is that you're getting the screen coordinates by click, not the world coordinates, which is actually two different things. In order to direct your projectile correctly you need to convert your screen coordinates to world like it's done here.
The next thing is how you move the projectile:
transform.position += transform.right * arrowSpeed * Time.deltaTime;
You're moving the projectile to the right and then rotating it somehow. Maybe you should try to move it with Vector3.Lerp, which will be easier and rotate it with Transform.LookAt.