Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 11 Next capture
2021 2022 2023
1 capture
11 Jun 22 - 11 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
1
Question by Sakuron · Jul 28, 2015 at 09:05 PM · scripting problemmovementaispeedwander

Wandering AI "ignores" speed

I´m trying to write a simple wandering AI for a 2D game. My code should generate a random position, move the object there and continue this. I know how it shoud be done, but my code is just not working.

Here is my code: using UnityEngine; using System.Collections;

 public class ZombieAI : MonoBehaviour {
 
     public float WalkSpeed;
     public float WalkRadius = 10;
     
     public bool Wandering;

     
     // Update is called once per frame
         void Update () {
         
     if (Wandering == true) {

         Vector2 WalkPoint = Random.insideUnitCircle * WalkRadius + new Vector2(transform.position.x,transform.position.y);
         Debug.Log(WalkPoint);
         while(new Vector2(transform.position.x, transform.position.y) != WalkPoint){

             transform.position = Vector3.MoveTowards (transform.position, WalkPoint, WalkSpeed / Time.deltaTime);
         }
     }
 }


When I run my game now, the Sprite realy fast from one point to another, like it´s teleporting. Even if i lower the speed value noting changes.

I think the proble is with the while-loop, but if I delete it the another problem shows up: The debug.Log returns normal coordinates, but the Sprite moves just very tiny very fast steps. It seems like the Sprite has not enough time to move to the target point ,instead it generates a new target every frame.

Please help me to figure out what´s wrong.

Thank you, TheSakuron

Comment
Add comment
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

2 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by Dave-Carlile · Jul 28, 2015 at 09:05 PM

You're correct that the while loop is the issue. You're generating the random point and moving the transform all the way to the target point in a single frame. And when you remove the while loop, you're generating the random point, moving one step towards it in a single frame, and then the next frame you're generating a new random point and moving one step towards that.

This kind of scenario comes up all of the time in game programming. You need to be able to do work that spans multiple frames. There are a number of ways you could handle this, but Coroutines are a decent fit here.

Something like this:

 void Start()
 {
   // start the coroutine to randomly move the zombie around
   StartCoroutine(ZombieMove());
 }


 IEnumerator ZombieMove()
 {
   // keep on running - you could replace "true" with a variable that would let you control when it stops
   while (true)
   {
      Vector2 WalkPoint = Random.insideUnitCircle * WalkRadius + 
                          new Vector2(transform.position.x,transform.position.y);
      Debug.Log(WalkPoint);

      while(new Vector2(transform.position.x, transform.position.y) != WalkPoint)
      {
          transform.position = Vector3.MoveTowards (transform.position, WalkPoint, WalkSpeed / Time.deltaTime);
          yield return null;  // wait for the next frame
      }
   }
 }

Oh, and I just noticed that you're comparing transform.position with WalkPoint. Since vectors use floating point, it's generally not a good idea to compare values for equality. Because of rounding errors and such it will be rare that they're exactly equal to another value. A good way to handle this is to compare distance from the target point. So replace the while (new Vector2... code with this:

 while (Vector2.Distance(new Vector2(transform.position.x, transform.position.y), 
         WalkPoint) > 0.1f)
 {
 }

This will keep looping until the transform moves within 0.1 units of the target. You may want a smaller values than 0.1, but that's something to play around with. Probably make it a public member variable so you can set it in the inspector.

Comment
Add comment · Show 6 · 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 Sakuron · Jul 29, 2015 at 09:06 AM 0
Share

Thank you for your fast answer and the hint with comparing vectors. I tried the code, but I´m afraid it´s not working. The sprite moves every frame to a new position again.

avatar image Dave-Carlile · Jul 29, 2015 at 12:58 PM 0
Share

What does your new code look like?

Actually, the value you're passing to $$anonymous$$oveTowards for maxDistanceDelta is potentially fairly large. What value are you using for WalkSpeed? If it's 1, dividing that by deltaTime, which would be 0.0167 at 60fps, will give you a value of 60 units. This means the position will change by 60 units each frame, which will cover the entire distance to your WalkPoint in a single frame.

You probably want WalkSpeed * Time.deltaTime ins$$anonymous$$d, which is what the documentation shows in the example code.

avatar image aceX · Jul 29, 2015 at 02:11 PM 0
Share

Guys stay away from while in Update ...

 if ((Vector2.Distance(new Vector2(transform.position.x, transform.position.y), WalkPoint) < 0.1f)
 {
     reached = true;
 }
 
 if (!reached)
 {
     transform.position = Vector3.$$anonymous$$oveTowards (transform.position, WalkPoint, WalkSpeed / Time.deltaTime);
 }
 
 else if (reached)
 {
     Vector2 WalkPoint = Random.insideUnitCircle * WalkRadius +  new Vector2(transform.position.x,transform.position.y);
     
     Debug.Log(WalkPoint);
     reached = false;
 }


^ Shove this in Update. Hope I helped ^^.

avatar image Dave-Carlile · Jul 29, 2015 at 02:24 PM 0
Share

@Acex, that is another way to do it (and I often do things that way), but it splits up the logic. The Coroutine allows for more intuitive code in this case.

avatar image Dave-Carlile · Jul 29, 2015 at 02:49 PM 1
Share

The Coroutine function is doing one task. It's randomly moving a zombie around, using pretty much the same code OP provided as an example. I don't think UA is really the place to $$anonymous$$ch coding philosophy. :)

Show more comments
avatar image
0

Answer by Wolfdog · Jul 29, 2015 at 02:12 PM

Try

 transform.position = Vector3.MoveTowards (transform.position, WalkPoint, WalkSpeed * Time.deltaTime);

instead.

Comment
Add comment · 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

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

3 People are following this question.

avatar image avatar image avatar image

Related Questions

How to Add Knockback Force Based on What Rotation it Came From 2 Answers

how to make 2D platformer AI for a skeleton 0 Answers

Do something every each multiple of 1000.. 2 Answers

NPC movement 1 Answer

Enemy AI Movement Decision Making 1 Answer


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