Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

a simple problem about math

Discussion in 'Scripting' started by RxGian, Jun 30, 2019.

  1. RxGian

    RxGian

    Joined:
    Mar 21, 2018
    Posts:
    41
    I using floating point forward and strafing, here's my script:
    Code (CSharp):
    1. Vector3 moveDir;
    2. float vertical; //forward, backward
    3. float horizontal; //strafing
    4.  
    5. moveDir = (this.transform.forward * vertical) + (this.transform.right * horizontal);
    the question is, how to get vertical and horizontal value if I already had moveDir? because my AI pathfinder give moveDir value, but I still need vertical and horizontal value so my AI can do Strafing anim.For example:

     (0,0,1) = [ (1,0,0) * vertical ] + [ (1,0,0) * horizontal ]  
     
  2. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,582
    I'm not completely sure what your going for here, but if you multiply transform.someDirection with a float... You will get some maths back lol. What exactly do those variables represent in this case? Are you assigning values to vertical and horizontal? The more you explain what your trying to accomplish the easier it is to give you a good answer, and without knowing more I can't say for sure what to try.
     
    RxGian likes this.
  3. RxGian

    RxGian

    Joined:
    Mar 21, 2018
    Posts:
    41


    Actually I was multiply with camera transform so my movement are based on camera facing. but this is for AI so I multiply with themselves. Here's the full image of explaination:



    so, for example: AI's point direction is x: 0.5 & z :0.5. and then AI moved to direction x: -0.5 & z 0.5 without facing to move direction (strafing)

    we can see actually they just move to the left based on their facing.
     
    Last edited: Jul 1, 2019
  4. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,482
    I'm also not sure what you're asking for, but based on what you've written here, it seems you want to reverse the calculation.

    For that case, you can imagine those vectors as some sort of mask for the three vector components. Forward only operates on the z axis, right only on the x axis. At least that's true if we don't take the current orientation of the object into account.

    For the purpose of explanation, lets ignore the rotation for a moment. In this particular scenario, the vectors component values are just factors that scale the corresponding direction (vertical, horizontal).

    If you want to take rotation into account, you can do the following:

    Since moveDir is a given value (in world space), you can transform this into the AI's local space. The local space should be aligned with the AI's "look direction". The result is, that the diagonal line of the look/attack direction in your image will be aligned with the local z, hence the example for the move direction is sort of aligned with the local x axis.

    Then again, it's just a matter of isolating the local x and z values for horizontal and vertical respectively. This should work for any values.

    If that's not what you're looking for, you'll have to go into a little more detail.
     
    MD_Reptile likes this.
  5. RxGian

    RxGian

    Joined:
    Mar 21, 2018
    Posts:
    41
    Yeah you right, I have problem with converting moveDir to local vector based on AI look direction, I had tried with subtracting global vector to AI look direction but some output value does not go right
     
  6. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,482
    For such purposes, there're built-in methods, the ones for directions are as follows:
    Transform.TransformDirection and Transform.InverseTransformDirection

    The former is used for local space of a transform -> world space, the latter for world space -> local space of a transform.

    There are similar methods for other uses. They're generally really handy and it's worth taking a look at them.
     
  7. RxGian

    RxGian

    Joined:
    Mar 21, 2018
    Posts:
    41
    so if I want to do that I must call AI transform and call inverse transform? I've tried that but the output is a bit difference, maybe because it not normalized but I am not sure
     
  8. calpolican

    calpolican

    Joined:
    Feb 2, 2015
    Posts:
    145
    For this case I think you should useTransform.InverseTransformPoint instead... I don't think you're after the direction but rather the position.
    You should also check if movDir is not already a local vector. If it is, you just need to take movDir.x for the horizontal and movDir.z for the vertical. But if movDir is indeed really a world vector, you can probably just get the local value doing:
    localMovDir = movDir - youCharacter.Transform.position... I think.
     
  9. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,482
    Yes, if it's facing direction is its transform's forward direction, then this should be fine.
    The direction itself it unaffected by any scale, so if you passed a direction that is not normalized, you cannot expect a direction vector that is normalized.

    If you visualized both, the original world space direction and the transformed local space directions, they'd be visually the exact same line (if you wanted to draw them as lines using their magnitude).

    As an example, the image you attached in a previous post shows a move direction in world space of (-0.5, 0.0, 0.5). The magnitude of that vector is
    mag = sqrt((-0.5 * -0.5) + (0.5 * 0.5)) = sqrt (0-25 + 0.25) which is ~ 0.7071.
    So it's not normalized, because its magnitude != 1.

    If you transformed that into local space of a transformed that's oriented as shown in your example (rotated by +45 degree around its y-axis), you should receive a local direction of roughly (0.7071, 0.0, 0.0).
     
  10. RxGian

    RxGian

    Joined:
    Mar 21, 2018
    Posts:
    41
    Thanks everyone that's really work when I tried to player input and print to console and it is matched, but I am really sorry before, Vertical and horizontal are used in my animation so It should work like throttle (output between -1 ~ 0 ~ 1), I was mistaken explained them worked as a movespeed, it actually throttle for animation.
    Code (CSharp):
    1. void Ingame_UpdateStates_FixedUpdate()
    2.         {
    3.            states.inp.horizontal = horizontal;
    4.            states.inp.vertical = vertical;
    5.  
    6.             states.inp.moveAmount = Mathf.Clamp01(Mathf.Abs(horizontal) + Mathf.Abs(vertical));
    7.             Vector3 moveDir = camHandler.transform.forward * vertical;
    8.             moveDir += camHandler.transform.right * horizontal;
    9.             moveDir.Normalize();
    10.             states.inp.moveDirection = moveDir;
    11.  
    12.             states.inp.rotateDirection = camHandler.mTransform.forward;;
    13.             float b = camHandler.mTransform.InverseTransformDirection(moveDir).x;
    14.             float a = camHandler.mTransform.InverseTransformDirection(moveDir).z;
    15.             Debug.Log("input ver/hor: " +vertical+"/"+horizontal+" | formula ver/hor :" +a+"/"+b);
    16.         }
    I modified it a bit for AI because they use same states script, I make separate class for control and character process:
    Code (CSharp):
    1. void Ingame_UpdateStates_FixedUpdate()
    2.         {
    3.             Vector3 moveDir = waypoint() - states.mTransform.forward;
    4.             moveDir.Normalize();
    5.             //moveDir = states.mTransform.InverseTransformPoint(moveDir);
    6.             horizontal = moveDir.x;
    7.             vertical= moveDir.z;
    8.             states.inp.horizontal = horizontal;
    9.             states.inp.vertical = vertical;
    10.  
    11.             states.inp.moveAmount = Mathf.Clamp01(Mathf.Abs(horizontal) + Mathf.Abs(vertical));          
    12.             states.inp.moveDirection = moveDir;
    13.             states.inp.rotateDirection = target;
    14.         }
    Here's some of my states code, used on both player and AI:
    Code (CSharp):
    1. void MovementNormal()
    2.         {
    3.             if (inp.moveAmount > 0.05f)
    4.                 rigid.drag = 0;
    5.             else
    6.                 rigid.drag = 4;
    7.  
    8.             float speed = stats.walkSpeed;
    9.             if (states.isRunning)
    10.                 speed = stats.runSpeed;
    11.             if (states.isCrouching)
    12.                 speed = stats.crouchSpeed;
    13.  
    14.             Vector3 dir = Vector3.zero;
    15.             dir = mTransform.forward * (speed * inp.moveAmount);
    16.             rigid.velocity = dir;
    17.         }
    18.  
    19.         void RotationNormal()
    20.         {
    21.             if(!states.isAiming)
    22.                 inp.rotateDirection = inp.moveDirection;
    23.             Vector3 targetDir = inp.rotateDirection;
    24.             targetDir.y = 0;
    25.  
    26.             if (targetDir == Vector3.zero)
    27.                 targetDir = mTransform.forward;
    28.  
    29.             Quaternion lookDir = Quaternion.LookRotation(targetDir);
    30.             Quaternion targetRot = Quaternion.Slerp(mTransform.rotation, lookDir, stats.rotateSpeed * delta);
    31.             mTransform.rotation = targetRot;
    32.         }
    33.  
    34.         void MovementAiming()
    35.         {
    36.             float speed = stats.aimSpeed;
    37.             Vector3 v = inp.moveDirection * speed;
    38.             rigid.velocity = v;
    39.         }
    40.  
    41.         void HandleAnimationAll()
    42.         {
    43.             //anim.SetBool("Sprinting", states.isRunning);
    44.             if(w_manager.GetCurrent() != null) anim.SetBool("Aiming", states.isAiming);
    45.             anim.SetBool("ground", states.onGround);
    46.             //anim.SetBool("Crouch", states.isCrouching);
    47.             if (states.isAiming)
    48.             {
    49.                 HandleAnimationsAiming();
    50.             }
    51.             else
    52.             {
    53.                 HandleAnimationsNormal();
    54.             }
    55.         }
    56.  
    57.         void HandleAnimationsNormal()
    58.         {
    59.             float anim_v = inp.moveAmount;
    60.             anim.SetFloat("vertical", anim_v, 0.15f, delta);
    61.             anim.SetFloat("horizontal", 0);
    62.         }
    63.  
    64.         void HandleAnimationsAiming()
    65.         {
    66.             float v = inp.vertical;
    67.             float h = inp.horizontal;
    68.            
    69.             anim.SetFloat("horizontal", h, 0.2f, delta);
    70.             anim.SetFloat("vertical", v, 0.2f, delta);
    71.         }
    72.  
    Actually I wrote this based on sharp accent channel, anyway maybe I can do something with localized vector. I will think about it. So the conclusion is modeDir should work as a global vector :facepalm:
    how do you know 0.7071 owned by X value of vector?
     
  11. RxGian

    RxGian

    Joined:
    Mar 21, 2018
    Posts:
    41
    I initially thought that moveDir works by issuing a local vector value, it turns out that after I check moveDir it should be of global value, because the moveDir value is used in rigidbody.addforce. But actually I just want to look for vertical and horizontal values which turns out to be used only to fill the animation value, which I have already posted one level above from here. So it turns out I only need the value to trigger the animation, and if it is diagonal then it should be ver = 0.5 / -0.5 hor = 0.5 / -05

    vector inverse is very useful knowledge, thank you for explaining it. But I still haven't found a solution, which seems like I was wrong to explain it earlier.

    n.b: I use google translate so sorry if it seems too convoluted

    EDIT: I've discovered that 0.7 0.7 is the max point of diagonal of radius 1.0, so converting into local vector is the answer. I don't need 1.0 1.0 because that outside of radius. How stupid I am I forgot pythagoras theorem even you already explained above. Once again it is because my language barrier and lack of knowledge about magnitude


    free image hosting
     
    Last edited: Jul 1, 2019
  12. calpolican

    calpolican

    Joined:
    Feb 2, 2015
    Posts:
    145
    What lenguage do you speak? maybe we can help with that.
    About this:
    Code (CSharp):
    1. Vector3 move = transform.InverseTransformDirection(agent.desiredVelocity);
    I could be wrong, but isn't the move.z just telling you how much your animator should go foward, and your mov.x value how much it should go to the side?
    What are you using, a blend tree?
    This things are tricky, but I'd almost bet you can do:
    Code (CSharp):
    1. animator.SetFloat("Forward", move.z, 0.1f, Time.deltaTime);
    2. animator.SetFloat("Side", move.x, 0.1f, Time.deltaTime);
     
    Last edited: Jul 1, 2019
    MD_Reptile likes this.
  13. RxGian

    RxGian

    Joined:
    Mar 21, 2018
    Posts:
    41
    I speak indonesian, anyway I use my own pathfinding for my final project, it's not perfect and still need fix. And now animation works fine. now what I'm looking for is known, Thanks a lot for you all guys.
     
    Last edited: Jul 1, 2019
    MD_Reptile likes this.