Search Unity

Moving an object back and forth on a single axis automatically

Discussion in 'Scripting' started by Jofo111, Mar 19, 2014.

Thread Status:
Not open for further replies.
  1. Jofo111

    Jofo111

    Joined:
    Feb 26, 2014
    Posts:
    1
    Hi All,

    As you will probably tell by my following question I'm very new to Scripting and C#.
    What I'm trying to do is make a gameobject (so for example in this case an enemy), move automatically on a particular axis (in this case the x), back and forth. So for example, it will move 3 along the x axis then back to its starting position and continually do that.
    I have found the following script for a similar idea using Coroutines:

    Code (csharp):
    1. public Vector3 pointB;
    2.    
    3.     IEnumerator Start () {
    4.         Vector3 pointA = transform.position;
    5.         while (true) {
    6.             yield return StartCoroutine(MoveObject(transform, pointA, pointB, 3));
    7.             yield return StartCoroutine(MoveObject(transform, pointB, pointA, 3));
    8.         }
    9.     }
    10.    
    11.     IEnumerator MoveObject (Transform thisTransform, Vector3 startPos, Vector3 endPos, float time) {
    12.         float i = 0.0f;
    13.         float rate = 1.0f / time;
    14.         while (i < 1.0f) {
    15.             i += Time.deltaTime * rate;
    16.             thisTransform.position = Vector3.Lerp(startPos, endPos, i);
    17.             yield return null;
    18.         }
    19.     }
    20.  
    while this works, the problem is that it needs to have a Vector3 set in the Inspector for each gameobject. I want to be able to save a prefab of the enemy then spawn it anywhere and it keeps the same logic without putting in a new vector for each one.

    What I have tried is giving pointB a set value, such as:
    pointB = new Vector3 (transform.position.x + 3, transform.position.y, transform.position.z)

    however, that just threw up a lot of errors.

    Any help will be appreciated, thank you very much.
     
  2. rrh

    rrh

    Joined:
    Jul 12, 2012
    Posts:
    331
    What sort of errors did that give you?
     
  3. parandham03

    parandham03

    Joined:
    May 2, 2012
    Posts:
    174
    try this

    Code (csharp):
    1. public float min=2f;
    2.     public float max=3f;
    3.     // Use this for initialization
    4.     void Start () {
    5.        
    6.         min=transform.position.x;
    7.         max=transform.position.x+3;
    8.    
    9.     }
    10.    
    11.     // Update is called once per frame
    12.     void Update () {
    13.        
    14.        
    15.         transform.position =new Vector3(Mathf.PingPong(Time.time*2,max-min)+min, transform.position.y, transform.position.z);
    16.        
    17.     }
     
  4. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    You could do something like (Using C#):

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class MoveTest : MonoBehaviour
    6. {
    7.     public Vector3 pointB;
    8.    
    9.     IEnumerator Start()
    10.     {
    11.         var pointA = transform.position;
    12.         while(true)
    13.         {
    14.             yield return StartCoroutine(MoveObject(transform, pointA, pointB, 3.0f));
    15.             yield return StartCoroutine(MoveObject(transform, pointB, pointA, 3.0f));
    16.         }
    17.     }
    18.    
    19.     IEnumerator MoveObject(Transform thisTransform, Vector3 startPos, Vector3 endPos, float time)
    20.     {
    21.         var i= 0.0f;
    22.         var rate= 1.0f/time;
    23.         while(i < 1.0f)
    24.         {
    25.             i += Time.deltaTime * rate;
    26.             thisTransform.position = Vector3.Lerp(startPos, endPos, i);
    27.             yield return null;
    28.         }
    29.     }
    30. }
    31.  
    Sourced from some unity answers thread, then tested in Unity. Works well.

    EDIT: for more complex movement, and examples, and lots more, check out "tweening" and some of the packages available, like hotween, iTween, or leanTween to mention a few. They provide lots of good info in this area of simple movement of gameobjects with little to no interaction. Good luck!
     
    Last edited: Mar 19, 2014
    tiagomatosmendes and nicksc777 like this.
  5. OceanBlue

    OceanBlue

    Joined:
    May 2, 2013
    Posts:
    251

    Var isn't C#
     
  6. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    Have you tested it yet? :p

    I didn't write the script like I said it came from some page I googled, but I had thought it worked...

    if you need to you can make floats be float, ints be int, and so on.

    EDIT: just to make sure it worked, I tested it again:

     
    Last edited: Dec 9, 2014
  7. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Yes it is.

    --Eric
     
  8. spycarrot

    spycarrot

    Joined:
    Feb 20, 2015
    Posts:
    8
  9. nbg_yalta

    nbg_yalta

    Joined:
    Oct 3, 2012
    Posts:
    378
    How to make this not looping?
     
  10. landon912

    landon912

    Joined:
    Nov 8, 2011
    Posts:
    1,579
    Why do people always overlook the naturally oscillating mathematical functions?

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. public class OccilatingPosition : MonoBehaviour
    4.     {
    5.      public enum OccilationFuntion { Sine, Cosine }
    6.      public void Start ()
    7.      {
    8.          //to start at zero
    9.          StartCoroutine (Oscillate (OccilationFuntion.Sine, 1f));
    10.          //to start at scalar value
    11.          //StartCoroutine (Oscillate (OccilationFuntion.Cosine, 1f));
    12.      }
    13.  
    14.      private IEnumerator Oscillate (OccilationFuntion method, float scalar)
    15.      {
    16.          while (true)
    17.          {
    18.              if (method == OccilationFuntion.Sine)
    19.              {
    20.                  transform.position = new Vector3 (Mathf.Sin (Time.time) * scalar, 0, 0);
    21.              }
    22.              else if (method == OccilationFuntion.Cosine)
    23.              {
    24.                  transform.position = new Vector3(Mathf.Cos(Time.time) * scalar, 0, 0);
    25.              }
    26.              yield return new WaitForEndOfFrame ();
    27.          }
    28.      }
    29. }
    30.  
    @nbg_yalta simply stop the coroutine whenever you'd like using:
    Code (CSharp):
    1. StopCoroutine(Oscillate());
    .
     
    mdYeet, Gumpy54, jurvanek and 3 others like this.
  11. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Use yield return null instead of yield return new WaitForEndOfFrame. (So you don't create new objects.) Anyway it's possible people just want stuff to pingpong without the slowdown/speedup that you get with sine.

    --Eric
     
    tkamruzzaman likes this.
  12. landon912

    landon912

    Joined:
    Nov 8, 2011
    Posts:
    1,579
    That's true, but it is often desired. I usually create those objects in an outer scope, but use this for simplicity as its what is seen in Unity's tutorials.
     
  13. nbmangan

    nbmangan

    Joined:
    Feb 1, 2018
    Posts:
    1

    is there a way to update the Point A and B so that the enemies are ping ponging to different locations all the time?
     
  14. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    I think perhaps you should open a new thread or even a unity answers post, because its difficult to tell what you mean without a detailed explanation, and also this thread is pretty old.
     
  15. kylejramstad

    kylejramstad

    Joined:
    Jul 1, 2019
    Posts:
    1
    I'm sure no one is still looking at this, but just in case:

    Here is code for a Saw (circle) that I have going back and forth.
    It exposes a speed and distance for your GameObject as well.
    I also have it spinning because it was for a saw.
    I used Rigidbody2D since I have it using a collider as well.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class saw : MonoBehaviour
    6. {
    7.  
    8.     public float distance;
    9.     public float spinSpeed;
    10.     public float linearSpeed;
    11.     private Rigidbody2D rgb2d;
    12.     private float startPosition;
    13.  
    14.     // Start is called before the first frame update
    15.     void Start()
    16.     {
    17.         rgb2d = GetComponent<Rigidbody2D>();
    18.         startPosition = rgb2d.position.x;
    19.     }
    20.  
    21.     private void FixedUpdate()
    22.     {
    23.         rgb2d.SetRotation(rgb2d.rotation + spinSpeed * Time.fixedDeltaTime);
    24.         rgb2d.MovePosition(new Vector2((Mathf.Sin((2 * Mathf.PI * (Time.time*linearSpeed/distance)) - (Mathf.PI / 2)) * (distance/2) + (distance/2))+startPosition,rgb2d.position.y));
    25.     }
    26. }
     
  16. mattood

    mattood

    Joined:
    May 15, 2014
    Posts:
    1

    I looked at it :)
     
    benhcat likes this.
  17. TheBloodyButcher

    TheBloodyButcher

    Joined:
    May 20, 2017
    Posts:
    3

    yup I looked at it too :)
     
  18. nicksc777

    nicksc777

    Joined:
    Mar 28, 2020
    Posts:
    1
     
  19. AYHossGames

    AYHossGames

    Joined:
    May 4, 2020
    Posts:
    4
    Code (csharp):
    1.  
    2. public class BlockMoveUni : MonoBehaviour
    3. {
    4.     [SerializeField]
    5.     public Vector3 targetPos1;
    6.     [SerializeField]
    7.     public Vector3 targetPos2;
    8.     [SerializeField]
    9.     public float speed = 1f;
    10.     public bool canMove;
    11.     public bool firstMove;
    12.     void Start()
    13.     {
    14.        
    15.         firstMove = true;
    16.        
    17.     }
    18.     void Update()
    19.     {
    20.         if(transform.position == targetPos1)
    21.         {
    22.             firstMove = false;
    23.         }
    24.         if (transform.position == targetPos2)
    25.         {
    26.             firstMove = true;
    27.         }
    28.         if (canMove)
    29.         {
    30.             if (firstMove)
    31.             {
    32.                 transform.position = Vector3.MoveTowards(transform.position, targetPos1, speed* Time.deltaTime);
    33.             }
    34.             else
    35.             {
    36.                 transform.position = Vector3.MoveTowards(transform.position, targetPos2, speed* Time.deltaTime);
    37.             }
    38.         }
    39.        
    40.     }
    41. }
    42.  
    Hi Guys, I know the question is old but being as a beginner I have made an extremely easy to follow code that can be plugged into any OBJ and adjust purely through Unity. Probably not very optimised but found it easy to implement. Please follow instruction under to apply. If you are more experienced or can see any glaring mistake or ways to optimise it a lot more, please let me know :)
    1. Add script to Object you want to move.
    2.Set Target1 as first destination
    3. Set Target2 as second destination/starting point if you want to move back where it started.
    4. select canMove as true if want to move straight away or leave false if you want to activate by a trigger.
    5. change speed via Unity.
    This should allow you to use on all moving Objects in scene or game without having to adjust code.
     
    G414XY, roopesh23 and anorak8 like this.
  20. dahiyabunty1

    dahiyabunty1

    Joined:
    Jan 22, 2020
    Posts:
    68
    you can use animator to move back forth without single line of coding
     
    Kurt-Dekker likes this.
  21. leone1

    leone1

    Joined:
    Jun 18, 2021
    Posts:
    2
    how do you do this on the z axis
     
    Joshsonsstudio likes this.
  22. mdYeet

    mdYeet

    Joined:
    Oct 21, 2020
    Posts:
    22
    transform.position =new Vector3(Mathf.PingPong(Time.time*2,max-min)+min, transform.position.y, transform.position.z)

    new Vector3(position.x, position.y, position.z) ...... Look at where the PingPong is in the original code. The position.x

    Simply put the Mathf.PingPong in the transform.position.z ... Or whichever position on the x,y,z Vector3 you so desire.
     
  23. Sphyco

    Sphyco

    Joined:
    Oct 3, 2021
    Posts:
    1
    Thank you so much
     
    G414XY likes this.
Thread Status:
Not open for further replies.