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
0
Question by jonmeldrum · Aug 08, 2015 at 12:29 PM · playerenemychase

Getting the player to retreat a certain distance from the player

Hi all,

This problem has been plaguing me for about 2 weeks now and I cant seem to crack it.

I have a simple state machine for the enemy. The enemy chases the player until the player reaches a light source. Once the player reaches a light source, the enemy retreats. This all works except i want the enemy to stop retreating a certain distance from the player.

At the moment, the enemy is retreating indefinitely until the player leaves the light in which the enemy once again, gives chase.

As you can see in the Retreat function below, I have tried a few methods but none seem to do exactly what I want.

Pastie here or code below: http://pastie.org/private/tjfb3r1xzemmm05dele0wa

Thanks for the help in advance, I really appreciate it.

using UnityEngine; using System.Collections;

public class DarkChase : MonoBehaviour {

 public float maxAdvanceSpeedY = 1.0f;
 public float maxAdvanceSpeedX = 1.0f;
 public float maxRetreatSpeedY = 1.0f;
 public float maxRetreatSpeedX = 1.0f;
 public float minDistance = 5.0f;
 //public float maxRetreatDistance = 100.0f;
 //public float maxDistance = -10.0f;

 public GameObject Player;
 public GameObject theDark;
 public PlayerControl thePlayerScript;
 //public Transform Target;
 
 // Use this for initialization
 void Start () {
 
     Player = GameObject.FindGameObjectWithTag("Player");
     thePlayerScript = thePlayerScript.GetComponent<PlayerControl>();

 }
 
 // Update is called once per frame
 void Update () {

     if (PlayerControl.inLight == false) 
         Advance();
     else if (PlayerControl.inLight == true)
         Retreat();

 }

 public void Advance () {

     print ("Advance");

     Vector3 playerPosition = Player.transform.position;
     Vector3 darkPosition = transform.position;

     Vector3 difference = darkPosition - playerPosition;
     difference.Normalize();

     transform.Translate (
         (difference.x * -maxAdvanceSpeedX), (difference.y * -maxAdvanceSpeedY), (difference.z * -1));

 }

 public void Retreat () {

     print ("Retreat"); 

     Vector3 playerPosition = Player.transform.position;
     Vector3 darkPosition = transform.position;
     
     Vector3 difference = darkPosition + playerPosition;
     difference.Normalize();
     
     transform.Translate (
         (difference.x * +maxRetreatSpeedX), (difference.y * +maxRetreatSpeedY), (difference.z * +1));
         
     float dist = Vector3.Distance(playerPosition, darkPosition);
     if (Vector3.Distance (playerPosition, darkPosition) <= minDistance)
         Debug.DrawLine (playerPosition, darkPosition, Color.yellow);
         print ("Distance to player: " + dist);

     //darkPosition = Vector2.MoveTowards (transform.position, playerPosition, maxAdvanceSpeedX * Time.deltaTime);

     //transform.Translate (
             //(maxDistance), (0), (0));

     
     //Vector3 maxDistance = Vector3.Distance (playerPosition, darkPosition);
         //if (maxDistance >= maxRetreatDistance)
             //.Translate (
                 //(difference.x - maxRetreatDistance), (difference.y - 0.01), (difference.z - 0.01));
 }

}

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 · Aug 08, 2015 at 02:21 PM 0
Share

I'm sure it's messed up with all the tweak attempts; at least put it back to form like

 Retreat()
 float dist = (the Distance calc)
 
 Debug.Log("Dist is: " + dist);
 
 if(dist <= $$anonymous$$Distance) {
 // do stuff, Translate, etc
 }

and show the dist debug; if Enemy is still retreating once dist fails check, there's something else.

2 Replies

· Add your reply
  • Sort: 
avatar image
0
Wiki

Answer by DwaynePritchett · Aug 08, 2015 at 02:35 PM

 I would add a third "state" idle. You might even choose to make an Enum for the states. But, to fix this, go into update and change the retreat conditions.


  void Update () {
  
      if (PlayerControl.inLight == false && (Vector3.Distance(playerPos,transform.pos)> minDistance)) {
             Advance();
          }
      else if (PlayerControl.inLight == true){
         if(Vector3.Distance(playerPos,transform.pos) < maxRetreatDistance){
             Retreat();
         }

     }else{
          Idle();
          //Idle = Rotate toward character and don't move? Or whatever you want.
     }

  }
  
Comment
Add comment · Show 3 · 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 getyour411 · Aug 08, 2015 at 02:45 PM 0
Share

While there's nothing wrong with this, I also don't see anything right about it in the sense that his current Update() looks fine to me; the state is either true or false and it's being checked appropriately. Update() is not going to call Retreat() if (!inLight)

avatar image DwaynePritchett · Aug 08, 2015 at 03:28 PM 0
Share

He says it "$$anonymous$$eeps" retreating. So having a 2nd check against the distance should stop the enemy from continuing to retreat past his maxRetreatDistance. And, the purpose of an idle state is just to have an explicit situation for when the enemy is neither advancing or retreating. Perhaps, if it goes idle for X amount of time, he wants to to lose aggro all together etc. Anyways... that is the logic behind it.

avatar image jonmeldrum · Aug 09, 2015 at 02:46 AM 0
Share

Sorry for the confusion. Yes the code I supplied currently works as it should. When the player is in a safe point the enemy retreats. The problem is that a player can sit in a safe area indefinitely and wait for the enemy to retreat far enough away that the player can just run through the rest of the level without danger.

I added a quick check as suggested by DwaynePritchett and this has worked without the Idle state. Problem now is that it is constantly checking and translating the advance or retreat method.

Ive been thinking that I would like the enemy to retreat back to the edge of the camera view. and then Idle.

At the moment, im just using public variables to dictate where the enemy stops and advance.

Vector3 playerPosition = Player.transform.position; Vector3 darkPosition = transform.position;

     if (PlayerControl.inLight == false && (Vector3.Distance(playerPosition, darkPosition) > $$anonymous$$Distance)) {
         Advance();
     }
         else if (PlayerControl.inLight == true) {
             if (Vector3.Distance(playerPosition, darkPosition) < maxRetreatDistance) {
                 Retreat();
      }

I think my main problem is I dont know how to get him to a point and then just stop the translate.

Thats why Im thinking that as long as the enemy retreats back to the camera edge and then goes idle, this would work best.

avatar image
0

Answer by sparkzbarca · Aug 09, 2015 at 03:09 AM

if your saying you dont like it running endless checks in that you can actually use trigger boxes around lights and OnTriggerEnter push bots back, OnTriggerExit send in the hordes.

The thing is if you do this you can actually sleep the monster and then use OnTriggerExit to wake it.

Up to you though.

if your saying the issue is as far as "get him to a point and then just stop the translate"

if your saying you dont know how to because it doesn't ever quite arrive. mathf.approximately is your friend. instead of saying if position == X do if mathf.approximately(X)

Approx allows you to be slightly innacurate to account for the fact that vector3 is a floating point, suffers floating point inaccuracies and so it lets you say if your really close thats good engouh.

alternatly just pick a point and go if (vector3.distance(monster.position, point)) < .1f i'm within a tenth of a meter to my idle area, thats fine, lets start idling.

if your saying you dont know how to pick a point.

cast a ray from monster to player and or light source.

rays actually have a method called ray.getpoint(float distance)

thats gets you the world point X distance along the line.

So casting a ray from monster to player and ray.getpoint(10); would get you the point in the world 10 meters from the monster in the direction of the player.

so say if you set origin to player, direction as player.position - light.position so you have a line starting at the player but traveling in the OPPOSITE direction of the light. and use getpoint(10).

you'll now have the point closest to the light within 10 feet of the player kind of thing.

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

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

Enemy raycast chase player 0 Answers

How to stop the enemy from jumping when chasing the player ? 1 Answer

Enemy's NavMesh not working 2 Answers

enemy targeting player in different scene 1 Answer

Teleporting Script Doesn't Work With Anything But The Player 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