I recently set up a movement script / animation tree for some top-down game tests I want to work on. Everything is working as intended however the player won’t stop the walking animation even when faced with a solid wall.
In my animation I have blend-trees that tell the game to switch between walk and idle, determined by a animation float “speed” but I can’t figure out how to get that speed to 0 when the wall is hit.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playermovement : MonoBehaviour
{
public float moveSpeed = 5f;
public Rigidbody2D rb;
public Animator animator;
Vector2 movement;
// Update is called once per frame
void Update()
{
// Input
movement.y = Input.GetAxisRaw("Vertical");
movement.x = Input.GetAxisRaw("Horizontal");
animator.SetFloat("vertical", movement.y);
animator.SetFloat("horizontal", movement.x);
animator.SetFloat("speed", movement.sqrMagnitude);
}
void FixedUpdate()
{
// Move
rb.MovePosition(rb.position + movement * moveSpeed * Time.fixedDeltaTime);
if (moveSpeed > 0)
{
animator.SetFloat("speed", Mathf.Abs(1));
}
}
}
The if statement at the bottom was the furthest I got, but I believe that “moveSpeed” is always at the number it’s initially set to and is different from a velocity, so I have a feeling velocity is part of the problem but so far I’ve found nothing.
Did you write any pseudo code before writing this?
Like:
Start moving/walking towards a defined direction.
Each frame, check if there is a wall (collider) in move direction, a short distance ahead of moving object.
If there isn’t continue moving to defined direction.
If there is, don’t move and set velocity to zero.
There are several ways to check if you are already colliding with another collider or if you are going to collide, just google about unity check collision to another object.
Alternatively, if you really want to drive the animation purely with physics, you’ll need to actually pass a value based on velocity instead of your inputs. Movement inputs won’t be 0 as long as you’re holding them down. Your character’s velocity however will be what you expect when hitting a wall.
Make your blend tree expect a value from 0 to 1, 0 being stopped, 1 being max speed. Then you can define a float variable for max speed, and pass in the fraction:
I just realized you’re using MovePosition, which moves in instant incremental changes, so perhaps your velocity won’t be correct. To avoid having to track your own velocity over frames, maybe using forces is the way to go if you want to pursue this approach. rb.AddForce(movement * moveSpeed * Time.deltaTime);
Thank you so much!! Those suggestions worked perfectly. It had some tinkering needed due to the rigidbody sliding around but increasing the drag worked just fine for that. Thank you!
…you should anyway yourself detect if you collided, and then stop the movement. Using drag sounds like a workaround to fix not stopping when colliding.
Then you can stop the animation easily, and also you don’t get any jitter against obstacles.
I have the same problem. my game’s floor and walls are made with tile maps and they are on the same layer and game object. Setting a collider wont work because it would stop the walk animation when it collides with the ground.