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

Steering Behaviors got me aaallll messed up, man.

Discussion in 'Scripting' started by jtsmith1287, Feb 26, 2015.

  1. jtsmith1287

    jtsmith1287

    Joined:
    Aug 3, 2014
    Posts:
    787
    Code (CSharp):
    1.     void Update() {
    2.  
    3.         Vector3 desiredVelocity = Vector3.Normalize(
    4.                 BaseShip.Target.position - transform.position) * BaseShip.baseSpeed;
    5.         Velocity = transform.TransformDirection(transform.forward) * BaseShip.Speed;
    6.         Destination = desiredVelocity - Velocity;
    7.         transform.LookAt(Velocity);
    8.  
    9.         transform.position += Vector3.Normalize(Destination) * BaseShip.Speed * Time.deltaTime;
    10.  
    EDIT: Previous image removed due to irrelevance and being solved. Just need the code working now.

    I have one simple question. $#($&#@*! Am I doing wrong??

    haha... I'm following this exactly as I'm reading it on multiple sites and I even bought a blasted bewk! I'm reading a bewk, people! I just.... *throws paper of his desk* Gaaahhhh!

    Please help. Thank you. :)

    EDIT: The box should stop at the fugly space ship.
    EDIT AGAIN: I realized I only specified in the title that I'm trying to implement steering behaviours, namely Seek, to start.
     

    Attached Files:

    • Derp.png
      Derp.png
      File size:
      34.7 KB
      Views:
      701
    Last edited: Feb 26, 2015
  2. nygren

    nygren

    Joined:
    Feb 13, 2014
    Posts:
    33
    Not sure why you're transforming transform.forward to get Velocity and using this as previous direction. Isn't transform.forward already your previous direction since it's in world coordinates? Are you trying to compensate for having moved your position or trying to introduce a less direct, more sliding approach of the box to the target? Seems like this value, Velocity, is not becoming what you intend it to be.

    Since you're using this value (Velocity) for drawing previous and current direction, and also moving your box these become incorrect?

    A guess as to why the red line (direction towards target) is wrong is that you've rotated and positioned the box with the incorrect Velocity value after calculating the direction to the target.
     
  3. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    There are some free assets on the store you can use as a start to your own steering solution.
     
  4. jtsmith1287

    jtsmith1287

    Joined:
    Aug 3, 2014
    Posts:
    787
    Transforming the forward gets me a normalized vector of the current heading. I started off with just transform.forward and the object always moved straight down (top down camera).

    The rotation of my object should not effect a 'thatposition - thisposition' calculation. I believe that once I solve why the red line problem this will work. Right now the object just moves to the center of the screen and stops. Regardless of what the player is doing (though when I move the lines slightly adjust). I'm sitting here with my book and looking at stuff online comparing back and forth and I'm doing exactly (that I can see, obviously) what it's showing.
    They're all expensive and once I get this method handled I can very easily handle the rest on my own.

    Do you guys have any other thoughts on what I might be doing wrong?
     
  5. nygren

    nygren

    Joined:
    Feb 13, 2014
    Posts:
    33
    I'm not so sure about that. Either way, if you want a normalized vector of current heading, why not use the Normalize method?
    It will not affect desiredVelocity, but it will affect everything else, including your position. Since you draw the line from your current position in the direction of target from your previous position, rotation will have an effect if your movement is large since your new position is based on it. But it's likely not large enough to be noticed.

    Your red line is wrong because you're treating your direction as a position.
    Code (csharp):
    1. Debug.DrawLine(transform.position, desiredVelocity, Color.red);
    should be
    Code (csharp):
    1. Debug.DrawLine(transform.position, transform.position + desiredVelocity, Color.red);
     
  6. jtsmith1287

    jtsmith1287

    Joined:
    Aug 3, 2014
    Posts:
    787
    In order to get the direction vector towards the target, you subtract the current position from the target's position. You're saying to then add the current position back in. I just tested to make sure I wasn't going crazy and it just makes the object spin in circles.
     
  7. nygren

    nygren

    Joined:
    Feb 13, 2014
    Posts:
    33
    What I'm saying is that DrawLine isn't drawing from a point in a direction. It draws from one point to another.

    Say your cube is at position (10,10,10) and your target at (15, 10, 10).

    Your desiredVelocity will be (5, 0, 0) and with the original code you will then draw the red line from (10, 10, 10) to (5, 0, 0).
     
    Last edited: Feb 26, 2015
  8. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    transform.forward is the object's local forward in world coordinates; so it looks like you've got some redundancy there

    IE - doing this will move an object one unit on its local forward
    Code (csharp):
    1.  
    2. transform.position += transform.forward;
    3.  
    If you want an object to move forward at a given speed then you would do this
    Code (csharp):
    1.  
    2. transform.position += transform.forward * speed * Time.deltaTime;
    3.  
    If you have a forward-facing velocity and no turn rate then the approach I would suggest would be to determine the desired velocity, transform.LookAt() that velocity + the current position and then move along transform.forward according to speed and time.
     
  9. nygren

    nygren

    Joined:
    Feb 13, 2014
    Posts:
    33
    Anyway, I'm not sure why you treat the vectors the way you do, but if your just going for a sort of velocity based drift without using physics, check out http://docs.unity3d.com/ScriptReference/Vector3.RotateTowards.html
    The following code is probably not quite correct (I didn't really think it through), but it makes the cube follow the spaceship. You will probably want to update it to for instance handle the difference in Speed and baseSpeed that you have. I also didn't really bother to make it optimized or clean. I just took your code and abused it a bit ;) Maybe it will give you some pointers

    Code (csharp):
    1.  
    2. Vector3 desiredVelocity = Vector3.Normalize(
    3.    Target.position - transform.position) * baseSpeed;
    4.  
    5. Vector3PrevVelocity = Velocity;
    6. Velocity = Vector3.RotateTowards(Velocity, desiredVelocity, 0.01f, 1f);
    7. transform.LookAt(transform.position + Velocity);
    8.  
    9. transform.position += Vector3.Normalize(Velocity) * Speed * Time.deltaTime;
    10.  
    11. //Drawaredlinethatshouldaimdirectlyatthetarget
    12. Debug.DrawLine(transform.position, transform.position + desiredVelocity, Color.red);
    13. //DrawayellowlineonthepreviousDirection
    14. Debug.DrawLine(transform.position, transform.position + PrevVelocity, Color.blue);
    15. //DrawagreenlineonthecurrentDirection.
    16. Debug.DrawLine(transform.position, transform.position + Velocity, Color.green);
    17.  
     
  10. jtsmith1287

    jtsmith1287

    Joined:
    Aug 3, 2014
    Posts:
    787
    Thanks for this. I'm trying to implement steering behaviors but just getting the seek in first since it's new for me, and I am not strong with vector math. I figured out your meaning with the lines. Once I added the current position the lines were all correct. At that point though I could clearly see that how I was handling them was different and obviously not giving desired results. I don't want to use RotateTowards as that will interfere with the steering behaviours.
    I've thoroughly tested this and you are incorrect. At least on my version of unity (4.6.2p), which shouldn't matter. I started off with just what you described and the object never turned. So with the scene running and the object moving towards its transform.forward I would rotate the object and it would not change directions. When I added the transform direction to the mix the object would then move in the direction I rotated it. I also checked this with debug.log. transform.forward is always (0, 0, 1). When I used transform direction the 0, 0, 1 would change based on the rotation. So, it's definitely not redundant. That's like the only thing in this whole mess I'm confident of, haha.
     
  11. nygren

    nygren

    Joined:
    Feb 13, 2014
    Posts:
    33
    KelsoMRK is correct. Quoting the documentation for Transform.forward (emphasis added by me):
    Just to be extra sure I tried it using 4.6.2f1 and it works as expected, ie rotating the object changes its transform forward and moved the object accordingly.

    So if your forward is always (0,0,1) I would suggest looking into why this is. Maybe that can give you some clues.
     
  12. jtsmith1287

    jtsmith1287

    Joined:
    Aug 3, 2014
    Posts:
    787
    I'm just using a standard primitive 3d cube. I have attached a script that only does what I've shown above. It just moves. When I tested I simple did transform.position += transform.forward * 5 * Time.deltaTime. I then went to the scene and rotated the object and it did not change directions. When I transformed directions and did the same it folowed its rotation. So unless my Unity build is bugged .... I don't know what I could possibly check. But regardless, I don't believe that's affecting my results, ya? I'm getting world coordinates either way. I'm mainly concerned with just getting this blasted bit to work, haha. I have no shame in admitting that I struggle with this stuff.

    (Side note, I encourage testing... I'd be totally comfortable betting against the accuracy of that snippet in the documentation)
     
  13. jtsmith1287

    jtsmith1287

    Joined:
    Aug 3, 2014
    Posts:
    787
    Code (CSharp):
    1.  
    2. Velocity = transform.TransformDirection(transform.forward);
    3. transform.position += Vector3.Normalize(DirectionToTarget - Velocity) * BaseShip.Speed * Time.deltaTime;
    4. transform.LookAt(transform.position + Destination);
    There we go. Phew... I was multiplying the Speed of the ship too often. I realized I needed to be merging the normalized vectors and THEN calculating the movement speed. Works like a charm now.

    EDIT: DirectionToTarget = Vector3.Normalize(
    BaseShip.Target.position - transform.position) * BaseShip.baseSpeed