I know this question is already asked a few times, but didn't find it in the way of my code.
In the movement of my playerObject I consider the direction the Camera is looking to atm.
What I want to do is to slow down the speed of the movement, but it doesn't work with the walkSpeed I use.
I also want to smooth the movement (start and end).
public void UpdateMovement()
{
Vector2 targetDir = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")); //In targetDir the direction the Player wants to move to is saved -> player presses W means forward
// targetDir = Vector2.ClampMagnitude(targetDir, 1);
Vector3 camForward = cam.forward; //camForward saves the direction, the cam is looking actually
Vector3 camRight = cam.right; //camRight saves the actual right side of the cam
camForward.y = 0.0f; //y=0 because we don't want to fly or go into the ground
camRight.y = 0.0f;
camForward = camForward.normalized;
camRight = camRight.normalized;
transform.position += (camForward * targetDir.y + camRight * targetDir.x) * walkSpeed * Time.deltaTime;
I'm not sure exactly about what the context of what you're trying to do here is, but I think you're looking for Vector2.Lerp().
The way you use it is to first calculate a target position as a Vector. So,
Vector2 target = new Vector2(targetX, targetY)
I'll let you figure out what targetX and targetY are, based on wherever you're trying to move the thing you're moving.
Then you would come up with the speed, which is what you're pretty much already doing. Like so:
float speed = walkSpeed * Time.deltatime;
Finally, instead of setting the position directly, you use the Lerp function instead.
transform.position = Vector2.Lerp(transform.position, target, speed);
I didn't test any of this, and just wrote it on the fly, but I'm pretty sure this is what you're looking for.
I wrote a script you can try to create a cube, I'm sorry because I'm also a unity3d newbie, but I hope it helps you
private Transform player;
Vector3 toposition;//interpolation
void Start(){
player = this.transform;
toposition = new Vector3(0,5,0);
}
// Start is called before the first frame update
void Update(){
if(Input.GetKey(KeyCode.W)){
UpdateMovement();
}
}
public void UpdateMovement(){
player.transform.position = Vector3.Lerp(transform.position, toposition, Time.deltaTime * 5f);
}
Related
Im scratching my head over this one, really cant figure it out.
Im trying to implement the player movement from this example:
https://www.youtube.com/watch?v=LNidsMesxSE
Starts at minute 4:25 and ends at minute 5:20
This script tries translating all that to unity.So I started all the way over from scratch and just want to make a simple movement script.
You can plug this into any Unity version, throw the script onto and object with a CharacterController component, add a child object with a mesh that will tilt, the main object will rotate around its Y axis and move.
I do recommend using a simple T pose character or atleast a long capsule so you can better see what is happening than when you would be using a cube to test this.
The weird glitches im having is that the object randomly spasms out even though im always only adding extremely small rotations and movements every frame. And 95% of the time it doesnt happen, so I havent been able to pinpoint exactly what is causing this.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterMove : MonoBehaviour
{
public float speed = 200f;
public float rotationSpeed = 180f;
public float tiltFactor = 8f;
public bool normalizeVelocity = false;
CharacterController cc;
Vector3 velocity;
Transform armatureBody;
void Start()
{
cc = GetComponent<CharacterController>();
armatureBody = transform.GetChild(0);
}
void Update()
{
velocity = new Vector3(Input.GetAxis("Horizontal"), 0,
Input.GetAxis("Vertical"));
}
void FixedUpdate()
{
if ((velocity != Vector3.zero))
{
var ccVelocity = cc.velocity; // CharacterController velocity. This might be the problem, but without it I cannot rotate the object towards the actual forward velocity.
Quaternion toRotation;
toRotation = Quaternion.LookRotation(ccVelocity, Vector3.up);
transform.rotation = Quaternion.RotateTowards(transform.rotation, toRotation, rotationSpeed * Time.deltaTime);
if (Input.GetKey(KeyCode.S)) print("new toRotation: " + toRotation);
armatureBody.localEulerAngles = new Vector3(velocity.z * tiltFactor, 0, -velocity.x * tiltFactor); // Tilt Body towards velocity This causes the weirdest and most consistest twitching bugs when the tilt is backwards so the object is moving backwards, maybe because im using LookRotation to look backwards?
}
velocity = Quaternion.Euler(0, transform.eulerAngles.y, 0) * velocity; // forward is always forward
cc.SimpleMove(velocity * Time.deltaTime * speed);
}
}
This script does 4 things,
get the velocity from player input.
rotate the main Object(this script) towards the velocity
add tilt towards the velocity, to the child armatureBody, this is a t Pose character in my case.
move the main Object this script is on.
Any help would be appreciated.
I tried removing the vector3 != Zero check, I tried normalizing the vectors, and I tried using a different Quaternion rotation method, but all with the same faulty results.
Check in Update() if Input.forward > threshold if so rotate to velocity. Dont rotate to velocity when only going sideways or backwards, so we can now strafe sideways and walk backwards when standing still or run and rotate to our velocity with the AD keys when running.
void Update()
{
velocity = new Vector3(Input.GetAxis("Horizontal"), 0,
Input.GetAxis("Vertical"));
if (velocity.z > 0.2f)
{
forwardVelocityThreshold = true;
}
else forwardVelocityThreshold = false;
}
Then in our FixedUpdate() we check for that bool and apply the rotateToVelocity if true.
Adjust the following if statement:
if (ccVelocity != Vector3.zero && forwardVelocityThreshold)
{
toRotation = Quaternion.LookRotation(ccVelocity, Vector3.up);
transform.rotation = Quaternion.RotateTowards(transform.rotation, toRotation, rotationSpeed * Time.fixedDeltaTime);
}
Now it works as intended, I also changed the deltaTime to FixedDeltaTime as suggested by Voidsay in the comments, although I have heard conflicting things about this. Some say FixedUpdate always uses fixedDeltaTime even if you are using deltaTime, other say no, always use fixedDeltaTime in FixedUpdate.
This question already has answers here:
Rotate GameObject over time
(2 answers)
Closed last year.
hey I am quite new to coding and I'm trying to right a simple player movement script using rigidbody.
I have been able to make my player move and turn to face its movement direction I just cannot figure out how to make it do it smoothly . I have made a float for turnspeed/smoothing but cannot figure out how to implement it into my code. sorry if my codes messy or wrong I am very new to this and would love some constructive advice cheers .
my code :
public float smoothing = .1f;
public void Update()
{
movement = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical")).normalized;
private void FixedUpdate()
{
moveCharacter(movement);
private void moveCharacter(Vector3 direction)
{
// player look direction
Vector3 lookDirection = movement + gameObject.transform.position;
gameObject.transform.LookAt(lookDirection);
// movement
rigidBodyComponant.MovePosition(transform.position + (direction * speed * Time.deltaTime));
}
For smoothing out position changes I like to use Lerping. This for example, can be used to lerp the rotation.
Quaternion toRotation = Quaternion.FromToRotation(transform.forward, direction);
transform.rotation = Quaternion.Lerp(transform.rotation, toRotation, speed * Time.deltaTime);
You should put this in the FixedUpdate() for smooth results. You can decide the speed yourself by giving it a certain value.
I just started with unity and followed thair 2D UFO example project.
In an effort to extend it, I came up with a quirky way of contolling my Player.
It always moves in circular paths and once I click a button, the circle's direction changes and the imaginary circle center is tanslated as shown in the picture below. That allows you to move in a figure 8 or S shape pattern and is quite fun.
However, once I figured out how to do this motion, the player object did not have any collision detection anymore.
In the original example the whole movemet handling is done within FixedUpdate(). I, however, use Update() since the former does not seem to work at all with my code (i.e. no movement at all).
This is my code for the movement so far:
public class ControlledRotation : MonoBehaviour
{
public float radius = 3f;
public float speed = 3f;
private float timeCounter = 0;
private float direction = 1f;
private Vector3 offset;
private Rigidbody2D rb2d;
void Start()
{
offset = transform.position;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.RightArrow))
{
//change the offset from the circle center and the rotation direction on keypress
offset += new Vector3(Mathf.Cos(timeCounter), Mathf.Sin(timeCounter), 0) * radius * direction * 2;
direction *= -1;
}
timeCounter += Time.deltaTime * direction * speed;
transform.position = new Vector3(Mathf.Cos(timeCounter), Mathf.Sin(timeCounter)) * radius * direction + offset;
}
}
The Plyer object has a Rigidbody 2D and a Circle Collider 2D. The walles it should collide with have Box Collider 2D. Yet, the UFO can simply pass the walls.
I assume a probable cause in the fact that I simply change transform.position or since im using Update/FixedUpdate wrong.
If you happen to have any advice on how I can keep my chosen movement control mechanism and still be able to collide with objects, I'd highly appreciate it :)
Edit:
I feel I need to go with using the rigidbody and applying some force... but I haven't figured out how to reproduce this movement with forces and also forces seem to not be super crisp in response
When you need to move an object that has a Rigidbody, you need to move it using forces, you cannot do it with just transform.position, it ignores physics. that's why you cannot detect the collision.. I suggest you move it like that. I have some examples when I had to move a character that needed to interact with physics.
gameObject.GetComponent<Rigidbody>().velocity = Vector3.zero;
And this one is for moving it in certain directions:
//Keys for controlling the player (move and shoot) only when he's alive
if (Input.GetKey(KeyCode.UpArrow) && alive)
{
GetComponent<Rigidbody>().MovePosition(transform.position + Vector3.forward * Time.deltaTime * 4);
}
if (Input.GetKey(KeyCode.DownArrow) && alive)
{
GetComponent<Rigidbody>().MovePosition(transform.position + Vector3.back * Time.deltaTime * 4);
}
I hope it helps.. greetings :)
I have a character/rigidbody and 'she' can turn around. When I press Play in Unity, if I move forward/backward, that's fine, she moves forward/backward. It's a good start.
But then if I turn her left or right, then go forward/backward, she now moves sideways.
She is a rigidbody component set as a parent in the scene.
Surely it's not difficult to do, but I can't figure out how to set her rotation so that when she turns, she will move 'forward' when I press the button to move her forward! There are plenty of first-person-shooter games where you can turn and move 'forward' and the player goes in the correct direction.
My rotation script at the moment is this:
Vector3 EulerAngleVelocity;
public float rotateSpeed = 250.0f;
void Update() {
if (Input.GetKey(KeyCode.UpArrow) || Input.GetKey(KeyCode.DownArrow))
{
MoveVector = PoolInput();
Move();
}
if (Input.GetKey(KeyCode.RightArrow))
{
EulerAngleVelocity = new Vector3(0, rotateSpeed, 0);
Quaternion deltaRotation = Quaternion.Euler(EulerAngleVelocity * Time.deltaTime);
rigidbody.MoveRotation(rigidbody.rotation * deltaRotation);
}
}
private void Move()
{
rigidbody.AddForce((MoveVector * moveSpeed));
}
private Vector3 PoolInput()
{
Vector3 dir = Vector3.zero;
dir.x = joystick.Horizontal();
dir.z = joystick.Vertical();
if (dir.magnitude > 1)
dir.Normalize();
return dir;
}
You're moving your joystick and adding that direction in relation to the WORLD instead of in relation to your player. If you want to add force relative to the orientation of the RigidBody probably what you want to use is rigidBody.AddRelativeForce (documentation) instead of simply rigidBody.AddForce.
Your problem isn't your rotation code, it's your movement code. You're applying a motion in world-space, not local-space ('object'-space).
For example, if you're using Vector3.Forward, you will want to use transform.Forward instead.
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;
}