Search Unity

  1. If you have experience with import & exporting custom (.unitypackage) packages, please help complete a survey (open until May 15, 2024).
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice

How to get "real" speed / velocity of charactercontroller?

Discussion in 'Editor & General Support' started by Ricks, Dec 17, 2010.

  1. Ricks

    Ricks

    Joined:
    Jun 17, 2010
    Posts:
    650
    Is there a way to get the real speed of a moving object? If my object is stuck running against the wall I could determine it. Unfortunately "velocity.magnitude" doesn't print the values I'd wish...

    (ps: there was already once a thread in this forum, but couldn't find it via search)
     
  2. eteeski

    eteeski

    Joined:
    Feb 2, 2010
    Posts:
    476
    Maybe you could save the position of your object at the end of each frame in a vector3 variable, say "lastPosition". Then you just need to use Vector3.Distance(lastPosition, transform.position) / Time.deltaTime; That should give you the real speed in units per sec.
     
    Wolfdog likes this.
  3. Ricks

    Ricks

    Joined:
    Jun 17, 2010
    Posts:
    650
    Thanks, I'll give it a try if I don't succeed with the velocity (meanwhile I'm not sure anymore if I was correct saying that "magnitude" doesn't show the real speed, I must debug my code more cleanly...)
     
  4. Ricks

    Ricks

    Joined:
    Jun 17, 2010
    Posts:
    650
    I'm frustrated... I thought I had solved this problem 1 year ago, but obviously not...

    The Scripting Reference clearly says here I can get the velocity of the CharacterController.

    "This allows you to track how fast the character is actually walking for example when he is stuck at a wall this value will be the zero vector."

    Well obviously it doesn't work on my setup. I always get approximately 5 as the velocity.magnitude, even when the Character stops! Can someone please have a look and explain what I do wrong? I've also attached a small example scene, ready to go (the console output shows the velocity).
     

    Attached Files:

    Vickey_Soni likes this.
  5. Ricks

    Ricks

    Joined:
    Jun 17, 2010
    Posts:
    650
    EDIT: after some experiments I came to the conclusion that the built in function velocity.magnitude is unusable for that purpose, because it seems to react on colliders only (it works if you put an obstacle in its way, but it doesn't work if you stop the character manually). Therefore eteeski's suggestion is the solution. Thanks for that a second time. I pasted the code for the example file above as I reminder for myself and maybe it helps some other people too.

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class MovePlayer : MonoBehaviour {
    5.    
    6.     Transform target;
    7.     CharacterController c;
    8.     Vector3 modifiedTarget;
    9.    
    10.     private Vector3 current_pos;
    11.     private Vector3 last_pos;
    12.    
    13.     // Use this for initialization
    14.     void Start () {
    15.         c = GameObject.Find("Player").GetComponent<CharacterController>();
    16.         target = GameObject.Find("Target").transform;
    17.        
    18.         current_pos = transform.position;
    19.         last_pos = transform.position;
    20.     }
    21.    
    22.     // Update is called once per frame
    23.     void Update () {
    24.         if(Vector3.Distance(target.position,transform.position)>4)
    25.         {
    26.             modifiedTarget = target.position;
    27.             modifiedTarget.y = 1;
    28.            
    29.             Vector3 relativePos = modifiedTarget - transform.position;
    30.             Quaternion rotation = Quaternion.LookRotation(relativePos);
    31.             transform.rotation = rotation;
    32.            
    33.             Vector3 forward = transform.forward;
    34.             c.SimpleMove(forward * 5);
    35.         }
    36.        
    37.         // this is the important part
    38.         current_pos = transform.position;
    39.         float speed = (current_pos - last_pos).magnitude/Time.deltaTime;
    40.         print(speed);
    41.         last_pos = current_pos;
    42.     }
    43. }
     
    Last edited: Dec 30, 2011
  6. Nemox

    Nemox

    Joined:
    Feb 16, 2010
    Posts:
    396
    I think velocity.magnitude is returning 5 because you're using it after applying your movement. Your script moves the character controller at a certain speed, and velocity.magnitude picks up on the new speed. Use velocity.magnitude first and it should work.
     
  7. Ricks

    Ricks

    Joined:
    Jun 17, 2010
    Posts:
    650
    Unfortunately not. Even if it's the first line in the Update loop velocity.magnitude is still returning 5. I've filed a bug report meanwhile so UT can take a look at it and clear things up, for the function doesn't provide the behavior expected.
     
  8. Vickey_Soni

    Vickey_Soni

    Joined:
    Jun 9, 2022
    Posts:
    19
    Hey Ricks! I am here stuck in the same issue even In 2023. I'm making a game for android. My Enemy(with Rigidbody) is facing this issue, where it works Great in Unity's Editor. But, after Export it doesn't play animation correctly. Enemy starts to Hover in the air, it goes to idle animation. My player has the similar script with a rigidbody. but only Enemy faces this Issue in the Build Only.

    Here is the script.

    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class EnemyFollow : MonoBehaviour
    7. {
    8.     public float speeed;
    9.     public Transform target;
    10.     public float minDist;
    11.     private Vector3 velocity;
    12.     private bool isGrounded;
    13.     private float gravity = -30f;
    14.  
    15.     public Rigidbody rb;
    16.  
    17.     [SerializeField]
    18.     private float range;
    19.  
    20.     [SerializeField]
    21.     private Transform originalPosition;
    22.  
    23.     [SerializeField]
    24.     LayerMask Player;
    25.     private bool isInRange;
    26.  
    27.     [SerializeField]
    28.     public Animator anim;
    29.  
    30.     void Update()
    31.     {
    32.         isInRange = Physics.CheckSphere(
    33.             transform.position,
    34.             range,
    35.             Player,
    36.             QueryTriggerInteraction.Ignore
    37.         );
    38.  
    39.         if (isInRange)
    40.         {
    41.             EnemyMove();
    42.         }
    43.         else
    44.         {
    45.             if (transform.position != originalPosition.transform.position)
    46.             {
    47.                 anim.SetBool("toPosition", true);
    48.                 transform.position = Vector3.MoveTowards(
    49.                     transform.position,
    50.                     originalPosition.position,
    51.                     3 * Time.deltaTime
    52.                 );
    53.                 transform.rotation = Quaternion.Euler(0, 90, 0);
    54.             }
    55.             else if (transform.position == originalPosition.transform.position)
    56.             {
    57.                 anim.SetBool("toPosition", false);
    58.                 transform.rotation = Quaternion.Euler(0, -90, 0);
    59.             }
    60.         }
    61.     }
    62.  
    63.     void EnemyMove()
    64.     {
    65.         if (target.position.x > transform.position.x)
    66.         {
    67.             transform.rotation = Quaternion.Euler(0, 90, 0);
    68.         }
    69.         else
    70.         {
    71.             transform.rotation = Quaternion.Euler(0, -90, 0);
    72.         }
    73.         if (Vector3.Distance(transform.position, target.position) > minDist)
    74.         {
    75.             anim.SetTrigger("chase");
    76.             transform.position = Vector3.MoveTowards(
    77.                 transform.position,
    78.                 target.position,
    79.                 speeed * Time.deltaTime
    80.             );
    81.         }
    82.         else
    83.         {
    84.             anim.ResetTrigger("chase");
    85.             StartCoroutine(AttackIndexs());
    86.         }
    87.     }
    88.  
    89.     IEnumerator AttackIndexs()
    90.     {
    91.         anim.SetTrigger("attack");
    92.         anim.SetInteger("attack_Index", Random.Range(0, 7));
    93.         yield return new WaitForSeconds(0.5f);
    94.     }
    95. }
    96.  
    97.  
    I tried searching a lot forums, Even one of your old one which had issues with velocity.magnitude. I could not figure it out. Any help is appriciated.
     
  9. Royy212

    Royy212

    Joined:
    Aug 1, 2016
    Posts:
    33
    Unity 2023.3.25.f1 LTS, I've got the same issue, works perfectly in the editor but glitches on my Android device.

    EDIT: So after @Kurt-Dekker gave me tips on how to post on this forum.

    I was planning to create a bug-report.
    I went to test some more stuff and this is what I found!

    In the editor I the velocity square magnitude of my character controller while moving was around 5.28f and always 0f while not moving.

    On my Android device this value was the same while moving, but after I stopped moving the value was always the same as when I was actually moving.
    I debugged a lot but couldn't find the issue till now, took me 2 days to find this out...

    I was using some editor only code since my input in the editor and on mobile are different.
    On my PC (editor) I always call the Character Controller's Move() function EVEN if there are 0 inputs!

    On my mobile I immediately STOP calling Move() when the joystick's touch position is equal to Vector2.zero.
    Since I stopped calling Move(); the velocity sqr mag NEVER reaches zero. WHILE the controller is not moving at all.
    This for me was unexpected behavior, I checked the documents but I didn't really understand this important line:
    So in other words, if you stop calling Move() on a CC the velocity shown is 'stuck' and won't change till you give it a different value. So the velocity will never reach 0 if you don't give it an input in which the controller won't move.
     
    Last edited: Sep 20, 2023
    RSolids likes this.
  10. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,952
    Please don't necro-post. If you have a new question, make a new post. It's FREE!!




    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, log output, variable values, and especially any errors you see
    - links to documentation you used to cross-check your work (CRITICAL!!!)

    The purpose of YOU providing links is to make our job easier, while simultaneously showing us that you actually put effort into the process. If you haven't put effort into finding the documentation, why should we bother putting effort into replying?



    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/

    - Do not TALK about code without posting it.
    - Do NOT post unformatted code.
    - Do NOT retype code. Use copy/paste properly using code tags.
    - Do NOT post screenshots of code.
    - Do NOT post photographs of code.
    - ONLY post the relevant code, and then refer to it in your discussion.





    If you have no idea what is going on in your project, fix that first. Here's how:

    Time to start debugging! Here is how you can begin your exciting new debugging adventures:

    You must find a way to get the information you need in order to reason about what the problem is.

    Once you understand what the problem is, you may begin to reason about a solution to the problem.

    What is often happening in these cases is one of the following:

    - the code you think is executing is not actually executing at all
    - the code is executing far EARLIER or LATER than you think
    - the code is executing far LESS OFTEN than you think
    - the code is executing far MORE OFTEN than you think
    - the code is executing on another GameObject than you think it is
    - you're getting an error or warning and you haven't noticed it in the console window

    To help gain more insight into your problem, I recommend liberally sprinkling
    Debug.Log()
    statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run? what order does it run in?
    - what are the names of the GameObjects or Components involved?
    - what are the values of the variables involved? Are they initialized? Are the values reasonable?
    - are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

    Knowing this information will help you reason about the behavior you are seeing.

    You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as
    Debug.Log("Problem!",this);


    If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

    You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

    You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

    You could also just display various important quantities in UI Text elements to watch them change as you play the game.

    Visit Google for how to see console output from builds. If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer for iOS: https://forum.unity.com/threads/how-to-capturing-device-logs-on-ios.529920/ or this answer for Android: https://forum.unity.com/threads/how-to-capturing-device-logs-on-android.528680/

    If you are working in VR, it might be useful to make your on onscreen log output, or integrate one from the asset store, so you can see what is happening as you operate your software.

    Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

    If your problem is with OnCollision-type functions, print the name of what is passed in!

    Here's an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

    https://forum.unity.com/threads/coroutine-missing-hint-and-error.1103197/#post-7100494

    "When in doubt, print it out!(tm)" - Kurt Dekker (and many others)

    Note: the
    print()
    function is an alias for Debug.Log() provided by the MonoBehaviour class.