Home > Blockchain >  (Unity 3D) How to move a GameObject incrementally to set position once its trigger has been clicked?
(Unity 3D) How to move a GameObject incrementally to set position once its trigger has been clicked?

Time:11-08

enter image description here Just for clarity - Here is an image for reference, I want to click on the cubes at the bottom so that the larger cubes move left or right with that corresponding position being centered in the screen.

So this is the script I'm using, and my issue is that once I've clicked my trigger it only moves a fraction of the total distance, the MoveTowards function does work the way I want, the only issue is that I have to click on my trigger/s multiple times before it reaches it's set destination, I would like this to work so that I only have to click the trigger once and it will smoothly move to it's set destination incrementally instead of based off a certain amount of time between position because the starting position will constantly be changing.

From what I've researched I think I'll need a coroutine, I'm just wondering if there's a simpler way to do this as it feels like I'm only one or 2 steps off my goal here.

public class MoveBoxes : MonoBehaviour
{
    RayCast rayCast; 
    Camera cam;     
    public LayerMask mask;     
    private float speed = 7500f;

    public Vector3 initialPosition; 
    public Vector3 positionOne; 
    public Vector3 positionTwo; 
    public Vector3 positionThree; 
    public Vector3 positionFour; 
    public Vector3 positionFive; 
    public Vector3 positionSix; 
    public Vector3 positionSeven; 
    public Vector3 positionEight; 
    public Vector3 positionNine; 
    public Vector3 positionTen; 
    public Vector3 positionEleven; 
    public Vector3 positionTwelve; 
    public Vector3 positionThirteen; 
    public Vector3 positionFourteen;

    public Vector3 tempPosition;

    void Awake() { 
    
        cam = Camera.main;
        
        initialPosition = new Vector3(-28000.20f, -102.18f, -3919.06f);
        positionOne = new Vector3(37000.20f, -102.18f, -3919.06f);
        positionTwo = new Vector3(27000.20f, -102.18f, -3919.06f);
        positionThree = new Vector3(17000.20f, -102.18f, -3919.06f);
        positionFour = new Vector3(7000.20f, -102.18f, -3919.06f);
        positionFive = new Vector3(-3000.20f, -102.18f, -3919.06f);
        positionSix = new Vector3(-13000.20f, -102.18f, -3919.06f);
        positionSeven = new Vector3(-23000.20f, -102.18f, -3919.06f);
        positionEight = new Vector3(-33000.20f, -102.18f, -3919.06f);
        positionNine = new Vector3(-43000.20f, -102.18f, -3919.06f);
        positionTen = new Vector3(-53000.20f, -102.18f, -3919.06f);
        positionEleven = new Vector3(-63000.20f, -102.18f, -3919.06f);
        positionTwelve = new Vector3(-73000.20f, -102.18f, -3919.06f);
        positionThirteen = new Vector3(-83000.20f, -102.18f, -3919.06f);
        positionFourteen = new Vector3(-93000.20f, -102.18f, -3919.06f);
        
        tempPosition = transform.position;
        
    Debug.Log(transform.position);
    }
    
    void Update()
    {
    float move = speed * Time.deltaTime;
    bool hitTarget = false;
    
    if (Input.GetMouseButtonDown(0))
    {
        Ray ray = cam.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
    
        if (Physics.Raycast(ray, out hit, 15000, mask))
        {
            
            if (hit.collider.tag == "1stBox")
                do
                {
                    transform.position = Vector3.MoveTowards(transform.position, positionOne, move);
    
                    Debug.Log(transform.position);
                }
                while (hitTarget == true);
    
            if (hit.collider.tag == "2ndBox")
            {
                transform.position = Vector3.MoveTowards(transform.position, positionTwo, move);
    
                Debug.Log(transform.position);
            }
            if (hit.collider.tag == "3rdBox")
            {
                transform.position = Vector3.MoveTowards(transform.position, positionThree, move);
    
                Debug.Log(transform.position);
            }
            if (hit.collider.tag == "4thBox")
            {
                transform.position = Vector3.MoveTowards(transform.position, positionFour, move);
    
                Debug.Log(transform.position);
            }
            if (hit.collider.tag == "5thBox")
            {
                transform.position = Vector3.MoveTowards(transform.position, positionFive, move);
    
                Debug.Log(transform.position);
            }
            if (hit.collider.tag == "6thBox")
            {
                transform.position = Vector3.MoveTowards(transform.position, positionSix, move);
    
                Debug.Log(transform.position);
            }
            if (hit.collider.tag == "7thBox")
            {
                transform.position = Vector3.MoveTowards(transform.position, positionSeven, move);
    
                Debug.Log(transform.position);
            }
            if (hit.collider.tag == "8thBox")
            {
                transform.position = Vector3.MoveTowards(transform.position, positionEight, move);
    
                Debug.Log(transform.position);
            }
            if (hit.collider.tag == "9thBox")
            {
                transform.position = Vector3.MoveTowards(transform.position, positionNine, move);
    
                Debug.Log(transform.position);
            }
            if (hit.collider.tag == "10thBox")
            {
                transform.position = Vector3.MoveTowards(transform.position, positionTen, move);
                
                Debug.Log(transform.position);
            }
            if (hit.collider.tag == "11thBox")
            {
                transform.position = Vector3.MoveTowards(transform.position, positionEleven, move);
    
                Debug.Log(transform.position);
            }
            if (hit.collider.tag == "12thBox")
            {
                transform.position = Vector3.MoveTowards(transform.position, positionTwelve, move);
    
                Debug.Log(transform.position);
            }
            if (hit.collider.tag == "13thBox")
            {
                transform.position = Vector3.MoveTowards(transform.position, positionThirteen, move);
    
                Debug.Log(transform.position);
            }
            if (hit.collider.tag == "14thBox")
            {
                transform.position = Vector3.MoveTowards(transform.position, positionFourteen, move);
    
                Debug.Log(transform.position);
            }
        }
    }
}

I've looked into a bunch of different ways on how to do this, most results I get involve using a character, my project does not involve a character at this point in the game, nor does it need a rigid body, these GameObjects will eventually be triggers for further events.

I need my Parent-GameObject to move based off of framerate/increments of space rather than based off amount of time. as the whole object shifts, the starting position will be constantly changing also.

The do/while statement in the code can be removed, at the moment it's ineffective, I was trying to use this method to loop the function in my script, with the goal to make a single mouse click act asif it's continuously being clicked. At the moment when I click on a trigger it will only move a fraction of the distance towards the target destination.

CodePudding user response:

Problem is in using if statemen without loops like here

 if (Physics.Raycast(ray, out hit, 15000, mask))
        {
            
            if (hit.collider.tag == "1stBox"){
                ....
        }
       ......
      }

Make new variable float dist; and set it to be equal to distance between transform.position and destination point, like this: Vector3.Distance(transform.position, positionOne) for first and so on.

after that use a While loop to check if distance is greater than 0.

Now your code will look like this:

float dist;
 if (Physics.Raycast(ray, out hit, 15000, mask))
        {
            
            if (hit.collider.tag == "1stBox"){
                dist = Vector3.Distance(transform.position, positionOne);
                while (dist > 0){
                      transform.position = Vector3.MoveTowards(transform.position, positionOne, move);
     
                }
        }
       ......
      }

This code is NOT tested but should work

CodePudding user response:

If I may, I looked at first reducing the amount of code to make things clearer, and then secondly, allowing the object to steadily move towards a destination. Naturally, as with almost all coding solutions, this is just one out of many ways to accomplish this.

The reason you need to trigger the code multiple times is because MoveTowards simply calculated a single value that represents a new position along the path from origin to destination. It is not a repeating function, it does one calculation and then stops. The method needs to be called every frame so that you can get a smooth movement from one position to the next. Your origin will change every frame as you get closer to the destination, but your destination point will stay the same. The movement step is also calculated by Time.deltaTime so that the movement is smooth independent of frame rate.

The resulting code looks like this:

public class MoveBoxes : MonoBehaviour
{
    [SerializeField] private float speed = 7500f;

    // Set default position values.
    [SerializeField] private List<Vector3> _positions = new()
    {
        new Vector3 ( -28000.20f, -102.18f, -3919.06f ),
        new Vector3 ( 37000.20f, -102.18f, -3919.06f ),
        new Vector3 ( 27000.20f, -102.18f, -3919.06f ),
        new Vector3 ( 17000.20f, -102.18f, -3919.06f ),
        new Vector3 ( 7000.20f, -102.18f, -3919.06f ),
        new Vector3 ( -3000.20f, -102.18f, -3919.06f ),
        new Vector3 ( -13000.20f, -102.18f, -3919.06f ),
        new Vector3 ( -23000.20f, -102.18f, -3919.06f ),
        new Vector3 ( -33000.20f, -102.18f, -3919.06f ),
        new Vector3 ( -43000.20f, -102.18f, -3919.06f ),
        new Vector3 ( -53000.20f, -102.18f, -3919.06f ),
        new Vector3 ( -63000.20f, -102.18f, -3919.06f ),
        new Vector3 ( -73000.20f, -102.18f, -3919.06f ),
        new Vector3 ( -83000.20f, -102.18f, -3919.06f ),
        new Vector3 ( -93000.20f, -102.18f, -3919.06f )
    };

    // Set default tag names.
    [SerializeField] private List<string> _tags = new()
    {
        "1stBox",
        "2ndBox",
        "3rdBox",
        "4thBox",
        "5thBox",
        "6thBox",
        "7thBox",
        "8thBox",
        "9thBox",
        "10thBox",
        "11thBox",
        "12thBox",
        "13thBox",
        "14thBox"
    };

    [SerializeField] private LayerMask _mask;

    [SerializeField] private Camera _cam;

    public bool moving { get; private set; }
    public int destinationIndex { get; private set; }


    private void Awake ( )
    {
        _cam = Camera.main;
    }

    void Update ( )
    {
        if ( Input.GetMouseButtonDown ( 0 ) )
        {
            if ( Physics.Raycast ( _cam.ScreenPointToRay ( Input.mousePosition ), out var hit, 15000, _mask ) )
            {
                for ( int i = 0; i < _tags.Count; i   )
                    if ( hit.collider.CompareTag ( _tags [ i ] ) )
                    {
                        // If a Box has been hit, set this as the new destination.
                        destinationIndex = i   1;
                        moving = true;
                        break;
                    }
            }
        }

        // if 'moving' is true, move slightly closer to destination every frame.
        if ( moving )
        {
            transform.localPosition = Vector3.MoveTowards ( 
                transform.localPosition, 
                _positions[ destinationIndex ], 
                speed * Time.deltaTime );

            // When two Vector3 items are compared with ==, they are determined to be
            // equal if they're 'approximately' the same, and very close to each other.
            if ( transform.localPosition == _positions [ destinationIndex ] )
                moving = false;
        }
    }
}

Here's the docs for the Screen Capture

  • Related