'Unity RTS style move object without navmesh agent

I'm trying to do RTS style movement with single selection only and without navmeshagent. When I click while another unit is already moving, its getting stopped and new one moving to same the point. Is there any way to seperate their hit points? Like I click to unit and order it to the point and then I click another unit and order him to another point.

Here is the video: demo

private Camera mycam;
private RaycastHit hit;
public Vector3 tf;
public LayerMask ground;
private bool move;


public static UnitMove instance;
private void Awake()
{
    instance = this;
}
private void Start()
{
    mycam = Camera.main;
}
private void Update()
{
    if (Input.GetMouseButtonDown(1) && haveSelected())
    {
        if (UnitClick.Instance.selectChanged)
        {
            getMouseRay();
        }
    }
    if (move)
    {
        SetDestination(UnitClick.Instance.selectedUnit.transform.position, hit);
    }
}
private void SetDestination(Vector3 unitPos, RaycastHit hit)
{
    move = true;
    if (Vector3.Distance(UnitClick.Instance.selectedUnit.transform.position, hit.point) > 0.5f)
    {
        UnitClick.Instance.selectedUnit.transform.position = Vector3.MoveTowards(UnitClick.Instance.selectedUnit.transform.position, 
            new Vector3(hit.point.x, UnitClick.Instance.selectedUnit.transform.position.y, hit.point.z), 1f * Time.deltaTime);
    }
}
public void getMouseRay()
{
    Ray ray = mycam.ScreenPointToRay(Input.mousePosition);
    if (Physics.Raycast(ray, out hit, Mathf.Infinity, ground))
    {
        move = true;
    }
}
private bool haveSelected()
{
    if (UnitSelection.Instance.unitSelected.Count > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

}



Solution 1:[1]

Looks to me like rather than just setting a destination, the SetDestination() function actually moves UnitClick.Instance.selectedUnit every frame. Once you click another unit, UnitClick.Instance.selectedUnit presumably changes to the newly selected unit, meaning every object’s SetDestination() code is always moving the same single object.

You’ll want to do something like save the destination in an instance variable when SetDestination() is first called and then have the move code change either:

  • change transform.position if the script is attached to the object you want to move
  • or if not: save the current UnitClick.Instance.selectedUnit in an instance variable when SetDestination() is first called and then change its position in the move code.

Edit: Here’s an attempt to show what I mean but note that this assumes the script is attached to the GameObject you want to move. It also preserves your existing system of setting the destination every frame while the unit is selected (it may be more desirable to update it only when the mouse is clicked?)

private Camera mycam;
private RaycastHit hit;
public Vector3 tf;
public LayerMask ground;
private bool move;

private Vector3 destination;

public static UnitMove instance;
private void Awake()
{
    instance = this;
}
private void Start()
{
    mycam = Camera.main;
}
private void Update()
{
    if (Input.GetMouseButtonDown(1) && haveSelected())
    {
        if (UnitClick.Instance.selectChanged)
        {
            getMouseRay();
        }
    }
    if (move)
    {
        if( transform == UnitClick.Instance.selectedUnit.transform ) // If we are currently selected
            SetDestination(/*UnitClick.Instance.selectedUnit.transform.position,*/ hit); // Update our destination

        // If ‘move’ is true, move towards our destination whether or not we are currently selected
        if (Vector3.Distance(transform.position, destination) > 0.5f) 
            transform.position = Vector3.MoveTowards(transform.position, destination, 1f * Time.deltaTime);
        else
            move = false; // This part is a guess at what you want — remove if it causes problems.
    }
}

private void SetDestination(/*Vector3 unitPos,*/ RaycastHit hit)
{
    move = true;
    destination = new Vector3(hit.point.x, transform.position.y, hit.point.z);
}

public void getMouseRay()
{
    Ray ray = mycam.ScreenPointToRay(Input.mousePosition);
    if (Physics.Raycast(ray, out hit, Mathf.Infinity, ground))
    {
        move = true;
    }
}
private bool haveSelected()
{
    if (UnitSelection.Instance.unitSelected.Count > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1