I have a simple character and want to move it in Environment with touch. in each moment if player move his hand character compare the previous and current position of the hand and calculate a vector for move direction.
writing this two class doesn't solved my problem.
I write this two class for character moving.
touch class
void Update()
{
if (Input.touchCount == 1)
{
PlayerTouch = Input.GetTouch(0);
if (PlayerTouch.phase == TouchPhase.Moved)
{
MoveDirection.x = TouchDeltaPosition.x;
MoveDirection.z = TouchDeltaPosition.y;
}
characterMove.Move(MoveDirection * 1000);
}
}
above class call the move function in CharacterMove class just like below
public void Move(Vector3 moveDirecion)
{
transform.rotation = Quaternion.Lerp(transform.rotation,
Quaternion.LookRotation(moveDirecion), Time.deltaTime * Speed);
transform.position += transform.forward*Time.deltaTime * Speed2;
}
In my Opinion you must use Transform.translate for your movement. after that with rotatetoward you can smoothly turn toward destination direction. why you comment those of this line in your movement script?
Related
Im trying to code so that my Character dashes to the right when pressing the Left mouse button, but instead of dashing it just starts slowly glieding or lets say floating.
This is the code i´ve used;
if (Input.GetMouseButton(0))
{
rb.velocity = Vector2.right * DashSpeed;
}
Im not sure but a other part of my code might be the reason for this problem but if so i would like to know how i could solve it. Thats the part im talking about
rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);
thats the code im using for movement.
void Start()
{
cam = Camera.main;
rb = GetComponent<Rigidbody2D>();
}
private void Update()
{
horizontal = Input.GetAxisRaw("Horizontal");
animator.SetFloat("Horizontal", Input.GetAxis("Horizontal"));
if (Input.GetKeyDown(KeyCode.Space) && isGrounded == true)
{
float jumpVelocity = 7f;
rb.velocity = Vector2.up * jumpVelocity;
jumpsound.Play();
}
Vector3 worldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
if (Input.GetKey(KeyCode.RightAlt))
{
Dashing();
}
}
void FixedUpdate()
{
isGrounded = Physics2D.OverlapCircle(groundCheck.position, CheckRadius, whatisGround);
moveInput = Input.GetAxisRaw("Horizontal");
rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);
if (Input.GetKeyDown(KeyCode.Escape))
{
SceneManager.LoadScene("Main menu");
}
}
void Dashing()
{
rb.AddForce(Vector2.right * DashSpeed, ForceMode2D.Impulse);
}
The issue with your current code is you are directly changing velocity in a few places. Some basic physics, the integral of position vs. time graph is velocity, and the integral of velocity is acceleration vs. time. To get a more realistic movement, it is better to apply a Force to objects. When doing this, the physics engine Unity uses can add a new force at a given time, then using acceleration can accelerate the object in that direction over time, then can change the velocity over time which will result in the position changing over time.
The example code you posted, you are directly setting velocity in a few places.
rb.velocity = Vector2.up * jumpVelocity; (Jump)
rb.velocity = new Vector2(moveInput * speed, rb.velocity.y); (Movement)
rb.velocity = Vector2.right * DashSpeed; (Dash)
When directly setting these values, the new values overwrite the old ones. As your movement code is not in any sort of if conditional it will continually write to the velocity causing the dash to never change anything regardless if you use add-force or change velocity directly.
I would consider making both your jump and dash use AddForce, and if you like the feel of your movement by applying velocity directly, then add the velocity do not set it.
Your previous line rb.velocity = new Vector2(moveInput * speed, rb.velocity.y); would then become rb.AddForce(new Vector2(moveInput * speed, 0), ForceMode2D.Impulse);. Similarly you can update your jump and dash to match this. Let me know if you get this working or have more questions.
It could be a problem with your animation. Link to a thread on unity answers:
https://answers.unity.com/questions/674516/rigidbody-character-problems-constant-floating-jum.html
You should go over to the animation place and hit bake into pose.
You should use the Rigidbody2D.AddForce(Vector2, ForceMode2D). What this does is moving the GameObject in the direction of the Vector2, with the force mode of ForceMode2D. What is different about this from just translating it, is that it interacts with physics and improves the quality of your game. Here is a link, and the script:
https://docs.unity3d.com/ScriptReference/Rigidbody2D.AddForce.html
Rigidbody2D rb;
float dashSpeed;
void Update()
{
if (Input.GetMouseButton(0))
{
rb.AddForce(Vector2.right * dashSpeed);
}
}
And if the other part of the code you were talking about, if that is glitching, then do the same trick.
How do I best describe the direction vector to move an object left (or right/up/down) from its current position, factoring the current view perspective into the equation?
For example, imagine the box depicted in the following picture, placed at origin (0,0,0). If I wanted to move the point on top of the box to the left, I'd have to make a step in (-1,0,0) direction (i.e. currentPos = currentPos + Vector3.left).
If I looked at the box from behind, I'd have to make a step in (1,0,0) direction to continue moving in the same direction.
i.e. When I'm looking at this box, placed at origin, and press an input button LEFT, I need for the point to move left and continue moving in that direction for as long as I keep pressing the button. It ultimately wraps around the surface, i.e. if I keep pressing just LEFT the point will wrap around the cube and re-appear so to speak.
To indefinitly trace a decal around a cube:
private Transform Cube;
private Transform Decal;
void Update() {
Vector3 moveLocal = Vector3.zero;
// Set moveLocal from User Input
moveLocal += Vector3.left * Input.GetAxis("Left"); // etc
if (moveLocal.sqrMagnitude > 0) {
var decalDirection = (Decal.position - Cube.position).normalized;
var angle = Vector3.SignedAngle(Cube.forward, decalDirection, Cube.up);
// Align decal to correct cube face
if (angle < -135 || angle > 135) { // Rear face
Decal.forward = -Cube.forward;
}
else if (angle < -45) { // Left face
Decal.forward = -Cube.right;
}
else if (angle > 45) { // Right face
Decal.forward = Cube.right;
}
else { // Front Face
Decal.forward = Cube.forward;
}
// Now move decal in it's local space:
Decal.Translate(moveLocal, Space.Self);
}
}
Admittedly, this only rotates Left/Right, but I hope you get the idea =)
As i mentioned you in my opinion you can achieve this with surface normals. I cracked some code which is not an exact solution because i used collision normals and on corners that gives different results. In any case i share it so that it gives you the idea. You can go left and right with this code relative to camera(even though it does not use anything related to camera) because it depends on surface normals.
private Vector3 normal;
private Vector3 contact;
private Vector3 direction;
private GameObject obj;
void Start () {
}
void Update () {
if (obj == null)
return;
if( Input.GetKey(KeyCode.LeftArrow))
{
obj.transform.position += direction * Time.deltaTime;
}
if (Input.GetKey(KeyCode.RightArrow))
{
obj.transform.position -= direction * Time.deltaTime;
}
}
void OnCollisionEnter(Collision collision)
{
Debug.Log("Collided");
Debug.Log("If works");
obj = collision.gameObject;
normal = collision.contacts[0].normal;
contact = collision.contacts[0].point;
//Cross product of normal and up gives direction Right.
//This up can be cube's up as well in cases it is tilted
direction = (-Vector3.Cross(Vector3.up, normal));
}
You can also see how it works from images below:
I use rigidbody.MovePosition to move around my character , and have a camera following it. The problem is when i switch directions suddenly the player will teleport a bit instead of smoothly moving in the opposite direction of motion. The scripts for the player and Camera are set to FixedUpdate , if I try moving camera to a LateUpdate then the whole thing jitters a lot.
Player Script :
private void Start()
{
m_Rb = GetComponent<Rigidbody>();
m_InputAxisName = "Vertical" + m_playerNumber;
m_StrafeAxisName = "Horizontal" + m_playerNumber;
}
private void FixedUpdate()
{
m_InputAxisValue = Input.GetAxis(m_InputAxisName);
m_StrafeAxisValue = Input.GetAxis(m_StrafeAxisName);
//Movement
Vector3 movement = (transform.forward * m_InputAxisValue * m_Speed * Time.deltaTime) + (transform.right * m_StrafeAxisValue * m_Speed * Time.deltaTime);
m_Rb.MovePosition(m_Rb.position + movement);
}
Camera Script
void FixedUpdate () {
m_NewPos = m_player.transform.position + m_offset;
if (m_Rotate)
{
Quaternion newRot = Quaternion.AngleAxis(Input.GetAxis("Mouse X") * m_rotSpeed, Vector3.up);
m_offset = newRot * m_offset;
}
transform.position = Vector3.SmoothDamp(transform.position, m_NewPos, ref m_MoveSpeed, m_DampTime); ;
if (m_Rotate)
transform.LookAt(m_player);
}
the problem is that your motion logic is implemented within FixedUpdate but you take the time.deltaTime. You have to use the fixedDeltaTime version.
Also do not try to get the Input within the FixedUpdate that can also cause jitter and stutter/jumping of objects.
Instead get the Input from Update and use variables to pass it inside the FixedUpdate.
A last one, look at your RigidBody for the Interpolation/Extrapolation depending on your Scene Setup and Camera this could also help.
I finally figured out what was wrong with it, something about the rotation of the camera in the fixed update. I moved it to update and it works fine now
I have following simple scene: scaled box at (0, 0, 0) for floor and 1 size box at (0, 2, 0). I try to do simple gravity and use following code:
private float gravity = 1.0f;
private Vector3 moveVector;
void Update()
{
if (characterController.IsGrounded)
{
Debug.Log("is grounded");
verticalVelocity = 0;
}
else
{
Debug.Log("not grounded");
verticalVelocity -= gravity;
}
Debug.Log("vertical velocity:" + verticalVelocity);
moveVector.x = 0;
moveVector.y = verticalVelocity;
moveVector.z = 0;
characterController.Move(moveVector * Time.deltaTime);
}
I see in log that event when object is on the floor I have grounded/not grounded messages. Visually object is on the floor and not oscillating.
Why I don't have constant "is grounded" when object is on the floor?
Maybe it is how CharacterController works but I can't find anything about it in documentation.
You have to set Character Controller Min Move Distance to '0' (zero) or else you will always get this behavior, it is trying to limit how many times it checks if it's grounded, but at the end of the day gamers don't care, they will mash the jump button and call it buggy
Had the same issue
Just had some gravity when the character controller is grounded
Replace verticalVelocity = 0;
By
verticalVelocity = -gravity * Time.deltaTime;
Setting "Min Move Distance" to 0 in the Character Controller Inspector solved a very similar problem for me.
Strubble is right. You have to add some small gravity even if character is grounded.
if (characterController.IsGrounded)
{
// Press the character down to the floor to avoid jitter "true-false"
// of the isGrounded property.
// To do it, add some small gravity (or velocity in your terms).
verticalVelocity = -gravity * 0.1f;
}
just use a Raycast with Vector3.down because I've tired of fixing it and it's really unreliable to use even while prototyping.
I make a character move on the surface of a circle. I let the camera move and rotate follow character. But the camera move and rotate very jerky. If I increase the value of the third parameter, the shock increases. and to reduce the value of the third parameter, the camera does not rotate to keep up the character. Help me fix it
My Code Camera Follow Player
public class CameraFollow : MonoBehaviour
{
public Transform player;
GameController gc;
public float speed = 2;
Vector3 pos = new Vector3 (0, 0, -10);
// Use this for initialization
void Start ()
{
gc = FindObjectOfType (typeof(GameController)) as GameController;
}
void FixedUpdate ()
{
if (gc.gameState == GameController.GameState.playing || gc.gameState == GameController.GameState.changeWave) {
transform.position = player.position + pos;
transform.rotation = Quaternion.Slerp (transform.rotation,
player.transform.rotation,
speed * Time.deltaTime);
}
}
}
Setting the position of a transform inside of FixedUpdate is a red flag for sure, especially when you're reporting that it's "jerky". Fixed update happens at an irregular interval compared to the frames displayed. This is because Physics needs to update using a fixed time step. The reason why this is the case is out of scope for this question.
Long story short, try changing FixedUpdate to Update and that should fix things looking "jerky".
Let me know if this doesn't work and I'll look for other possible causes.
If you are using a Rigidbody2D to move the character, make sure to set its Interpolate property to 'Interpolate'. This should fix it.