Script 1:

public class randomizer : MonoBehaviour { public void fear() { int rand = Random.Range(0, 100); if (rand<55){ Debug.Log("нападают"); } if (rand >= 55) { Debug.Log("убегают"); } } } 

Script 2:

 public class enemy : MonoBehaviour { private Vector3 Player; private Vector2 PlayerDirection; private float Xdif; private float Ydif; private float speed; private float distance; private bool stun; private float stuntime; // Use this for initialization void Start () { stuntime = 0; stun = false; speed = 6; } // Update is called once per frame public void Update () { distance = Vector2.Distance (Player, transform.position); Player = GameObject.Find ("Player").transform.position; if (stuntime > 0) { stuntime -=Time.deltaTime; } else { stun = false; } if (distance < 25 & !stun) { Xdif = Player.x - transform.position.x; Ydif = Player.y - transform.position.y; PlayerDirection = new Vector2 (Xdif, Ydif); GetComponent<Rigidbody2D>().AddForce (PlayerDirection.normalized * speed); } } void OnCollisionEnter2D(Collision2D Playerhit){ if (Playerhit.gameObject.tag == "Player") { stun = true; stuntime = 1; } } } 

Script 3:

 public class EnemyRun : MonoBehaviour { public AnimationClip a_idle; public AnimationClip a_walk; public AnimationClip a_run; public AnimationClip a_jump; //public Transform target; public Vector3 target; public int moveSpeed; public float rotationSpeed; float corutTimer; float dist; float rRot; Ray ray, rayUp, rayDown, rayDownLeft, rayDownRight, rayRight, rayLeft, rayRun; RaycastHit hit, hitDown, hitRight, hitLeft; Vector3 p, p1; bool startCast; bool turnedAccess; int tempTurn; Animation anim; private Transform myTrans; void Awake() { turnedAccess = true; myTrans = transform; moveSpeed = Mathf.RoundToInt(Random.Range(6,8.5f)); rotationSpeed = moveSpeed * 0.5f; corutTimer = 0.3f/moveSpeed; startCast = true; anim = this.GetComponent<Animation>(); } void Start () { GameObject go = GameObject.FindGameObjectWithTag("Player"); //target = go.transform; StartCoroutine(OrientationEnemy()); } // Update is called once per frame void Update () { RunFromPlayer (); } void RunFromPlayer() { if (target != Vector3.zero) { if (dist > 2) { if (Physics.Raycast(rayDown, out hitDown, 2)){ if (turnedAccess) { Quaternion rawRotation = Quaternion.Slerp(myTrans.rotation, Quaternion.LookRotation(target - myTrans.position), rotationSpeed*Time.deltaTime); myTrans.rotation = new Quaternion(0, rawRotation.y, 0, rawRotation.w); } myTrans.position += myTrans.forward * moveSpeed * Time.deltaTime; }else { myTrans.rotation *= Quaternion.Euler(new Vector3(0, -45, 0)); } } else { anim.Play (a_idle.name); } }else anim.Play (a_idle.name); } IEnumerator OrientationEnemy() { while (startCast){ yield return new WaitForSeconds(corutTimer); //проверяем дистанцию до цели if (target !=null) { dist = Vector3.Distance(myTrans.position, target); } //проверяем наличие поверхности под телом rayDown = new Ray (transform.position, transform.forward + Vector3.down); rayDownLeft = new Ray (transform.position, -transform.right + Vector3.down); rayDownRight = new Ray (transform.position, transform.right + Vector3.down); //если дистанция до цели больше и есть поверхность делаем проверки для определения непроходимых мест if (dist > 2 && Physics.Raycast(rayDown, out hitDown, 2)) { //луч вперед из центра ray = new Ray(transform.position, transform.forward); //луч около головы rayUp = new Ray (transform.position + Vector3.up*0.5f, transform.forward); //проверяем левую и правую сторону rayRight = new Ray (transform.position + Vector3.down * 0.5f, transform.right + Vector3.up*0.5f); rayLeft = new Ray (transform.position + Vector3.down * 0.5f, -transform.right + Vector3.up*0.5f); if (Physics.Raycast(rayRight, out hitRight, 2) && hitRight.collider.name !="Enemy" || Physics.Raycast(rayLeft, out hitLeft, 2) && hitLeft.collider.name !="Enemy") { turnedAccess = false; } else { if (Physics.Raycast(rayDownLeft, out hitDown, 2) && Physics.Raycast(rayDownRight, out hitDown, 2)) turnedAccess = true; } if ((Physics.Raycast(ray, out hit, 2) && hit.collider.name == "Collider") || (Physics.Raycast(rayUp, out hit, 2) && hit.collider.name !="Enemy")) { tempTurn = Mathf.RoundToInt(Random.Range(0,1.9f)); if (tempTurn == 0) myTrans.rotation *= Quaternion.Euler(new Vector3(0, -45, 0)); else myTrans.rotation *= Quaternion.Euler(new Vector3(0, 45, 0)); /*if (hitRight.collider != null && hitLeft.collider == null) { myTrans.rotation *= Quaternion.Euler(new Vector3(0, 45, 0)); } else if (hitLeft.collider != null && hitRight.collider == null) { myTrans.rotation *= Quaternion.Euler(new Vector3(0, -45, 0)); } else { tempTurn = Mathf.RoundToInt(Random.Range(0,1.9f)); if (tempTurn == 0) myTrans.rotation *= Quaternion.Euler(new Vector3(0, -45, 0)); else myTrans.rotation *= Quaternion.Euler(new Vector3(0, 45, 0)); }*/ } //отрисовка линий для теста Debug.DrawRay(transform.position + Vector3.up*0.5f, transform.forward); Debug.DrawRay(transform.position, transform.forward); Debug.DrawRay(transform.position, transform.forward*2 + Vector3.down*2); Debug.DrawRay(transform.position + Vector3.down * 0.5f, transform.right + Vector3.up*0.5f); Debug.DrawRay(transform.position + Vector3.down * 0.5f, -transform.right + Vector3.up*0.5f); if (target != Vector3.zero) anim.Play(a_run.name); } } } void OnTriggerEnter(Collider other) { if (other.name == "Player") { rRot = Random.Range (0, 270); //рандомный кгол поворота для убегания myTrans.rotation *= Quaternion.Euler(new Vector3(0, rRot, 0)); rayRun = new Ray (myTrans.position, transform.forward*30); target = rayRun.GetPoint(30); //точка в качестве таргета } } } 

In 1 script, if (rand<55) , script 2 should be executed, and if (rand>=55) script 3 should be executed. This should be applied to all objects with the "enemy" tag. How can this be implemented?

Attempt 1:

 public class randomizer : MonoBehaviour { public enemy enemyRun; private float Xdif; private float Ydif; private Vector3 Player; public void fear() { int rand = Random.Range(0, 100); if (rand<55){ enemyRun.Update(); Debug.Log("нападают"); } if (rand >= 55) { Xdif = Player.x + transform.position.x; Ydif = Player.y + transform.position.y; enemyRun.Update(); Debug.Log("убегают"); } } } 

Whether prompt it will turn out to make something efficient from this? Currently not working. Those. now the enemy is always attacking. When you press the button, the log goes different (attack / run away), but the enemy does not change the movement.

  • 2d or 3d game? It could be done in general like this: for an object with script No. 1, hang up a trigger ... width / diameter (depending on the type of collider) to be equal to the value specified in this script .... in this case 55 .. all ..in enemy objects, in fact, script No. 3 will always be included .... and the reaction will occur in OnTriggerEnter and OnTriggerExit dude with script No. OnTriggerEnter if if (collider.CompareTag("Enemy")) - enable the second script, turn off the third .... in OnTriggerExit other way around if (collider.CompareTag("Enemy")) turn off the second turn on the third - Alex Shimansky
  • @ Alexey Shimansky in general is a player’s skill and it hangs on the button. In fact, enemies always attack if they approach a certain distance, i.e. always 2 script works. And if you press the "scare" button, then with some probability the enemy will be frightened and run away ie. script 3 will work. Apparently this is not exactly what is needed. - MikhailChu
  • And, well, if there is something on the button - then yes. I just thought maybe this very fear() somewhere in Update() is listed ..... you can then look at the answer given below - Alexey Shimansky

1 answer 1

I would make another EnemyController script in which we store references to both scripts 2 and 3. Create a method

 public void FearActivate(bool active) { enemy.enabled = !active; enemyRun.enabled = active; } 

Add a static variable with a list of enemies to the script. public static List<EnemyController> enemies . Now, when creating an enemy (well, or as necessary) through EnemyController , EnemyController add / delete in script 1 to the list of enemies. It remains in the script 1 in fear to make a detour throughout the cycle of registered enemies and call the FearActivate(rand>=55) method FearActivate(rand>=55)

  • And if enemies 1.000? 10.000? 100,000? Do you think it would be expedient to cycle all enemies? - Alexey Shimansky
  • While it is not very clear what you exactly want: Running a script from another class made a link and called a method .. You yourself wrote: Применяться это должно ко всем объектам с тегом "enemy". Traversing the list will in any case be cheaper than searching all objects by tags on the scene. If you need the enemies to be grouped according to some criterion (distance to the target, type of enemies, etc.) then you need to of course implement other options. Perhaps it is worth then to focus on the use of events. An example went into the range of the tower and subscribed to the event a wave of fear from this tower, etc. - KingPeas
  • Personally, I don’t care about all this, because I do not need anything - Alexey Shimansky
  • @KingPeas is the ability to "scare the enemy", the skill is called with a button. Enemies (enemy) if they are approached for a certain distance, they attack the player, but when this skill is applied, the likelihood that the enemy can become frightened and run away is triggered - MikhailChu
  • Well, then we make a collider trigger on the player and when entering the player zone the controller will trigger one of the behaviors. Then of course the list is not needed, since each enemy has its own behavior. - KingPeas