Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Idle when encountering a wall

Discussion in '2D' started by Deleted User, Jan 17, 2020.

Thread Status:
Not open for further replies.
  1. Deleted User

    Deleted User

    Guest

    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.


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class playermovement : MonoBehaviour
    6. {
    7.  
    8.  
    9.     public float moveSpeed = 5f;
    10.     public Rigidbody2D rb;
    11.     public Animator animator;
    12.  
    13.     Vector2 movement;
    14.  
    15.     // Update is called once per frame
    16.     void Update()
    17.     {
    18.         // Input
    19.         movement.y = Input.GetAxisRaw("Vertical");
    20.         movement.x = Input.GetAxisRaw("Horizontal");
    21.      
    22.         animator.SetFloat("vertical", movement.y);
    23.         animator.SetFloat("horizontal", movement.x);
    24.         animator.SetFloat("speed", movement.sqrMagnitude);
    25.     }
    26.  
    27.     void FixedUpdate()
    28.     {
    29.         // Move
    30.         rb.MovePosition(rb.position + movement * moveSpeed * Time.fixedDeltaTime);
    31.  
    32.        if (moveSpeed > 0)
    33.    
    34.         {
    35.             animator.SetFloat("speed", Mathf.Abs(1));
    36.         }
    37.     }
    38. }
    39.  
    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.

    Any help would be greatly appreciated
     
    Last edited by a moderator: Jan 20, 2020
  2. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    Hi @mageplush

    You don't have any logic there...

    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.
     
  3. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    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:
    Code (CSharp):
    1. float speedValue = Mathf.Clamp01(rb.velocity.sqrMagnitude / maxSpeed);
    2. animator.SetFloat("speed", speedValue);
    Edit:

    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);
     
  4. Deleted User

    Deleted User

    Guest

    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!
     
  5. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    @mageplush

    ...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.
     
  6. falsepehr

    falsepehr

    Joined:
    Dec 22, 2022
    Posts:
    1
    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.
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,971
    Probably not actually.

    Instead of necro-posting a thread by a long-deleted user, start your OWN post... it's FREE!

    When you post remember that none of us can read your mind. You must communicate clearly. Here's how:

    How to report your problem productively in the Unity3D forums:

    http://plbm.com/?p=220

    This is the bare minimum of information to report:

    - what you want
    - what you tried
    - what you expected to happen
    - what actually happened, especially any errors you see
    - links to documentation you used to cross-check your work (CRITICAL!!!)

    If you post a code snippet, ALWAYS USE CODE TAGS:

    How to use code tags: https://forum.unity.com/threads/using-code-tags-properly.143875/
     
    WildWolvesGames and MelvMay like this.
Thread Status:
Not open for further replies.