Daniel Halfoni Daniel Halfoni -4 years ago 103
C# Question

How can i make that when the player is getting close to a waypoint he will slow down and then will speed up again?

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityStandardAssets.Characters.ThirdPerson;

public class WayPoints : MonoBehaviour {

public GameObject[] waypoints;
public Transform target;
public float moveSpeed = 1f;
public float rotationSpeed = 1f;
private Transform myTransform;
private int targetsIndex = 0;
private Vector3 originalPosition;

public float walkSpeed = 15f;

void Awake()
{
myTransform = transform;
}
// Use this for initialization
void Start()
{
waypoints = GameObject.FindGameObjectsWithTag("ClonedObject");

originalPosition = myTransform.position;
}

// Update is called once per frame
void Update()
{
if (MyCommands.walkbetweenwaypoints == true)
{
WayPointsAI();
}

DrawLinesInScene();
}

private void WayPointsAI()
{
if (targetsIndex == waypoints.Length)
targetsIndex = 0;
target = waypoints[targetsIndex].transform;
float distance = Vector3.Distance(myTransform.position, target.transform.position);
myTransform.rotation = Quaternion.Slerp(myTransform.rotation, Quaternion.LookRotation(target.position - myTransform.position), rotationSpeed * Time.deltaTime);

//move towards the player
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
if (distance < 2f)
targetsIndex++;

if (distance < 5f)
{
moveSpeed = 5;
}
else
{

}
}

void DrawLinesInScene()
{
// draw lines between each checkpoint //
for (int i = 0; i < waypoints.Length - 1; i++)
{
Debug.DrawLine(waypoints[i].transform.position, waypoints[i + 1].transform.position, Color.blue);
}

// draw a line between the original transform start position
// and the current transform position //
Debug.DrawLine(originalPosition, transform.position, Color.red);

// draw a line between current transform position and the next waypoint target
// each time reached a waypoint.
if (target != null)
Debug.DrawLine(target.transform.position, myTransform.position, Color.green);
}
}


I want that when the player/gameobject is getting close to the next waypoint he will slow down and then when he pass the waypoint and after did the rotation to the next waypoint speed uo to the original speed it was before slow down.

So i added:

if (distance < 5f)
{
moveSpeed = 5;
}
else
{

}


But first I'm not sure if
< 5
is far enough to make it slow but let's say for a second it's far enough how do i make it to speed up after reaching the way point and rotating to the next one ? I could store the original speed in some variable in the
Start
function but there might be a situation where the user change the speed while the game is running already so storing the original speed in the Start function will not work all the time.

And how can i find each waypoint in the array waypoints radius ?
Now i set it to distance < 2

if (distance < 2f)
targetsIndex++;


But if the waypoint object radius is bigger then 2 the player will stuck at this waypoint. so i think instead checking against 2f it should be something like distance < waypoints[i].radius or how to find radius. The logic is to find the radius of each way point and check against it's radius and not 2f.

Answer Source

Assuming player movement speed is changed by float and you are using unity standard asset 3rd First Person Controller. You can of adjust it to your custom player controller. Anyway this script require you to set moveSpeedSetter, moveSpeedSlowedSetter and motorSetter in Editor. You can put this script anywhere you like.

using UnityEngine;

public class WayPoints : MonoBehaviour
{
    //setters for setting everything in Unity editor
    public float moveSpeedSetter = 1f;
    public float moveSpeedSlowedSetter = 0.5f;
    public CharacterMotor motorSetter;

    //static objects changeable via any script
    public static float moveSpeed;
    public static float moveSpeedSlowed;
    public static CharacterMotor motor;

    public static void SetSpeed(float speed)
    {
        motor.movement.maxForwardSpeed = speed;
    }

    private void Start()
    {
        moveSpeed = moveSpeedSetter;
        moveSpeedSlowed = moveSpeedSlowedSetter;
        motor = motorSetter;
        motor.movement.maxForwardSpeed = moveSpeed;
    }
}

After that create empty object in all your waypoints and add trigger to them. Then put this script on that newly created object with trigger.

using UnityEngine;

class SlowDown : MonoBehaviour
{ 
    private void OnTriggerEnter(Collider other)
    {
        Debug.Log("Object " +other.name+" entered "+ name);
        WayPoints.SetSpeed(WayPoints.moveSpeedSlowed);
    }

    private void OnTriggerExit(Collider other)
    {
        Debug.Log("Object " + other.name + " exited " + name);
        WayPoints.SetSpeed(WayPoints.moveSpeed);
    }
}

---EDIT FOR UNITY 5 BELOW---

So in order to access float WalkSpeed and RunSpeed of object FirstPersonController defautly in gameObject FPSController from Unity standard asset you have to modify it or make your own method for accessing them like this one. (you can just put that anywhere inside FirstPersonController script).

 public void ChangeSpeed(float walk,float run)
        {
            m_WalkSpeed = walk;
            m_RunSpeed = run;
        }

Here is script for movement speed control

using UnityEngine;
using UnityStandardAssets.Characters.FirstPerson;

public class WayPoints : MonoBehaviour
{
    //setters for setting everything in Unity editor
    public float moveSpeedRunSetter = 10f;
    public float moveSpeedSlowedRunSetter = 6f;
    public float moveSpeedWalkSetter = 5f;
    public float moveSpeedSlowedWalkSetter = 3f;
    public FirstPersonController motorSetter;

    //static objects changeable via any script
    public static float moveSpeedRun;
    public static float moveSpeedSlowedRun;
    public static float moveSpeedWalk;
    public static float moveSpeedSlowedWalk;
    public static FirstPersonController motor;

    public static void SetSpeed(float walk, float run)
    {
        motor.ChangeSpeed(walk, run);
    }

    private void Start()
    {
        moveSpeedWalk = moveSpeedWalkSetter;
        moveSpeedSlowedWalk = moveSpeedSlowedWalkSetter;
        moveSpeedRun = moveSpeedRunSetter;
        moveSpeedSlowedRun = moveSpeedSlowedRunSetter;
        motor = motorSetter;
        motor.ChangeSpeed(moveSpeedWalk, moveSpeedRun);
    }
}

Here is script for waypoints

using UnityEngine;
using UnityStandardAssets.Characters.FirstPerson;

class SlowDown : MonoBehaviour
{ 
    private void OnTriggerEnter(Collider other)
    {
        Debug.Log("Object " +other.name+" entered "+ name);
        WayPoints.SetSpeed(WayPoints.moveSpeedSlowedWalk, WayPoints.moveSpeedSlowedRun);
    }

    private void OnTriggerExit(Collider other)
    {
        Debug.Log("Object " + other.name + " exited " + name);
        WayPoints.SetSpeed(WayPoints.moveSpeedWalk, WayPoints.moveSpeedRun);
    }
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download