How to make sword (or some other action) push target unit

How could we make the target unit move after getting hit by the sword, say for example moving over one square in the direction of the hit?

I figure it has something to do with using the MoveAction.cs code to determine if the target unit can move to the next square over (or more) but I am not sure how to get the valid grid position list for the target unit instead of the acting unit like we currently have it. Then after getting that list, would we just follow the TakeAction(GridPosition gridPosition, Action onActionComplete) in MoveAction.cs?

In this case, I’m not sure an Action is the right fit, as this is more of a Reaction, a passive effect as the result of getting hit by the sword (for example, we don’t want such an action showing up in the menu)…

Probably a special class you can put on the Unit that will accept a “push” from a given direction.

The actual methodology is rather simple… Say you push a unit in the GridPosition(0,1) direction, check to see if that GridPosition is unoccupied. If it is, set that GridPosition as a target and set some state that the unit is being pushed. Then an Update() on that component will see that it’s being pushed and transform.translate the character to that square quickly, but not too quickly.

I started something like this in Unit.cs

public void Pushed(int pushDistance)
    {
        List<GridPosition> validGridPositionList = new List<GridPosition>();

        GridPosition unitGridPosition = GetGridPosition(); //Grab unit position

        for (int x = -pushDistance; x <= pushDistance; x++) //Cycle through all valid grid positions
        {
            for (int z = -pushDistance; z <= pushDistance; z++)
            {
                GridPosition offsetGridPosition = new GridPosition(x, z);
                GridPosition testGridPosition = unitGridPosition + offsetGridPosition; //Using constructed operation from GridPosition

                if (!LevelGrid.Instance.IsValidGridPosition(testGridPosition)) //not valid then skip
                {
                    continue;
                }

                if (LevelGrid.Instance.HasAnyUnitOnGridPosition(testGridPosition))
                {
                    //Grid position has another unit. Checked on grid object and then through level grid.
                    continue;
                }

                if (!Pathfinding.Instance.IsWalkableGridPosition(testGridPosition))
                {
                    //Not walkable
                    continue;
                }
                validGridPositionList.Add(testGridPosition);
            }
        }
    }

However, I realized I am not actually setting a target from the other action. How could I get the target grid position behind the target unit at GridPosition(x, z +/- pushDistance) or GridPosition(x +/- pushDistance, z)?

If you have set up the math operators in GridPosition, then the direction of the push is the Target’s grid position - the attacker’s GridPosition
Since this is a sword attack, it should always be one unit away from the target’s unit…

GridPosition pushedGridPosition;
bool isPushed=false;
public void Pushed(GridPosition direction)
{
     GridPosition testGridPosition = GetGridPosition() + direction;
     if(!LevelGrid.Instance.IsValidGridPosition(testGridPosition)) return;
     if(LevelGrid.Instance.HasAnyUnitOnGridPosition(testGridPosition)) return;
     if(!Pathfinding.Instance.IsWalkableGridPosition(testGridPosition)) return;
     pushedGridPosition = testGridPosition;
     isPushed=true;
}

Then in Update, check to see if character is pushed… if it is, move the character towards the pushedGridPosition. If it’s close, just set the position to pushedGridPosition and clear isPushed.

I added unit.Pushed(targetUnit.GetGridPosition() - unit.GetGridPosition()); in the private void NextState() for SwordAction.cs and that seems to work fine.

Then I added the public void Pushed(GridPosition direction) in Unit.cs, but it isn’t able to get passed the second check. I put some debugs like so

GridPosition testGridPosition = GetGridPosition() + direction;
if (!LevelGrid.Instance.IsValidGridPosition(testGridPosition)) return;
Debug.Log("Pass step 1");
if (LevelGrid.Instance.HasAnyUnitOnGridPosition(testGridPosition)) return;
Debug.Log("Pass step 2");
if (!Pathfinding.Instance.IsWalkableGridPosition(testGridPosition)) return;
Debug.Log("Pass step 3");
pushedGridPosition = testGridPosition;
isPushed = true;
Debug.Log("Pushed? " + isPushed);

It gets passed the first step but then ends and so nothing happens. I tried flipping around unit.Pushed(unit.GetGridPosition() - targetUnit.GetGridPosition()); but that just made the sword unit go backward.

For reference, this is the code I added to Update()

if (!isPushed)
{
       return;
}
Debug.Log("Push activated");
Vector3 targetPosition = LevelGrid.Instance.GetWorldPosition(pushedGridPosition);
Vector3 moveDirection = (targetPosition - transform.position).normalized;

float rotateSpeed = 12f;
transform.forward = Vector3.Lerp(transform.forward, moveDirection, Time.deltaTime * rotateSpeed);

float stoppingDistance = .1f;
if (Vector3.Distance(transform.position, targetPosition) > stoppingDistance)
{
      float moveSpeed = 6f;
      transform.position += moveDirection * moveSpeed * Time.deltaTime;
}
else
{
       newGridPosition = LevelGrid.Instance.GetGridPosition(transform.position);
       isPushed = false;
}

Are you calling the Pushed() method on the target or the sword unit? :slight_smile:

That was the problem. I changed unit to targetUnit in unit.Pushed(targetUnit.GetGridPosition() - unit.GetGridPosition()); It all works now!

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms