Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question [2D Top Down] How to make my idle face the last direction of my animation ?

Discussion in 'Scripting' started by misterunsafe, Feb 17, 2021.

  1. misterunsafe

    misterunsafe

    Joined:
    Feb 15, 2021
    Posts:
    10



    Hello guys ! Same project, new problem :cool:

    Every time I stop moving, my character faces north . How can I manage this situation ? I was thinking it will be fixed easily this morning but sun is gone and here I am.
    Is there anyway to rotate my idle so it face my last direction ?

    I found something interesting about passing a enum to the animator with cardinal direction but either the script is too old either I'm too noob to make it work.

    Do I need to focus on my script ? Or can I fix it in my animator ? Big noob here don't hesitate to explain obvious things !

    Here's a GIF of the situation:


    Here's the functions I call in my Update() :
    Code (CSharp):
    1.     private void ProcessInputs() {
    2.         if (useController) {
    3.         movement = new Vector3(Input.GetAxis("MoveHorizontal"), Input.GetAxis("MoveVertical"), 0.0f);
    4.         aim = new Vector3(Input.GetAxis("AimHorizontal"), Input.GetAxis("AimVertical"), 0.0f);
    5.         aim.Normalize();
    6.         isAiming = Input.GetButton("Fire");
    7.         endOfAiming = Input.GetButtonUp("Fire");
    8.     } else {
    9.         movement = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0.0f);
    10.         Vector3 mouseMouvement = new Vector3(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"), 0.0f);
    11.         aim = aim + mouseMouvement;
    12.         if (aim.magnitude > 1.0f) {
    13.             aim.Normalize();
    14.         }
    15.         isAiming = Input.GetButton("Fire1");
    16.         endOfAiming = Input.GetButtonUp("Fire1");
    17.     }
    18.  
    19.     if (movement.magnitude > 1.0f) {
    20.         movement.Normalize();
    21.     }
    22. }
    23.  
    24.  
    25.     private void Move() {
    26.         transform.position = transform.position + movement * Time.deltaTime;
    27.     }
    28.  
    29.  
    30.     private void Animate() {
    31.         animator.SetFloat("Horizontal", movement.x);
    32.         animator.SetFloat("Vertical", movement.y);
    33.         animator.SetFloat("Magnitude", movement.sqrMagnitude);
    34.     }
    35.  
    36.  
    37.     private void AimAndShoot() {
    38.         Vector2 shootingDirection = new Vector2(aim.x, aim.y);
    39.  
    40.         if (aim.magnitude > 0.0f) {
    41.             crossHair.transform.position = aim * 0.8f + thePlayer.transform.position;
    42.             crossHair.transform.rotation = Quaternion.identity;
    43.             crossHair.SetActive(true);
    44.  
    45.             shootingDirection.Normalize();
    46.             if(endOfAiming) {
    47.                 GameObject ammo = Instantiate(ammoPrefab, transform.position, Quaternion.identity);
    48.                 ammo.GetComponent<Rigidbody2D>().velocity = shootingDirection * 3.0f;
    49.                 ammo.transform.Rotate(0.0f, 0.0f, Mathf.Atan2(shootingDirection.y, shootingDirection.x) * Mathf.Rad2Deg);
    50.                 Destroy(ammo, 2.0f);
    51.             }
    52.         } else {
    53.             crossHair.SetActive(false);
    54.          }
    55.     }
    have a nice experience with playing god.
     
    Last edited: Feb 17, 2021
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    I'm not sure what this means.

    As to your issue, the problem is you are rotating the player always, whether he is moving or not.

    Instead what you want to do is ONLY rotate the player when there is at least some minimum amount of control deflection, such as greater than 0.1f magnitude.

    I'm not 100% if line 49 above is your rotate (maybe?) but if it is, then only do it when the magnitude of your motion is above 0.1f.

    To see it in another context, doing precisely what I suggest above, you can look at my DemoRotatedControls scene in my proximity_buttons game. This is the source file:

    https://github.com/kurtdekker/proxi...edControls/RotatedControlsPlayerController.cs

    Go to line 141 for the "is magnitude greater than 0.1?" check.
     
  3. misterunsafe

    misterunsafe

    Joined:
    Feb 15, 2021
    Posts:
    10
    The function AimAndShoot() who start at line 37 is only for my crosshair and tracking the path of my bullets. Sorry I shouldn't c/p that, it's confusing.

    All the rotation animation happen in my blend tree, I rotate the same sprite on the z axis. And I get back to idle when I stop running.

    For my movement I tried to implant your code likes this, but i can't make it work:
    Code (CSharp):
    1.     private void Move() {
    2.         transform.position = transform.position + movement * Time.deltaTime;
    3.  
    4.         if (movement.magnitude >= 0.1f) {
    5.             float controlsFacing = Mathf.Atan2(movement.x, movement.z) * Mathf.Rad2Deg;
    6.             float myCurrentHeading = transform.eulerAngles.y;
    7.             myCurrentHeading = Mathf.MoveTowardsAngle(myCurrentHeading, controlsFacing, TurnToFaceRate * Time.deltaTime);
    8.             transform.rotation = Quaternion.Euler(0, myCurrentHeading, 0);
    9.         }
    10.     }

    I copy you my entire script, maybe there is information I don't give you. I understand what you want me to do but I don't get where in my script I need to interact !
    In my ProcessInputs() ? or Animate()? Or do I need to create an other one ? SORRY AGAIN king, I'm really trying, big noob here.

    EDIT : Is my problem coming from the fact there is only one idle who is facing north in my animation blend at my idle section ? Do I need to make an idle for every direction ? Or is there a way to rotate one idle to every direction I was facing ?

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PlayerController : MonoBehaviour
    6. {
    7.  
    8.     public int playerId = 0;
    9.     public bool useController;
    10.  
    11.     public Animator animator;
    12.     public GameObject crossHair;
    13.     public GameObject thePlayer;
    14.  
    15.     public GameObject ammoPrefab;
    16.  
    17.     Vector3 movement;
    18.     Vector3 aim;
    19.     bool isAiming;
    20.     bool endOfAiming;
    21.  
    22.     const float TurnToFaceRate = 500;
    23.  
    24.  
    25.     void Awake() {
    26.         Cursor.lockState = CursorLockMode.Locked;
    27.         Cursor.visible = false;
    28.     }
    29.  
    30.     void Update() {
    31.         ProcessInputs();
    32.         AimAndShoot();
    33.         Animate();
    34.         Move();
    35.     }
    36.  
    37.  
    38.     private void ProcessInputs() {
    39.         if (useController) {
    40.         movement = new Vector3(Input.GetAxis("MoveHorizontal"), Input.GetAxis("MoveVertical"), 0.0f);
    41.         aim = new Vector3(Input.GetAxis("AimHorizontal"), Input.GetAxis("AimVertical"), 0.0f);
    42.         aim.Normalize();
    43.         isAiming = Input.GetButton("Fire");
    44.         endOfAiming = Input.GetButtonUp("Fire");
    45.     } else {
    46.         movement = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0.0f);
    47.         Vector3 mouseMouvement = new Vector3(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"), 0.0f);
    48.         aim = aim + mouseMouvement;
    49.         if (aim.magnitude > 1.0f) {
    50.             aim.Normalize();
    51.         }
    52.         isAiming = Input.GetButton("Fire1");
    53.         endOfAiming = Input.GetButtonUp("Fire1");
    54.     }
    55.  
    56.     if (movement.magnitude > 1.0f) {
    57.         movement.Normalize();
    58.     }
    59. }
    60.  
    61.  
    62.     private void Move() {
    63.         transform.position = transform.position + movement * Time.deltaTime;
    64.  
    65.         if (movement.magnitude >= 0.1f) {
    66.             float controlsFacing = Mathf.Atan2(movement.x, movement.z) * Mathf.Rad2Deg;
    67.             float myCurrentHeading = transform.eulerAngles.y;
    68.             myCurrentHeading = Mathf.MoveTowardsAngle(myCurrentHeading, controlsFacing, TurnToFaceRate * Time.deltaTime);
    69.             transform.rotation = Quaternion.Euler(0, myCurrentHeading, 0);
    70.         }
    71.     }
    72.  
    73.  
    74.     private void Animate() {
    75.         animator.SetFloat("Horizontal", movement.x);
    76.         animator.SetFloat("Vertical", movement.y);
    77.         animator.SetFloat("Magnitude", movement.sqrMagnitude);
    78.     }
    79.  
    80.  
    81.     private void AimAndShoot() {
    82.         Vector2 shootingDirection = new Vector2(aim.x, aim.y);
    83.  
    84.         if (aim.magnitude > 0.0f) {
    85.             crossHair.transform.position = aim * 0.8f + thePlayer.transform.position;
    86.             crossHair.transform.rotation = Quaternion.identity;
    87.             crossHair.SetActive(true);
    88.  
    89.             shootingDirection.Normalize();
    90.             if(endOfAiming) {
    91.                 GameObject ammo = Instantiate(ammoPrefab, transform.position, Quaternion.identity);
    92.                 ammo.GetComponent<Rigidbody2D>().velocity = shootingDirection * 3.0f;
    93.                 ammo.transform.Rotate(0.0f, 0.0f, Mathf.Atan2(shootingDirection.y, shootingDirection.x) * Mathf.Rad2Deg);
    94.                 Destroy(ammo, 2.0f);
    95.             }
    96.         } else {
    97.             crossHair.SetActive(false);
    98.          }
    99.     }
    100. }
     
    Last edited: Feb 17, 2021
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    Hm, not 100% sure... I've never used animation for turning. I usually don't animate the root object, which lets me control it with code and face it whichever way I want, then things below it are animated.

    One possibility is to look at your
    Animate()
    method and only set the "Horizontal" and "Vertical" properties if
    movement.magnitude > 0.1f


    I would continue unconditionally setting the "Magnitude" property as you are now.
     
  5. misterunsafe

    misterunsafe

    Joined:
    Feb 15, 2021
    Posts:
    10
    Sorry Kurt i have done what you said but still not working. I'm still looking since my post but not finding for the moment. Is there a way to use this https://docs.unity3d.com/ScriptReference/Animator-deltaRotation.html or something like https://docs.unity3d.com/ScriptReference/Animator-bodyRotation.html or even https://docs.unity3d.com/ScriptReference/Animator.SetLookAtPosition.html or why not https://docs.unity3d.com/ScriptReference/Animator-targetRotation.html ?

    I'm looking in doc in animator section but since I'm new I think I overdose a bit with the quantity of info today.
     
    Last edited: Feb 18, 2021
  6. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    687