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. Dismiss Notice

Having trouble with using basic vector math for character movement

Discussion in 'Scripting' started by Sendatsu_Yoshimitsu, Feb 20, 2015.

  1. Sendatsu_Yoshimitsu

    Sendatsu_Yoshimitsu

    Joined:
    May 19, 2014
    Posts:
    691
    I'm trying to write a function that takes cached movement input in the form of a x and y axis, and converts that to forces I can send to the motor elsewhere in my controller. Movement direction is determined by camera facing, so W/S should always move toward and away from the direction the camera is looking, and A/D should always move toward camera left and right. I have a working routine for W/S:

    Code (csharp):
    1.  
    2.     m_MotorThrottle += Player.InputMoveVector.Get().y * (Transform.TransformDirection(
    3.        Transform.InverseTransformDirection(Player.CameraLookDirection.Get()) *
    4.        (MotorAcceleration * 0.1f)));
    5.  
    I originally tried copy + pasting this for my left-right movement and substituting InputMoveVector.Get().x for Get().y, but that just made W/S and A/D move in the same direction. I barely understand why this works to begin with, so I'm wondering what needs to change for this math to return the same control behaviour (interpret axis in terms of camera direction) for InputMoveVector.Get()x (the A/D input) instead of Get().y?
     
  2. bloomingdedalus

    bloomingdedalus

    Joined:
    Aug 13, 2012
    Posts:
    139
    Transform.forward will give you the local forward direction in world coordinates as long as the script is attached to your camera.

    what do you mean by motor? You mean a vibrating controller? or is this an in game object?
     
  3. Sendatsu_Yoshimitsu

    Sendatsu_Yoshimitsu

    Joined:
    May 19, 2014
    Posts:
    691
    It's an in-game bit of code, I break movement into a couple of steps: get and cache the input, then I send it to the motor, which is a set of functions in my movement code that makes adjustments (smoothing, gravity if the player is mid-jump/falling, inertia if a moving object hits them from a given angle), calculates the final angle + velocity the player should move at, and notifies the character controller to move the character. This is heavily adapted from a commercial asset, which is why I'm having trouble figuring out exactly how the math functions, but this is essentially setting MotorThrottle to the angle we want to move the player at. The y value (W/S, movement towards and away from the camera) is what I posted, and what works correctly. What's bugging out is computing the correct x value, which I'm currently doing with

    Code (csharp):
    1.  
    2.     m_MotorThrottle += Player.InputMoveVector.Get().x * (Transform.TransformDirection(
    3.        Camera.main.transform.right *
    4.        (MotorAcceleration * 0.1f)));
    5.  
    What I expect this to do is: 1) Take the cached player movement on the x axis (A/D keys), 2) reorient it to be local to the camera facing, 3) combine that with the correctly-computed movement on the y-axis.

    What it actually does, however, is return movement in world space: A/D will always strafe toward and away from world X, regardless of how the camera moves. I made a gif illustrating the problem: http://imgur.com/kLI96a6

    The first bit of movement is holding the W key while rotating the mouse, and W correctly changes the angle it moves toward in response to the change in mouse orientation. The second bit of movement is holding the D key and rotating the mouse, the player model rotates correctly (this is done in separate code), but D's angle doesn't change in response to camera reorientation, resulting in a model that spins in place while moving toward world X.

    This sounds like a stupid thing to be having problems with, but I'm basically trying to figure out how to rewrite the code I posted in the opening to do exactly what it's already doing, only for the x-axis and Camera.right instead of the y axis and Camera.forward.
     
  4. bloomingdedalus

    bloomingdedalus

    Joined:
    Aug 13, 2012
    Posts:
    139
    I've never used "transformdirection" before, but it transforms a local coordinate into a world coordinate. Camera.main.transform.right is already in world coordinates otherwise it would just be Vector3.right because "right" in local coordinates is always (1,0,0) just like "right" in world coordinates is always (1,0,0).

    Get it? Transform.TransformDirection(Vector3.right) = Transform.right = Transform.TransformDirection(new Vector3(1,0,0))

    I'm still not sure what you're trying to do so I can't really help you beyond telling you that it makes no sense to transform a world coordinate relative to local space into world coordinates relative to local space.
     
    Last edited: Feb 20, 2015
  5. bloomingdedalus

    bloomingdedalus

    Joined:
    Aug 13, 2012
    Posts:
    139
    Maybe you're trying to get the world direction the camera is facing relative to the player?

    If you're in the player object's script:

    DirectionCameraIsFacingRelativeToMeInWorldCoords = Camera.Transform.Right
    DirectionCameraIsFacingRelativeToMeInLocalCoords = Transform.InverseTransformDireciton(Camera.Transform.Right)
     
  6. Sendatsu_Yoshimitsu

    Sendatsu_Yoshimitsu

    Joined:
    May 19, 2014
    Posts:
    691
    I hadn't noticed the second conversion, that did the trick! All I had to do was delete Transform.TransformDirection() from the second paragraph and it worked correctly- thank you!! I've been working on this for days :)
     
  7. bloomingdedalus

    bloomingdedalus

    Joined:
    Aug 13, 2012
    Posts:
    139
    But do you understand why it didn't make sense before?
     
  8. Sendatsu_Yoshimitsu

    Sendatsu_Yoshimitsu

    Joined:
    May 19, 2014
    Posts:
    691
    Yes, thank you again!