Search Unity

screenPointToRay() not pointing to cursor?

Discussion in 'Scripting' started by lakehaze, Mar 10, 2012.

  1. lakehaze

    lakehaze

    Joined:
    Mar 7, 2011
    Posts:
    24
    A rigidbody cylinder follows the cursor. When the cylinder encounters an obstacle, it tries to push towards the cursor. Depending on the shape of the obstacle, the cylinder will bind and wait, with the obstacle between the cylinder and cursor, or will ride the obstacle's edge until it can rejoin the cursor.

    My code for the cylinder works. The cylinder constantly moves toward the cursor, and deflects off of and around obstacles. But after binding behind an obstacle, the cursor is no longer accurate.

    Example sequence:
    Cylinder follows cursor, to the right, near perfectly. fine
    Cursor crosses perpendicular obstacle. fine
    Cylinder collides and stops. fine
    Cursor drags 30 pixels further, to the right. fine
    Cylinder remains stuck behind obstacle. fine
    Cursor moves up-screen to pull cylinder around obstacle. fine
    Cylinder slides up-screen following cursor. fine
    Cylinder clears obstacle...
    Cylinder now targets a point 30 pixels left of the cursor. -broken-
    Cursor moves toward cylinder, to the left.
    Cylinder moves to the left, following a point 30 pixels to the left. -still broken-
    Sometimes, positioning cursor in a certain area will reset the issue, and the cylinder will re-target the cursor location and zip back to the correct cursor location.

    Why is my screenPointToRay() hit.point pointing to a location other than the cursor?


    This is the creation code for the cylinder (pathcyl, pathfinder):
    On camera.
    Code (csharp):
    1. var target : Transform; //player character
    2. var spawnOrigin = Vector3(0,0,0); //used for instancing spawn location
    3. var flag : GameObject; //waypoint prefab
    4. var waypoint : GameObject; //waypoint clone
    5. var pathcyl : GameObject; //****cylinder prefab****             <----------
    6. var pathfinder : GameObject; //****cylinder clone****          <----------
    7. var hit : RaycastHit;
    8. var ray : Ray;
    9.  
    10. function Update() {
    11.     transform.LookAt(target); //Camera looks at player character
    12.     if ( Input.GetMouseButtonDown(0)){
    13.         ray = Camera.main.ScreenPointToRay (Input.mousePosition);
    14.         if (Physics.Raycast (ray, hit, 100.0)){
    15.             spawnOrigin = Vector3(hit.point.x,2,hit.point.z);//set cylinder spawn location
    16.             pathfinder = Instantiate(pathcyl, spawnOrigin, Quaternion.identity); //create cylinder
    17.         }
    18.     }
    19.         if (Input.GetMouseButtonUp(0)){
    20.             Destroy(pathfinder); //destroy cylinder
    21.     }
    22. }
    And this is the behavior code on the cylinder:
    On cylinder prefab (pathcyl).
    Code (csharp):
    1. var hitPoint : Vector3 = Vector3(0,0,0);
    2. var hit : RaycastHit;
    3. var ray : Ray;
    4. var targetXY : Vector3 = Vector3(0,0,0);.
    5. var dist : float = 0; //placeholder: how far cylinder is from target.
    6. var attraction : float = 50; //arbitrary multiplier: How hard/fast the cylinder tries to reach the cursor
    7.  
    8. function Start() {
    9. rigidbody.centerOfMass = Vector3(0, -10, 0); //lowers center of gravity; cylinder should not roll onto it's side
    10. }
    11.  
    12. function Update() {
    13.     ray = Camera.main.ScreenPointToRay (Input.mousePosition); //generates ray?
    14.     if (Physics.Raycast (ray, hit, 100.0)){
    15.         hitPoint = hit.point; //define cursor location in 3D space
    16.     }
    17.     targetXY = Vector3(hitPoint.x,1,hitPoint.z); //negates the y-position value of the cursor location
    18.     transform.LookAt(targetXY); //aims cylinder forward axis toward cursor
    19.     dist = Vector3.Distance(targetXY,transform.position); //measures current distance from cursor
    20.     rigidbody.velocity = transform.forward*attraction*dist; //sets motion of cylinder to meet cursor.
    21.     //rigidbody.AddForce(transform.forward*attraction*dist*50); //same result with AddForce. too bouncy though.
    22. }
    [EDIT] Changed line 17 from: "targetXY = Vector3(hitPoint.x,transform.position.y,hitPoint.z);" no change in behavior.
     
    Last edited: Mar 11, 2012
  2. George Foot

    George Foot

    Joined:
    Feb 22, 2012
    Posts:
    399
    Maybe your cylinder is inadvertently moving in the Y axis when it's getting stuck colliding with the other object?
     
  3. lakehaze

    lakehaze

    Joined:
    Mar 7, 2011
    Posts:
    24
    It is doing that. I can see the cylinder (almost a disk) lower toward the ground plane as I pull the cursor further away across the obstacle. But it returns to the correct y-position value as the cursor distance decreases. I don't see a relationship between the cylinder's y-position value and the misalignment.

    To avoid this, I changed line 17 to set the y-position value to a constant '1':
    targetXY = Vector3(hitPoint.x,1,hitPoint.z);
    ... but the cylinder still 'dips' as the cursor draws further away. Not completely sure why. Still I feel it's unrelated as the y value repairs itself once clearing the obstacle. Just the hit.point position is off.

    Thanks for the suggestion :)
    Any other ideas?
     
    Last edited: Mar 11, 2012
  4. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,433
  5. lakehaze

    lakehaze

    Joined:
    Mar 7, 2011
    Posts:
    24
    Your camera is perspective? Is it aimed perpendicular with the ground plane? My camera is more 3rd person. The CameraDiff variable in that example doesn't seem to account for a tilted camera.

    I tried implementing it anyway. No dice.
     
    Last edited: Mar 11, 2012
  6. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,433
    you can try adding Debug.drawline line (to see where is your hitpoint)
    Code (csharp):
    1.         hitPoint = hit.point; //define cursor location in 3D space
    2.         Debug.DrawLine (Camera.main.transform.position+Vector3(0,-1,0), hit.point, Color.red,0.1);
    also,
    documentation says:
    Rigidbody.velocity
    "in most cases you should not modify the velocity directly, as this can result in unrealistic behaviour..."
     
  7. lakehaze

    lakehaze

    Joined:
    Mar 7, 2011
    Posts:
    24
    I wasn't able to get your code line to work:
    "BCE0023: No appropriate version of 'UnityEngine.Debug.DrawLine' for the argument list '(UnityEngine.Vector3, UnityEngine.Vector3, UnityEngine.Color, float)' was found."
    But I'm sure hitPoint is correct after implementing another test (line 14 below);

    You're right, the documentation does say not to adjust the rigidbody.velocity. I think this is an exception though because I'm not actually simulating real behavior, I just need the collision and solidity. Regardless, I've gone ahead and switched over to AddForce() to simplify the troubleshooting process. There is no difference in the offset target problem, the AddForce just causes the cylinder to become very elastic in it's movement.

    The code has evolved slightly and now looks like this:
    Code (csharp):
    1. function FollowCursor(){
    2.     var hitPoint : Vector3 = Vector3(0,0,0);
    3.     var hit : RaycastHit;
    4.     var ray : Ray;
    5.     var targetXY : Vector3 = Vector3(0,0,0);
    6.     var dist : float = 0;
    7.  
    8.     ray = Camera.main.ScreenPointToRay (Input.mousePosition);
    9.     if (Physics.Raycast (ray, hit, 100.0)){
    10.         hitPoint = hit.point;
    11.     }
    12.     targetXY = Vector3(hitPoint.x,yy,hitPoint.z); //Added 'yy' variable to set the altitude of vehicle.
    13.     dist = Vector3.Distance(targetXY,rigidbody.position); //changed from (targetXY,transform.position) No effect.
    14.     cubey.transform.position = targetXY; //Added non-physics cube to follow the hitPoint location. Bug is not in the ray.
    15.     transform.LookAt(targetXY);
    16.     //rigidbody.velocity = transform.forward*attraction*dist; //not currently modifying the velocity, although it makes no observable difference.
    17.     rigidbody.AddForce(transform.forward*attraction*dist*50);
    18.     transform.eulerAngles.x = 0; //red flag here
    19.     transform.eulerAngles.z = 0; // and here
    20.     rigidbody.position.y = yy;
    21. }
    Changed lines: 12,13,14,17,18,19,20
    Absolutely no effect on the target-location problem.

    'Cubey', at line 14, follows the cursor flawlessly.

    The eulerAngles code at lines 18 and 19 have me worried a bit, but I'm confident they are unrelated since the problem predates them. I don't like modifying the transform in physics sims, but I don't know another way to limit the rotation to the y axis. Trying Configurable Joint, but it's not really working.

    Anyway, line 14 shows that hitPoint is correct, and the problem is apparent by line 17, so it must be an issue with line 15 or 17, right? I just can't fathom how the cylinder, after breaking, will behave perfectly, just at an offset target.