Slow enemy towards waypoint

Hi, I am making a Tower Defence game and have tried to make a slow tower. It slows the enemy, but the enemy backs, and then continues with a lower speed. It does this because I’m using Lerp. But I don’t know how to fix it. Here is my code:

    private int currentWaypoint = 0;
    private float lastWaypointSwitchTime;
    private float lastSlowedSwitchTime; //TODO: Remove slow after some seconds
    public float speed = 1.0f;

    private bool slowed = false;
    private SpriteRenderer spriteRenderer;

    void Start(){
        lastWaypointSwitchTime = Time.time;
        lastSlowedSwitchTime = Time.time;
        spriteRenderer = GetComponentInChildren<SpriteRenderer> ();
    }

    void Update(){
        Vector3 startPosition = waypoints [currentWaypoint].transform.position;
        Vector3 endPosition = waypoints [currentWaypoint + 1].transform.position;

        float pathLength = Vector3.Distance (startPosition, endPosition);
        float pathLengthGotten = Mathf.Abs(Vector3.Distance (gameObject.transform.position , endPosition) - pathLength);
        float pathLengthLeft = pathLength - pathLengthGotten;

        float totalTimeForPath = pathLength / speed; 

        //FIXME: New waypoint from where he gets shot, to the waypoint
        float currentTimeOnPath = Time.time - lastWaypointSwitchTime;

        if(slowed){
            currentTimeOnPath = Time.time - lastWaypointSwitchTime;
            totalTimeForPath = pathLength / speed;       
            gameObject.transform.position = Vector3.Lerp (gameObject.transform.position, endPosition, currentTimeOnPath / totalTimeForPath);
            Debug.Log (currentTimeOnPath);
        }else{
            gameObject.transform.position = Vector3.Lerp (startPosition, endPosition, currentTimeOnPath / totalTimeForPath);
        }


        if(gameObject.transform.position.Equals(endPosition)){
            if(currentWaypoint < waypoints.Length - 2){
                currentWaypoint++;
                lastWaypointSwitchTime = Time.time;
                if(slowed){
                    lastSlowedSwitchTime = Time.time;
                }
                RotateIntoMoveDirection ();
            } else {
                Destroy (gameObject);

                GameManagerBehavior gameManager = GameObject.Find ("GameManager").GetComponent<GameManagerBehavior> ();
                gameManager.Health -= 1;

                AudioSource audioSource = gameObject.GetComponent<AudioSource> ();
                AudioSource.PlayClipAtPoint (audioSource.clip, transform.position);
            }
        }
    }

Do you want the enemy to speed up to normal speed after? need more explanation :stuck_out_tongue:

Yes, but that’s not the problem. When the turret hits the enemy, the speed goes down with 0.5. Because of this gameObject.transform.position doesnt work, so the enemy teleports backwards, and then continues at 0.5 of the speed

It moves forwards with this code

Are you effecting the position on the object that hits the enemy?

It only makes the slowed variable true

I think maybe using lerps isn’t the best way to do movement.

you are moving to a point, so when you reach the point the lerp value will be 1,

It seems you are dividing the lerp value when slowed = true;

seeming as this is how you’re moving to the next point it will make it go from like 0.54 of the way, to like 0.36 which means it loses the value.

Do you have any other good way of doing it?

I’ve never made a tower defence game before, but i would use the Navmeshagent and waypoints, and just half the speed on a bullet collision. This also allows you to bake the map and set the movable zones for the enemies

edit: i’m also pretty sure navmeshagents aren’t suitable for 2D games, as it’s not supported as of my knowledge,

I would use vector3.distance and vector3.movetowards to get player movement, and set up 2d box colliders so they cant go into unwanted zones

Im using the vector3.moveTowards. But I can’t use the deltaTime. When i use this

gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, endPosition, speed * Time.deltaTime);
The enemy starts on the right side (should be left), and out of bounds.

Does the enemy spawn into the start position? or you place them there?

its possibly getting spawned using the prefab’s transform data, depending on the Instantiate method your using. The Instantiate() version can be buggy sometimes in that the transform isn’t cached properly. it’ll render in the scene where you specify it, but in physics memory it’ll think its at it’s prefab’s location. I’ve had my fair share of this issue back in 5.1.2 (when I tried to do raycasts from its transform position) and I’m not sure if it was ever fixed. nonetheless switching back to the normal Instantiate (and moving the prefab out of the way) avoided this issue.

normally in your code you were lerping from waypoint to waypoint. now you need to moveTowards to next waypoint from your current position, so you need to make sure you’re at the right position when you start.

in that script’s Start method just make sure that the transform.position = waypoints [0].transform.position;