I am trying to replicate the editor's camera for runtime use, and all is working as expected, but I am trying to Ease the movement and can't get it working right. Here is my code for the movement. It works correctly but isn't Eased out like I want.
Vector3 move = Vector3.zero;
if (Input.GetKey(KeyCode.W))
move += Vector3.forward * currentSpeed;
if (Input.GetKey(KeyCode.S))
move -= Vector3.forward * currentSpeed;
if (Input.GetKey(KeyCode.D))
move += Vector3.right * currentSpeed;
if (Input.GetKey(KeyCode.A))
move -= Vector3.right * currentSpeed;
if (Input.GetKey(KeyCode.E))
move += Vector3.up * currentSpeed;
if (Input.GetKey(KeyCode.Q))
move -= Vector3.up * currentSpeed;
transform.Translate(move);
I have tried a destination Vector3, setting that to move, then lerping the position to destination. This does Ease it as expected, but then the directions are all broken. Left moves forward, right moves back, and so on.
I have tried moving to fixedUpdate but still no luck.
Any help would be greatly appreciated!
Try to use CharacterController. It is component from Unity. It is easy to use and smooth.
public CharacterController controler;
public void Start(){
controller = GetComponent<CharacterController>();}
public void Move(){
controller.Move(moveDirection * Time.deltaTime);}
On youtube you can find tutorials from CharacterController.
After much experimentation, easing/smoothing can be achieved by doing the following in an update loop:
float x, y, z;
x = Input.GetAxis("Horizontal") * currentSpeed * Time.deltaTime;
z = Input.GetAxis("Vertical") * currentSpeed * Time.deltaTime;
y = 0;
transform.Translate(x,y,z);
Related
i am new in unity. I want to car game with mouse control to Unity 2D. I was trying this code but not working. Car vibrates when i move mouse over car. I want it to work perfectly when the mouse hovers over the car. how can i do this? my code is as follows:
private void OnMouseOver()
{
// Distance from camera to object. We need this to get the proper calculation.
float camDis = cam.transform.position.y - my.position.y;
// Get the mouse position in world space. Using camDis for the Z axis.
Vector3 mouse = cam.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, camDis));
float AngleRad = Mathf.Atan2 (mouse.y - my.position.y, mouse.x - my.position.x);
float angle = (180 / Mathf.PI) * AngleRad;
body.rotation = angle;
Vector3 temp = Input.mousePosition;
temp.z = 10f; // Set this to be the distance you want the object to be placed in front of the camera.
this.transform.position = Camera.main.ScreenToWorldPoint(temp);
}
I'm not too clear on the effect you want to achieve, but if you just want the object to move and turn gradually instead of instantly changing, that can be achieved using Vector3.MoveTowards and Quaternion.RotateTowards, e.g.:
private void OnMouseOver()
{
// Distance from camera to object. We need this to get the proper calculation.
float camDis = cam.transform.position.y - my.position.y;
// Get the mouse position in world space. Using camDis for the Z axis.
Vector3 mouse = cam.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, camDis));
float AngleRad = Mathf.Atan2 (mouse.y - my.position.y, mouse.x - my.position.x);
float angle = (180 / Mathf.PI) * AngleRad;
//body.rotation = angle; //??
float turnSpeed = 200f;
transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.Euler(0, 0, angle), turnSpeed * Time.deltaTime);
Vector3 temp = Input.mousePosition;
temp.z = 10f; // Set this to be the distance you want the object to be placed in front of the camera.
float moveSpeed = 10f;
transform.position = Vector3.MoveTowards(transform.position, Camera.main.ScreenToWorldPoint(temp), moveSpeed * Time.deltaTime);
}
Edit in response to comment: If you want it to move only when the player begins the drag on the car, then yes, putting it in OnMouseDrag() would work. If you want it to move when the player drags from anywhere on the screen, you'd want to put the movement code in Update() and check whether the left mouse button is being held down using Input.GetMouseButton(0).
If you wanted it to keep moving towards the last mouse position (e.g. player can click on the screen and it will move there while the mouse button is not being held down), you'd need to keep the last mouse location in a class variable and move towards that in Update().
Incidentally if you want it to move a bit more like a car, you could always move it forwards while it turns towards the mouse, rather than moving it directly towards the mouse even if it's facing a different direction.
Here's an example but be aware that I've changed a few things that didn't seem necessary to me, like using my.position rather than transform.position. If you use it you may need to adapt it to suit the rest of your code.
public float maxTurnSpeed = 250f;
public float maxSpeed = 8f;
public float stopDistance = 0.5f;
public float slowDistance = 2.5f;
private void Update()
{
if( !Input.GetMouseButton(0) ) // If the mouse button is NOT being held down this frame
return; // Don't move. (Ideally you would decelerate the car rather than stopping it immediately though.)
// Remove the above two lines and move all of this to OnMouseDrag if you want to require the drag to begin on this object to move it.
// Also note: this code now assumes the object begins in the desired z position and doesn't change it, rather than forcing a z position.
// Distance from camera to object. We need this to get the proper calculation.
float camDis = transform.position.z - Camera.main.transform.position.z; // Changed this to use z instead of y as it appeared to be a mistake(?)
// Get the mouse position in world space. Using camDis for the Z axis.
Vector3 mouse = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, camDis));
float distanceFromMouse = Vector3.Distance(transform.position, mouse);
// If we're further away from the mouse than stopDistance, move.
if( distanceFromMouse > stopDistance )
{
float speedMultiplier = 1.0f;
float rotationMultiplier = 1.0f;
// If we're closer to the mouse than slowdistance, slow down proportionately to the remaining distance from stopDistance
if( distanceFromMouse < slowDistance )
{
speedMultiplier = (distanceFromMouse - stopDistance) / (slowDistance - stopDistance);
}
// Reduce turning speed as we approach stopDistance, but not by as much as speed is reduced
if( speedMultiplier < 0.5f )
rotationMultiplier = speedMultiplier * 2f;
float AngleRad = Mathf.Atan2(mouse.y - transform.position.y, mouse.x - transform.position.x);
float angle = (180 / Mathf.PI) * AngleRad;
// Turn the car towards facing the mouse position
transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.Euler(0, 0, angle), maxTurnSpeed * rotationMultiplier * Time.deltaTime);
// Move the car towards its transform.right vector.
transform.position += transform.right * (maxSpeed * speedMultiplier * Time.deltaTime);
}
}
I'm making a 3D space game where you fly a ship. its first person from the cockpit.
All my movements work like a charm (W/S = speed up/down, Q/R = rotate left/right) and the mouse moves the ship around.
But if I use my rotate buttons, the mouse stays "stuck". Easiest way to explain it is: when I fly normal, moving the mouse up pans the camera up, and down - pans down.
But if I fly upside down the mouse doesnt seem to notice it and pans the wrong way (inverted). Like it doenst know my rotation. On the side its even weirder. The mouse keeps going up on the initial rotation not on the new one I dont know how to solve it.
What I basicly want to do is also turn the mouse orientation when pressing Q or E
This is my rotate/mouse script:
if (Input.GetKey("q"))
{
orientationPanel.transform.Rotate(-Vector3.left * 100f * Time.deltaTime);
cam.transform.Rotate(Vector3.forward * 100f * Time.deltaTime);
transform.Rotate(Vector3.forward * 100f * Time.deltaTime);
}
if (Input.GetKey("e"))
{
orientationPanel.transform.Rotate(Vector3.left * 100f * Time.deltaTime);
cam.transform.Rotate(-Vector3.forward * 100f * Time.deltaTime);
transform.Rotate(Vector3.forward * 100f * Time.deltaTime);
}
if (Input.GetMouseButtonDown(0) && Time.time > nextFire)
{
nextFire = Time.time + fireRate;
Fire();
}
float mouseX = Input.GetAxis("Mouse X");
float mouseY = -Input.GetAxis("Mouse Y");
rotY += mouseX * mouseSensitivity * Time.deltaTime;
rotX += mouseY * mouseSensitivity * Time.deltaTime;
rotX = Mathf.Clamp(rotX, -clampAngle, clampAngle);
rotZ = orientationPanel.transform.rotation.z;
Quaternion localRotation = Quaternion.Euler(rotX, rotY, rotZ);
transform.rotation = localRotation;
You need to rotate your ship always in local space. If you move mouse to right - always move nose of the ship to right.
Rotate(axis, angle, Space.Self);
For example
Rotate(Vector3.up, rotY, Space.Self);
Rotate(Vector3.right, rotX, Space.Self);
This will also fix rotation with Q/E, because with
Quaternion localRotation = Quaternion.Euler(rotX, rotY, rotZ);
transform.rotation = localRotation;
you basically override changes made with
transform.Rotate(Vector3.forward * 100f * Time.deltaTime);
transform.Rotate(Vector3.forward * 100f * Time.deltaTime);
i have start a project in unity 3d.I want to make a spaceship that moving forward,but when i pressed the ArrowUp then i want to change its y postion to
( currentpos+ 1.5 ) but i want this smoothly.
this is my code
transform.position += transform.forward * Time.deltaTime * 10f;
if (Input.GetKey (KeyCode.UpArrow))
transform.position = new Vector3 (transform.position.x, 5f,
transform.position.z);
through the above code the Y position of object can b changed but it work so fast and i want to make it smooth.
so please help me.
I think the best solution to your problem is to use Mathf.SmoothDamp.
Example:
private float targetY = 0f;
private float verticalVelocity = 0f;
private const float smoothTime = 1f;
private void Update()
{
transform.position += transform.forward * Time.deltaTime * 10f;
if (Input.GetKey(KeyCode.UpArrow))
{
targetY = 5f;
}
float y = Mathf.SmoothDamp(transform.position.y, targetY, ref verticalVelocity, smoothTime);
transform.position = new Vector3 (transform.position.x, y, transform.position.z);
}
This example will smoothly change the y coordinate to 5 over the course of 1 second (you can change the smoothTime constant for a different time).
Based in your own code the easiest way for you to work it out could be something like this
//this sets the X position
transform.position += transform.forward * Time.deltaTime * 10f;
//if the button is pressed then modify Y
if (Input.GetKey (KeyCode.UpArrow))
transform.position += new Vector3 (0, 5f * Time.deltaTime * y_speed,0);
y_speed could be a public float y_speed = 1.0f in your script so you could modify it from the inspector to get the effect you want to achieve.
Hope it helps!
Assuming your spaceship is a rigidbody, you should take a look at Rigidbody.AddForce
https://docs.unity3d.com/ScriptReference/Rigidbody.AddForce.html
By working with forces, you can get a smooth movement in all directions very easily, and tweak it within the Rigidbody's parameters (like mass) without fiddling in the script again. It's part of the Unity physics model.
If you only want to move in y-direction, input a vector like (0,1,0) but you can also input the Transform.forward vector of your spaceship's Gameobject. That way, it will always move the direction it is facing in.
I'm struggling with false Gravity in a Cylinder or Capsule. Basically I thought I could take the same Code as for spherical gravity, which does not work. So I changed some lines to get a better result.
[SerializeField] float gravity = 10;
public void Attract ( Transform target )
{
Vector3 gravityUp = (target.position - new Vector3(transform.position.x, transform.position.y,target.position.z)).normalized;
Vector3 bodyDown = -target.up;
Rigidbody rb = target.GetComponent<Rigidbody>();
rb.AddForce(gravityUp * gravity);
Quaternion targetRotation = Quaternion.FromToRotation(bodyDown, gravityUp) * target.rotation;
targetRotation.x = 0;
target.rotation = Quaternion.Slerp(target.rotation, targetRotation, 30.0f * Time.deltaTime);
}
This worked OK on the first try. But the Player(target) can't rotate one the Y-Axis. Does anyone have any ideas?
OK, I tried the following.
Quaternion targetRotation = Quaternion.FromToRotation(bodyDown, gravityUp) * target.rotation;
targetRotation.x = 0;
target.rotation = Quaternion.Slerp(target.rotation, targetRotation, 30.0f * Time.deltaTime);
Now I use the Surface normal to rotate the Player.
if (Physics.Raycast(attractedBody.transform.position + attractedBody.transform.forward, -attractedBody.transform.up, out hit, distance))
{
surfaceNorm = hit.normal;
}
But without Rigidbody Contrains the Player starts rotating without any Input. So I have to use:
rb.constraints = RigidbodyConstraints.FreezeRotation;
This works.
Here is my code for moving a 2D top-down object using the built in virtual joystick:
void Update ()
{
Vector2 moveVec = new Vector2(CrossPlatformInputManager.GetAxis("Horizontal"),
CrossPlatformInputManager.GetAxis("Vertical"));
Vector3 lookVec = new Vector3(CrossPlatformInputManager.GetAxis("Horizontal"),
CrossPlatformInputManager.GetAxis("Vertical"), 4000);
transform.rotation = Quaternion.LookRotation(lookVec, Vector3.back);
transform.Translate(moveVec * Time.deltaTime * speed);
}
Without the rotation code, the movement was perfect, after adding the rotation code the movement got all messed up, if the direction is down, it moves up.
But the rotation is exactly how it should.
Simply change the transform.Translate(moveVec * Time.deltaTime * speed); line to transform.Translate(moveVec * Time.deltaTime * speed, Space.World); : by default, the translation is made relatively to the transform own space (Space.Self).