简体   繁体   中英

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.

EDIT

This is my WayPoints script now. I'm adding a collider and the SlowDown script to each waypoint in the waypoints array:

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

public class WayPoints : MonoBehaviour {

    //setters for setting everything in Unity editor
    public float moveSpeedWalkSetter = 10f;
    public float moveSpeedSlowedWalkSetter = 3f;

    //static objects changeable via any script
    public static float moveSpeedWalk;
    public static float moveSpeedSlowedWalk;
    static ThirdPersonCharacter thirdperson;


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

    public Transform reverseTarget;
    private int reverseTargetsIndex = 0;
    private Vector3 reverseOriginalPosition;

    //public float walkSpeed = 15f;

    void Awake()
    {
        myTransform = transform;
    }
    // Use this for initialization
    void Start()
    {
        thirdperson = new ThirdPersonCharacter();

        moveSpeedWalk = moveSpeedWalkSetter;
        moveSpeedSlowedWalk = moveSpeedSlowedWalkSetter;
        thirdperson.ChangeSpeed(moveSpeedWalk);

        waypoints = GameObject.FindGameObjectsWithTag("ClonedObject");
        robots = GameObject.FindGameObjectsWithTag("Robots");

        AddColliderToWaypoints();
        AddSlowdownScriptToWaypoints();

        originalPosition = robots[0].transform.position;
        reverseOriginalPosition = robots[1].transform.position;
    }

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

        DrawLinesInScene();
    }

    public static void SetSpeed(float move)
    {
        thirdperson.ChangeSpeed(move);
    }


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

        //move towards the player
        robots[0].transform.position += robots[0].transform.forward * moveSpeedWalk * Time.deltaTime;
        if (distance < 2f)
            targetsIndex++;


    }

    private void ReverseWayPointsAI()
    {
        if (reverseTargetsIndex == 0)
            reverseTargetsIndex = waypoints.Length -1;
        reverseTarget = waypoints[reverseTargetsIndex].transform;
        float distance = Vector3.Distance(robots[1].transform.position, reverseTarget.transform.position);
        robots[1].transform.rotation = Quaternion.Slerp(robots[1].transform.rotation, Quaternion.LookRotation(reverseTarget.position - robots[1].transform.position), rotationSpeed * Time.deltaTime);

        //move towards the player
        robots[1].transform.position += robots[1].transform.forward * moveSpeedWalk * Time.deltaTime;
        if (distance < 2f)
            reverseTargetsIndex--;


    }

    void RandomWayPointsAI()
    {

    }

    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, robots[0].transform.position, Color.red);
        Debug.DrawLine(originalPosition, robots[1].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, robots[0].transform.position, Color.green);
        if (reverseTarget != null)
            Debug.DrawLine(reverseTarget.transform.position, robots[1].transform.position, Color.green);
    }

    void AddColliderToWaypoints()
    {
        foreach (GameObject go in waypoints)
        {
            SphereCollider sc = go.AddComponent<SphereCollider>() as SphereCollider;
            sc.isTrigger = true;
        }
    }

    void AddSlowdownScriptToWaypoints()
    {
        foreach (GameObject go in waypoints)
        {
            go.AddComponent<SlowDown>();
        }
    }
}

Then the SlowDown script

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);
    }

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

And in the ThirdPersonController script i add this

public void ChangeSpeed(float move)
        {
            m_MoveSpeedMultiplier = move;
        }

Now i'm using only the moving speed variable and not the walking speed. So i'm using only the move for now since it's a ThirdPersonController and not FirstPersonController.

But still it's not slowing down when entering OnTriggerEnter any way point .

My idea is you can check distance between 2 checkpoint if it is inline and then calculate speed.

var distanceCheckpoint = Vector3.Distance(checpoint_1.position, checpoint_2.position);
var distance = Vector3.Distance(myTransform.position, target.transform.position);
var thresholdSpeed = distance / distanceCheckpoint * moveSpeed;

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);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM