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 FallingRocketGames · Jan 16, 2019 at 02:55 AM · c#positionaimovetowardsnpc

Moving from one position to another

Hello I'm making a little AI behaviour with not much success, problem is I need my NPC to choose from several positions, move to one of them, then choose again and move to that one, and so on...

Problem is I haven't managed a way to make it move from the first position to the second one until the first one is reached and son on...

I decided the best way to do this was to put a line in update with Vector2.MoveTowards and feed it with the desired endPosition

     if (shouldLerp)
        {            
         npc.transform.position = Vector2.MoveTowards(transform.position, endPosition, moveSpeed * Time.deltaTime);
        }

      IEnumerator StopWandering()
 {
     yield return new WaitForSeconds(Random.Range(5f,10f));
     wandering = false;
     StopCoroutine(Wander());
     StartCoroutine(InitialMove());
     yield return null;
 }

 public IEnumerator InitialMove()
 {
     MoveToLadder();
     yield return new WaitUntil(() => Vector2.Distance(this.transform.position, endPosition) == 0);
     MoveToLevel();
     yield return new WaitUntil(() => Vector2.Distance(this.transform.position, endPosition) == 0);
     MoveToValve();
     yield return new WaitUntil(() => Vector2.Distance(this.transform.position, endPosition) == 0);        
     yield return null;
 }

 public Vector2 MoveToLadder()
 {        
     int numeroRandom = Random.Range(0, 100);
     if (numeroRandom % 2 == 0)
     {
         endPosition = ladderLeft.transform.position;
     }
     else endPosition = ladderRight.transform.position;        
             
     return endPosition;

 }

 public Vector2 MoveToLevel()
 {
     int numeroRandom = Random.Range(0, 100);        
     if (numeroRandom % 2 == 0 && this.transform.position.x < 0)
     {
         endPosition = level1Left.transform.position;
     }
     else if (numeroRandom % 2 != 0 && this.transform.position.x > 0)
     {
         endPosition = level1Right.transform.position;
     }
     else if (numeroRandom % 2 == 0 && this.transform.position.x < 0)
     {
         endPosition = level2Left.transform.position;
     }
     else if (numeroRandom % 2 != 0 && this.transform.position.x > 0)
     {
         endPosition = level2Right.transform.position;
     }        

     return endPosition;
 }
   ….

Sometimes it works some others it does not and I need to be foolproof, the game I'm trying to emulate is Cock In or Chicken Chase for the commodore, that's the movement I need for a similar scene. https://www.lemon64.com/?mainurl=https%3A//www.lemon64.com/games/details.php%3FID%3D3309

Comment
Add comment · Show 5
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 Klarzahs · Jan 16, 2019 at 10:17 AM 1
Share

Could you elaborate on what is not working? Does it stop at a position, does it not choose the next?

Two side notes: You don't want to compare Vector2.Distance == 0, as distance calculates a float subtraction. Due to the inherent inaccurateness of floats, this might never be exactly 0. You should check for a threshold ins$$anonymous$$d, something like Vector2.Distance < 0.001.

Also, why do you return your endPosition in your $$anonymous$$oveToXXX functions? You don't use the returned result. It gets updated as it is a class scope variable. They should be void functions ins$$anonymous$$d.

avatar image FallingRocketGames Klarzahs · Jan 16, 2019 at 11:55 AM 0
Share

Sorry the problem was that sometimes it reached the first position (1/3) some times it skipped over the last position (3/3)

avatar image DCordoba · Jan 16, 2019 at 10:42 AM 2
Share

as the code is designed, the npc will ever do the route ladder->level->valve, even if have a decision to stay and don't do the route, will go there to check... I think is better to do a random chooser between this options inside the main coroutine, but, before refactorize it, I think you need this code working, so, lets point some errors...

1) on the piece of code that you show, you never manage bool shouldLerp, if you dont assign it in other place, do it on Initial$$anonymous$$ove()

  public IEnumerator Initial$$anonymous$$ove()
  {
      $$anonymous$$oveToLadder();
      shouldLerp = true;
      yield return new WaitUntil(() => Vector2.Distance(this.transform.position, endPosition) == 0);
      shouldLerp = false;
      $$anonymous$$oveToLevel();
      shouldLerp = true;
      yield return new WaitUntil(() => Vector2.Distance(this.transform.position, endPosition) == 0);
      shouldLerp = false;
      $$anonymous$$oveToValve();
      shouldLerp = true;
      yield return new WaitUntil(() => Vector2.Distance(this.transform.position, endPosition) == 0);  
      shouldLerp = false;      
      yield return null;
  }

2) on $$anonymous$$oveToLevel() you are considering the height of each level, but, to go to the ladder you aren't. Your NPC will go to the same point ever, the top or the bottom of the ladder, or anywhere its centered... Because the ladder is vertical u can consider just the x axis to displacement...

  public Vector2 $$anonymous$$oveToLadder()
  {        
      int numeroRandom = Random.Range(0, 100);
      if (numeroRandom % 2 == 0)
      {
          endPosition = ladderLeft.transform.position;
      }
      else endPosition = ladderRight.transform.position;       
      //same level that the npc currently is     
      endPosition.y = npc.transform.position.y; 
      return endPosition;
  }
 

3) the if condition of line 42(and line 46) is the same as line 50(with line 54)... so line 50(and 54) never will be called, to evade this kind of errors, I suggest use nested ifs sometimes, just when is necessary ofc

  public Vector2 $$anonymous$$oveToLevel()
  {
      int numeroRandom = Random.Range(0, 100);        
      if (numeroRandom % 2 == 0 ){
          if (this.transform.position.x < 0)
          {
              endPosition = level1Left.transform.position;
          }
          else
          {
              endPosition = level1Right.transform.position;
          }
      }
      else 
      {
          if (this.transform.position.x < 0)
          {
              endPosition = level2Left.transform.position;
          }
          else
          {
              endPosition = level2Right.transform.position;
          }
      }         
      return endPosition;
  }
avatar image DCordoba · Jan 16, 2019 at 10:43 AM 1
Share

4) and last but not less important, float numbers arent precise so, get the exact 0.0f when u get the distance between two close points, are.. unusual

 public bool Reached(){
     //squared $$anonymous$$imiun distance to be considerer as "at the waypoint" (set is as public global?)
     float sqrt$$anonymous$$inDiff = 0.03f
     //use squared for faster calculation
     return (this.transform.position-endPosition).sqr$$anonymous$$agnitude < sqrt$$anonymous$$inDiff;
 }

and use it in the main coroutine

  public IEnumerator Initial$$anonymous$$ove()
  {
      $$anonymous$$oveToLadder();
      yield return new WaitUntil( Reached());
      $$anonymous$$oveToLevel();
      yield return new WaitUntil( Reached());
      $$anonymous$$oveToValve();
      yield return new WaitUntil( Reached());        
      yield return null;
  }

avatar image FallingRocketGames DCordoba · Jan 16, 2019 at 12:01 PM 0
Share

Thank you very much I'll try your advice to optimize the code a little bit indeed the problem was the distance between the 2 positions (current-target) the sprite not always reached a distance of 0 also changed some other details like defining the positions as vector2, I wrote them as "coordinates x, y" and worked very well there's the code as an answer, and altough it's working properly now any enhancement is very welcome.

3 Replies

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

Answer by FallingRocketGames · Jan 16, 2019 at 11:32 AM

I'm sure I over did it but this worked flawlessly:

            void Update () {
     if (shouldLerp)
     {            
         npc.transform.position = Vector2.MoveTowards(transform.position, endPosition, moveSpeed * Time.deltaTime);

         //Flip Sprite
         if (npc.transform.position.x > startPosition)
         {
             npc.transform.rotation = Quaternion.Euler(0, 0, 0);
         }

         if (npc.transform.position.x < startPosition)
         {
             npc.transform.rotation = Quaternion.Euler(0, 180, 0);
         }
     }

     currentPosition = npc.transform.position;
     startPosition = npc.transform.position.x;        
     
 }

 public IEnumerator Wander()
 {
     moveSpeed = 1;
     shouldLerp = true;
     wandering = true;
     while (wandering)
     {            
         endPosition = new Vector2(Random.Range(-6f, 6f), Random.Range(-3.5f, -2.5f));
         yield return new WaitForSeconds(Random.Range(5f, 8f));
         yield return null;
     }

 }

 IEnumerator StopWandering()
 {
     yield return new WaitForSeconds(Random.Range(5f,10f));
     wandering = false;
     StopCoroutine(Wander());
     shouldLerp = false;
     StartCoroutine(MoveToLadder());
     yield return null;
 }    

 public IEnumerator MoveToLadder()
 {
     moveSpeed = 1;
     shouldLerp = true;
     print(ladderLeft.transform.position.x + ladderLeft.transform.position.y);
     ladderReached = false;
     shouldLerp = false;
     int numeroRandom = Random.Range(0, 100);
     if (numeroRandom % 2 == 0)
     {
         endPosition = new Vector2(ladderLeft.transform.position.x, ladderLeft.transform.position.y);
     }
     else endPosition = new Vector2(ladderRight.transform.position.x, ladderRight.transform.position.y);

     while (!ladderReached)
     {
         shouldLerp = true;            
         if (Mathf.Approximately(currentPosition.x, endPosition.x) && Mathf.Approximately(currentPosition.y, endPosition.y))
         {
             ladderReached = true;
             shouldLerp = false;
             print("LLego a escalera");
             StartCoroutine(MoveToLevel());
         }
         yield return null;
     }

     yield return null;
 }

 public IEnumerator MoveToLevel()
 {
     //ladderReached = false;
     levelReached = false;
     shouldLerp = true;
     int numeroRandom = Random.Range(0, 100);        
     if (numeroRandom % 2 == 0 && this.transform.position.x < 0)
     {
         endPosition = new Vector2(level1Left.transform.position.x, level1Left.transform.position.y);
     }
     else if (numeroRandom % 2 != 0 && this.transform.position.x < 0)
     {
         endPosition = new Vector2(level2Left.transform.position.x, level2Left.transform.position.y);
     }
     else if (numeroRandom % 2 == 0 && this.transform.position.x > 0)
     {
         endPosition = new Vector2(level1Right.transform.position.x, level1Right.transform.position.y);
     }
     else if (numeroRandom % 2 != 0 && this.transform.position.x > 0)
     {
         endPosition = new Vector2(level2Right.transform.position.x, level2Right.transform.position.y);
     } 
     ….
Comment
Add comment · Show 2 · 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 xxmariofer · Jan 16, 2019 at 11:36 AM 1
Share

glad to hear that, also spriterenderer has a property called flip for doing the flip easier.

avatar image FallingRocketGames xxmariofer · Jan 16, 2019 at 12:04 PM 0
Share

I'll check it out didn't know about that one, thanks!

avatar image
1

Answer by xxmariofer · Jan 16, 2019 at 10:49 AM

I find your code a bit confusing and i would suggest a little refactor, but i am pretty sure your problem is with MoveToLevel mehod, else if 3 and 4 statement never enters. that means that some times the endposition will not be modified. one example when the endposition wont be modified is when numeroRandom % 2 == 0 && this.transform.position.x > 0

Try changing the on both 3 and 4 if, cant check the movetovalve method so cant make sure if there is something else wrong.

@DCordoba solution points the same but with code and better explained, i will leave this answer in case someone doesnt checks his comment.

Comment
Add comment · Show 2 · 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 FallingRocketGames · Jan 16, 2019 at 11:38 AM 0
Share

No, numeroRandom is just a way for me to say Random.Range[0,3] you know like when a number from 0 to 100 is even or odd but already found the problem, the sprites were scaled and never reached the absolute position so I couldn't compare the current position and the destination position so I used a loop with $$anonymous$$athf.Approximately also and haven't check if it worked in the previous way but changed: endPosition = level1Left.transform.position; to endPosition = new Vector2(level1Left.transform.position.x, level1Left.transform.position.y); as I said below I think I over didi it perhaps can be simplified but so far this worked without errors, thanks for time mate.

avatar image xxmariofer FallingRocketGames · Jan 16, 2019 at 12:12 PM 0
Share

You didnt understand my topic, i know that there is only posible to be even or odd but in the code you first saw you confused and else if 3 and 4 was never reachable. You changed it in your last anwser but you should check your first attempt.

avatar image
1

Answer by badadam · Jan 16, 2019 at 12:49 PM

At first add this script below to your player

 public class Player2D : MonoBehaviour {
 
      public int indexOfPoints = 0;
      public List<Transform> points;
      public Transform newPoint;
      public float speed = 10;    
     // Update is called once per frame
     void Update () {
           transform.position = Vector3.Lerp(transform.position, newPoint.position,Time.deltaTime*speed);
     }
 }

Create a empty objects to your destination points, add them collider(don't fortget to make them trigger) add the script below to all empty object at your destination points

 public class SpawnScript : MonoBehaviour {
      public Player2D player;
 
      private void OnTriggerEnter2D(Collider2D collision)
      {
           if (collision.gameObject.tag=="yourplayertag")
           {
                player.indexOfPoints++;
                player.newPoint = player.points[player.indexOfPoints];
           }
      }
 
 }

Drag all empty objects with trigger at the destnation points to "List points;" in the Player2D script you add to your player.

Comment
Add comment · Show 1 · 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 FallingRocketGames · Jan 17, 2019 at 04:55 AM 0
Share

This sounds promising and also tried an approach like this well not quite the same but had problems adding items to the list, my script considered adding (choosing) an item after being at a certain position in x or in y so but I can try this one later on, thank you very much

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

608 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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

AI Patrolling 1 Answer

Distribute terrain in zones 3 Answers

Operator `+' cannot be applied to operands of type `UnityEngine.Vector3' and `int' 1 Answer

Multiple Cars not working 1 Answer

How to make the Health bar on Enemys head not be in relation to Player(main) Camera? 2 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