Search Unity

Question How do I scale an object using raycast in the right direction?

Discussion in 'Scripting' started by darkmax, Sep 26, 2022.

  1. darkmax

    darkmax

    Joined:
    Feb 21, 2012
    Posts:
    83
    Hi I was trying to make a box on runtime where the initial point is on the first click of the mouse (I have a box with a pivot on the bottom left corner) and then drag to the mouse in the direction where I want to create a box while holding the mouse button (I just scale the box with the distance in x and y).

    Like you can see on the video only works correctly on the back wall, and on the other walls does't work correctly with mix results, I know that this has to be related with the rotation of the camera, but I don't know if I need to apply some kind of vector to my object or something else to scale the object correctly on all the walls like the wall that is behind me.

    I hope some can guide me in the right direction to solve this problem, thanks in advance

    I attach a video on my problem and some snippets of my code.


    Code (CSharp):
    1. //Door Scale logic
    2.         if (Input.touchCount > 0)
    3.         {
    4.             Touch touch = Input.GetTouch(0);
    5.             Ray ray = Camera.main.ScreenPointToRay(touch.position); //ray from camera
    6.  
    7.             bool hasHit = Physics.Raycast(ray, out var hit, float.PositiveInfinity,LayerMask.GetMask("Wall")); //raycast from camera to infinity
    8.  
    9.             //If doesn't hit with wall exit
    10.             if (!hasHit)
    11.                 return;
    12.  
    13.             //If hits
    14.             if (touch.phase == TouchPhase.Began)
    15.             {
    16.                 //Set the pivot of the box on the first hit point
    17.                 currentDoor.transform.position = hit.point;
    18.                 currentDoor.transform.rotation = Quaternion.FromToRotation(Vector3.forward, hit.normal);
    19.                 currentDoor.transform.localScale = Vector3.one * 0.01f;
    20.             }
    21.             //If mouse is move scale the box with the width and height dimensions
    22.             else if (touch.phase == TouchPhase.Moved)
    23.             {
    24.                 float width = 0;
    25.                 float height = 0;
    26.  
    27.                 width = hit.point.x - currentDoor.transform.position.x;
    28.                 height = hit.point.y - currentDoor.transform.position.y;
    29.                 currentDoor.transform.localScale = new Vector3(width, height, 0.01f);
    30.             }
    31.         }
     
  2. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,108
    You don't want to arbitrarily scale an object without any control whatsoever, what you want is to be able to register any two different touches, and THEN, only once you have a legit input, you want to introduce code which will produce a box from these points in world space.

    In the final code, you can do this in every frame, which will result in what you want to achieve, but this is the order in which you need to setup your workflow to make this properly.

    To help you with the first part, make OnDrawGizmos method which will simply draw two spheres in proper places (i.e. Gizmos.DrawSphere). Once you're positive that the two points are where they're supposed to be I will help you make the code for the box itself.

    If your walls are always oriented as such (upright against the ground and only rotated on Y), making a box (or is it a rectangle that you want, boxes are 3D?) is a matter of aligning the box to match that Y rotation and resizing it in such a way that it barely contains the two endpoints. In your example your rectangle has a pivot that is corner based, and you need to think twice whether the box should have a corner pivot or a center pivot, as this will affect the way the scaling works.

    You can adapt the code to any convention, but it's important to stay consistent with such choices.

    All in all, what I'm trying to say is that you're supposed to solve this piece-wise, one thing after another, and that's the sure way to have a robust solution that won't bite you later. Start with registering touches properly (don't forget you need a surface normal as well) and we'll finish the rest of it, one thing at a time.