1

private int PingPong(int baseNumber, int limit)
{
    if (limit < 2) return 0;
    return limit - Mathf.Abs(limit - Modulus(baseNumber, limit + (limit - 2)) - 1) - 1;
}

private int Modulus(int baseNumber, int modulus)
{
    return (modulus == 0) ? baseNumber : baseNumber - modulus * (int)Mathf.Floor(baseNumber / (float)modulus);
}

It's part of my script. I thought it should make the object to move between two waypoints back and forward. But it's not.

I can't figure out what this part of the code should do and what it does.

My complete script with the changes I did:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class PatrolData
{
    public Transform target = null;
    public float minDistance = 5f;
    public float lingerDuration = 5f;
    public float desiredHeight = 10f;
    public float flightSmoothTime = 10f;
    public float maxFlightspeed = 10f;
    public float flightAcceleration = 1f;
    public float levelingSmoothTime = 0.5f;
    public float maxLevelingSpeed = 10000f;
    public float levelingAcceleration = 2f;
}

public class PatrolOverTerrain : MonoBehaviour
{
    public FlyToOverTerrain flyOverTerrain;
    public LookAtCamera lookAtCamera;
    public UserInformation userinformation;
    public enum PatrolMode { Clamp, Wrap, PingPong, Random };
    public PatrolData[] patrolPoints;
    public PatrolMode mode = PatrolMode.Wrap;

    private int iterator = 0;
    private int index = 0;
    private float lingerDuration = 0f;
    private int overallLength = 0;

    public bool autoFreedomPatrol = false;
    public List<GameObject> Targets = new List<GameObject>();
    public string tagName;
    public Vector3 distanceFromTarget;
    public float k = 0f;
    public Vector3 WayPointA;
    public Vector3 WayPointB;

    public void Start()
    {
        if (tagName != "")
        {
            GameObject[] tempObj = GameObject.FindGameObjectsWithTag(tagName);

            for (int i = 0; i < tempObj.Length; i++)
            {
                //Add to list only if it does not exist
                if (!Targets.Contains(tempObj[i]))
                {
                    Targets.Add(tempObj[i]);
                }
            }

            //Get the current Size
            if (tempObj != null)
            {
                overallLength = Targets.Count;
            }

            GeneratePatrolPoints();
        }
    }

    private void OnEnable()
    {
        if (patrolPoints.Length > 0)
        {
            lingerDuration = patrolPoints[index].lingerDuration;
        }
    }

    private void Update()
    {
        int length = patrolPoints.Length;
        if (!flyOverTerrain) return;
        if (patrolPoints.Length < 1) return;
        if (index < 0) return;

        var patrol = patrolPoints[index];

        if (lingerDuration <= 0)
        {
            iterator++;
            switch (mode)
            {
                case PatrolMode.Clamp:
                    index = (iterator >= length) ? -1 : iterator;
                    break;
                case PatrolMode.Wrap:
                    iterator = Modulus(iterator, length);
                    index = iterator;
                    break;
                case PatrolMode.PingPong:
                    WayPointA = patrolPoints[index].target.position;
                    WayPointB = patrolPoints[index + 1].target.position;
                    break;
                case PatrolMode.Random:
                    index = Random.Range(0, patrolPoints.Length);
                    break;
            }
            if (index < 0) return;

            patrol = patrolPoints[index];

            flyOverTerrain.target = patrol.target;
            flyOverTerrain.desiredHeight = patrol.desiredHeight;
            flyOverTerrain.flightSmoothTime = patrol.flightSmoothTime;
            flyOverTerrain.maxFlightspeed = patrol.maxFlightspeed;
            flyOverTerrain.flightAcceleration = patrol.flightAcceleration;
            flyOverTerrain.levelingSmoothTime = patrol.levelingSmoothTime;
            flyOverTerrain.maxLevelingSpeed = patrol.maxLevelingSpeed;
            flyOverTerrain.levelingAcceleration = patrol.levelingAcceleration;

            if (lookAtCamera != null)
            {
                lookAtCamera.target = patrol.target;
                lookAtCamera.RotationSpeed = 3;
            }
            //userinformation.target = patrol.target;

            lingerDuration = patrolPoints[index].lingerDuration;
        }

        Vector3 targetOffset = Vector3.zero;
        if ((bool)patrol.target)
        {
            targetOffset = transform.position - patrol.target.position;
        }

        float sqrDistance = patrol.minDistance * patrol.minDistance;
        if (targetOffset.sqrMagnitude <= sqrDistance)
        {
            flyOverTerrain.target = null;
            if (lookAtCamera != null)
                lookAtCamera.target = null;
            lingerDuration -= Time.deltaTime;
        }
        else
        {
            flyOverTerrain.target = patrol.target;
            if (lookAtCamera != null)
                lookAtCamera.target = patrol.target;
        }
        distanceFromTarget = transform.position - patrol.target.position;
    }

    private void PingPong()
    {  
        k = Mathf.PingPong(Time.time, 1);
        transform.position = Vector3.Lerp(WayPointA, WayPointB, k);
    }

    private int Modulus(int baseNumber, int modulus)
    {
        return (modulus == 0) ? baseNumber : baseNumber - modulus * (int)Mathf.Floor(baseNumber / (float)modulus);
    }

    public void GeneratePatrolPoints()
    {
        patrolPoints = new PatrolData[Targets.Count];
        for (int i = 0; i < patrolPoints.Length; i++)
        {
            patrolPoints[i] = new PatrolData();
            patrolPoints[i].target = Targets[i].transform;
            patrolPoints[i].minDistance = 30f;
            patrolPoints[i].lingerDuration = 3f;
            patrolPoints[i].desiredHeight = 20f;
            patrolPoints[i].flightSmoothTime = 10f;
            patrolPoints[i].maxFlightspeed = 10f;
            patrolPoints[i].flightAcceleration = 3f;
            patrolPoints[i].levelingSmoothTime = 0.5f;
            patrolPoints[i].maxLevelingSpeed = 10000f;
            patrolPoints[i].levelingAcceleration = 2f;
        }
    }
}

The changes I did and tried so far:

Added WaypointA and WaypointB as global variables:

public Vector3 WayPointA;
public Vector3 WayPointB;

Then in the case of PingPong I did:

case PatrolMode.PingPong:
    WayPointA = patrolPoints[index].target.position;
    WayPointB = patrolPoints[index + 1].target.position;
    break;

Then created a PingPong method:

private void PingPong()
    {  
        k = Mathf.PingPong(Time.time, 1);
        transform.position = Vector3.Lerp(WayPointA, WayPointB, k);
    }

But I'm not sure where to call the PingPong method in the Update ?

And maybe I should use a flag bool type to check when it's pingpong mode in the Update ?

What I want to do is if I start the game in PingPong mode case then the object should move between waypoint index 0 and index 1 nonstop.

But if I change the mode to PingPong in the middle while the game is running then the object should move between the current waypoint index and the next one. For example between index 4 and index 5.

zwcloud
  • 4,546
  • 3
  • 40
  • 69
Daniel Lip
  • 3,867
  • 7
  • 58
  • 120
  • I think I know your issue. I can answer if you explain what PatrolMode.Clamp, PatrolMode.Wrap and PatrolMode.Random are supposed to do. I know that PatrolMode.PingPong should move from index0 to index1 but not the others. – Programmer Mar 19 '18 at 16:53
  • Programmer the other I don't know what they are doing either. I don't fully understand this script. I know when I select the Wrap mode the object is moving between the waypoints from first to last from 0 to length. Clamp I don't know what it is. But Random is my own mode I added it and Random should just move the object randomly between the waypoints. If Wrap we said making the object moving from 0 to length then Random should be moving it randomly. – Daniel Lip Mar 19 '18 at 19:43
  • @Programmer The Random mode is working I think I tested it and the object is moving randomly between the waypoints. Sometimes the object when he is on Random mode and he is reaching a waypoint he is wating there longer I'm not sure why but in most of the cases the object move after 3-5 seconds. – Daniel Lip Mar 19 '18 at 19:45
  • @Programmer Another problem is that I don't know how to change the time of the object to wait at each waypoint. For example if I don't it to wait at all. – Daniel Lip Mar 19 '18 at 19:45
  • @Programmer Here is a 3 links for the 3 scripts I'm using for it. All 3 scripts are attached to the same GameObject. The first link is for the PatrolOverTerrain script: https://pastebin.com/s1N9yj3B The second link is for the script FlyOverTerrain: https://pastebin.com/AdPrSAVc and the last link is for the script LookAtCamera: https://pastebin.com/txD70PRE – Daniel Lip Mar 19 '18 at 19:48
  • @Programmer The scripts are all working fine and do what I wanted in the beginning: A object that move between the waypoints and moving also depending on the terrain heights bumps and using the LookAtCamera the object is smooth rotating to each next waypoint. – Daniel Lip Mar 19 '18 at 19:51
  • @Programmer Now I want to add two more modes for the enum: Random and PingPong. Random should make the object to be moving randomly between the waypoint. PingPong at any time should make the object to move backward forward between the two waypoints he is now for example the last waypoint was 3 then the pingpong will be between waypoint index 3 and 4. And Wrap make it move in order from first ot last waypoint. This are the 3 modes I want to be active to use: Wrap , Random , PingPong for now. Maybe I should write all this in the question I tried to explain as much as I can :) – Daniel Lip Mar 19 '18 at 19:55
  • Did you write this code? I just want to knwo before making an answer – Programmer Mar 19 '18 at 20:16
  • @Programmer No it's not my own code. I just tried to add and change some stuff in it. – Daniel Lip Mar 19 '18 at 22:52
  • In that case I don't think that my answer will help since you may not be able to implement it. I do suggest you learn Unity coroutines and C#.That way, you know what your code can do and can actually extend it. `Mathf.PingPong` is simply used to move from one position to another. If you want to do something sequentially after that, you have to abandon `Mathf.PingPong` and use coroutine in a while loop especially when you said you want to wait for some time. That's much more better to implement what you are looking for. – Programmer Mar 20 '18 at 01:19
  • [This](https://stackoverflow.com/questions/36850253/move-gameobject-over-time/36851965#36851965) post shows how to move a gameobject to another positron with a coroutine. That should get you started. – Programmer Mar 20 '18 at 01:20

2 Answers2

1

As for pingpong logic, use Mathf.PingPong.

using UnityEngine;

public class PingPong : MonoBehaviour {
    public float k = 0f;
    public Vector3 WayPointA = new Vector3(100, 0, 100);
    public Vector3 WayPointB = new Vector3(0, 0, 0);
    void Update() {
        k = Mathf.PingPong(Time.time, 1);
        transform.position = Vector3.Lerp(WayPointA, WayPointB, k);
    }
}

See also Mathf.PingPong speed issue.

Update

But if I change the mode to PingPong in the middle while the game is running then the object should move between the current waypoint index and the next one. For example between index 4 and index 5.

I think you can dynamically change the way-point A and B. But the hardest part is how to maintain the current position while the object is still moving ping-pongly, namely, the object should move between waypoint index 0/1/2 and index 1/2/3 nonstop.

Here is the source code of Mathf.PingPong, hoping it helps.

public static float PingPong(float t, float length)
{
    t = Mathf.Repeat(t, length * 2f);
    return length - Mathf.Abs(t - length);
}
zwcloud
  • 4,546
  • 3
  • 40
  • 69
  • This is working as for PingPong logic I tried it on another script. Working great. I updated my question since I didnt explain fully what I wanted to do. If you can look maybe to my question now. I tried to implement the PingPong logic with my script but I'm not sure what to do next. – Daniel Lip Mar 19 '18 at 13:55
1

What I want to do is if I start the game in PingPong mode case then the object should move between waypoint index 0 and index 1 nonstop. But if I change the mode to PingPong in the middle while the game is running then the object should move between the current waypoint index and the next one. For example between index 4 and index 5.

I think what you're looking for is Vector2/3.lerp to move your object between 2 points constantly.

when you start the game you can set startMarker.position and endMarker.position (or wayPointA and wayPointB whatever you like to call it) to to [index] and [index+1], but swap out these values for whatever index you're currently at when you switch in the middle of the game (lerping should be done in the update method)

Remy
  • 4,843
  • 5
  • 30
  • 60