Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by GimLee · Sep 05, 2015 at 02:19 AM · movementvector2movetowards

Vector2.MoveTowards giving me a hard time

First of all, it's a 2d "sidescroller" game, where the player is moving towards the right at a constant speed.

I've created an ability for the player to move 5 seconds back in time with the player object.

It seemed to work pretty fine a while ago as far as I can remember. But after I've implemented a bunch of other stuff and came back to test this ability, it's causing problems (sometimes).

Let me explain the timetravelling feature For each 0.5sec I am adding the current position to a list. And through that list I can move to an earlier position, later on in the game. I am moving the object with the Vector2.MoveTowards() feature

The problem is Sometimes it moves REALLY slowly, and sometimes too fast. But sometimes it also feels correct, hard to tell anymore.

The code is as follows: I know it's a lot to take in, but I've cut away most of what seems unnecessary tor this question. I would advise your to start reading from the IENumerator Move() since that is most likely where the problem is.

     private PlayerController player;
     private bool cooldown;
     private List<Vector2> positionList = new List<Vector2>();
     
 
     void Awake()
     {
         player = GameObject.Find("Stickman").GetComponent<PlayerController>();
     }
 
     void Start()
     {
         StartCoroutine(Cooldown());
         StartCoroutine(Track());
     }

     public void Ability() // This begins the moving
     {        
         if (!cooldown)
         { 
             StartCoroutine(Move(positionList[positionList.Count - 10]));
             positionList.Clear();
         }
     }

     IEnumerator Track() // Adding the position to a list every 0.5sec
     {
         float timer = 0f;
         positionList.Add(player.transform.position);
         while (timer < 0.5f) 
         {
             timer += Time.deltaTime;
             yield return null;
         }     
         StartCoroutine(Track());
     }

     IEnumerator Move(Vector2 target)//Here the actual moving happens
     {
         StartCoroutine(Cooldown());
         bool reached = false;
         float step = 10f * Time.deltaTime;
         player.collider2D.enabled = false;
         
         while (!reached && !player.isDead)
         {
             player.rigidbody2D.isKinematic = true; // This is needed
             player.transform.position = Vector2.MoveTowards(player.transform.position, 
                                                             target, step); //Here it moves
 
             if (player.transform.position.x < target.x + 0.0001f) // That's good enough for me
             {
                 reached = true;
                 player.collider2D.enabled = true;
                 player.rigidbody2D.isKinematic = false;
             }
             yield return null;
         }     
     }

What is causing this problem here? Also feel free to point at any other stuff that seems "weird".

Thanks for reading!

Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image getyour411 · Sep 05, 2015 at 03:02 AM 0
Share

Track could be InvokeRepeating, which is a bit more performant than Coroutine. Cooldown isn't shown so assu$$anonymous$$g there's nothing in there that might cause this. What's your Frames Per Sec - if it's bouncing around cuz of other stuff, the "step" will be affected.

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Suddoha · Sep 05, 2015 at 03:44 AM

I'm not aware about the difference in speed, so I'll suggest to check two things for now:

Either you happen to get a "huge" difference in Time.deltaTime in line 42:

 float step = 10f * Time.deltaTime;

which is rather unlikely. Note, that this won't make your player move framerate-independantly as you calculate the step value once and use it for many frames. More to that later.

Or, what I suspect to be the reason and this is more likely, is that you probably do not disable the player's movement during the move-back-in-time-phase.


Off Topic due to request by OP

As you also asked for other things to be pointed out:

In order to move the player back in a framerate-independant manner, you should consider to calculate the value in each iteration again, just like for normal movements. As for that, remove the line above and change this line (48)

 player.transform.position = Vector2.MoveTowards(player.transform.position, target, step);

to:

 player.transform.position = Vector2.MoveTowards(player.transform.position, target, step*Time.deltaTime);

Next, your caching of the positions seems suboptimal if you only need the position that the player had 5 seconds ago (assuming you stick to the constant speed). You can calculate that on the fly (note, that this does not apply to the first 5 seconds):

 cachedPosition.x = (player.transform.position.x - playersMoveSpeedPerSecond * seconds)

If you still want to cache the last 10 positions (e.g. speed changes so that the formula above does not apply), think about an array that you iterate over and once you reach the last element, start at the beginning again and overwrite the obsolete entries. You won't have a continuously growing cache then.

And one more thing: is your cooldown supposed to start right over or do you wait in the cooldown coroutine until the player moved back and continues to play?

Comment
Add comment · Show 8 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image GimLee · Sep 05, 2015 at 04:06 AM 0
Share

$$anonymous$$any thanks for this answer.

I have tried setting the player's speed to 0f during the time jump, but it is still moving though, but with a 0f speed. The problem still occurs, don't know if disabling the movement tottaly will help.

But I think the problem might be that I only calculated step once. So doing it in the loop seems to have fixed the problem. I'll test it some more tomorrow, and then I'll come back to accept your answer.

In response to the caching. Yes there will be speed changes, jumping and stuff that will make it impossible for me to calculate the previous position.

But the other thing you're explaining, isn't that kind of what I'm already doing? I'm storing positions in a list, whenever the time-ability is used, I go 10steps back, and then I .clear() it.

And yes the cooldown is supposed to be triggered at once.

Again, thank you very much for this delicate answer!

avatar image getyour411 · Sep 05, 2015 at 06:34 AM 0
Share

If you are using this as an opportunity to learn some C#, take a look at the Queue collection ins$$anonymous$$d of the List. It's not discussed too often but it has its uses.

avatar image Suddoha · Sep 05, 2015 at 12:29 PM 0
Share

@GimLee Yes you're kind of doing that already, but your list grows larger as time continues until you clear it. I'm not sure what's your cooldown, but imagine someone waits several $$anonymous$$utes to use the ability: you'd currently store 120 positions per $$anonymous$$ute. Let your player just wait 3 $$anonymous$$utes and you'll already have 360 positions from which you only need the 350th.

Thus, you could have an array of 10 positions and once you filled the last element with the recent position, you'll start with the first one again as it's no longer needed for your time reset.

As for the cooldown i meant the following: Imagine you've got a cooldown of 30 seconds. In the beginning, you'll have a total cooldown of 30 seconds, once used the ability, you'll have 'cooldown - ability time' as cooldown as you start the cooldown routine immediately when you use the ability - effectively you'll only have 25 seconds because the player will be moved back in the first 5 seconds. $$anonymous$$aybe you've addressed this by waiting in the cooldown coroutine until the reset time is over, but i just wanted to point this out as a possible small mistake.

avatar image GimLee · Sep 05, 2015 at 02:15 PM 0
Share

@Suddoha I don't know the "cost" of storing values, but I was wondering, wont it cost more performance to remove the entries in the list frequently, rather than leave them be.

avatar image GimLee · Sep 05, 2015 at 02:16 PM 0
Share

Ah, I think I get your point now. Thanks for the tip.

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

28 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Moving an UI element from point A to point B 1 Answer

Making a character move automatically in one direction. 2 Answers

MoveTowards is not working with RectTransform component 0 Answers

Push an object opposite direction of mouse position 0 Answers

How to know if 2D gameobject is moving left or right? 3 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges