0

Hey Working on something new here. I have an enemy for a game I'm coding. I'm trying to modularize by stuff more so I have an overall AIMovement.cs file that handles well... movement. I also have AIUtility.cs which handles any randomization of the movement such that the parent makes simple calls and the utility takes care of most things concerning IEnumerators. So AIUtility makes use of System.Random to generate most of its wait times with maxes given by the editor. So at Start() I generate the random seed for waiting. The problem is that when the game starts I run a spawner script that basically spawns a random number of prefabs at the start of the game mostly used for testing at this point though I'm sure it will come in handy later. Its just that all my enemies behave in the exact same way! Now some enemies are originally made to teleport a few times (at random) and then self destruct. Its kind of cool to have it all happen at once and turn the game into a mini bullet hell but for standard enemies it totally sucks! How can I get this to stop? Here are the scripts. I did pull out some code that shouldn't change the problem as these scripts are made for more than one type of mob. Also a few things have not been implemented yet. If I need to restructure I'll cry, but I'll still do it. Any help is appreciated.
Spawner:

using UnityEngine;

public class SpawnerScript : MonoBehaviour
{
    [SerializeField] private GameObject gameObj;
    private readonly System.Random _random = new System.Random();
    private int numOfSpawns;
    private Vector3[] spawnLocations;
    private void Start() {
        numOfSpawns =  _random.Next(3, 7);
        spawnLocations = new Vector3[numOfSpawns];
        for(int i = 0; i < numOfSpawns; i++){
            spawnLocations[i] = Camera.main.ScreenToWorldPoint(new Vector3(Random.Range(0,Screen.width), Random.Range(0,Screen.height), 10));
        }
        for(int i = 0; i < numOfSpawns; i++){
            GameObject.Instantiate(gameObj,spawnLocations[i],Quaternion.identity);
        }
    }
}

AIMovement.cs

public class AIMovement : MonoBehaviour
{
    Rigidbody2D body;
    Animator animator;
    int horizontal;
    int vertical;
    public float runSpeed = 3.0f;
    public bool isTeleport;
    private AIUtility utilityScript;

    // Start is called before the first frame update
    void Start()
    {
        animator = GetComponent<Animator>();
        body = GetComponent<Rigidbody2D>();
        utilityScript = GetComponent<AIUtility>();
    }

    // Update is called once per frame
    void Update()
    {
        //Debug.Log(utilityScript.guard + "        " + utilityScript.walkTime);
        if((utilityScript.walkTime && !utilityScript.guard) && !isTeleport)
        {
            //Got Stuck here. Setting velocity, then changed face, then set Speed caused
            //quite a few bugs that were very quiet.
            switch(animator.GetInteger("Face"))
            {
                case 0:
                    body.velocity = Vector2.down * runSpeed;
                    break;
                case 1:
                    body.velocity = Vector2.right * runSpeed;
                    break;
                case 2:
                    body.velocity = Vector2.left * runSpeed;
                    break;
                case 3:
                    body.velocity = Vector2.up * runSpeed;
                    break;
                default:
                    body.velocity = Vector2.zero;
                    break;
            };
            //Why is there the x2???
            animator.SetFloat("Speed", (body.velocity.x + body.velocity.y) * 2);
            utilityScript.WalkWaitSwitch();
            //Make this an int to make your life easier -------------------------------------
        }
        else if(isTeleport && !utilityScript.guard)
        {
            utilityScript.Teleport();
        }
        if((!utilityScript.walkTime && !utilityScript.guard))
        {
            animator.SetFloat("Speed", 0);
            body.velocity = Vector2.zero;
            utilityScript.WalkWaitSwitch();
        }
    }
    /// <summary>
    /// Sent when an incoming collider makes contact with this object's
    /// collider (2D physics only).
    /// </summary>
    /// <param name="other">The Collision2D data associated with this collision.</param>
    void OnCollisionEnter2D(Collision2D other)
    {
        if(other.gameObject.tag == "Room"){
            body.velocity = Vector2.zero;
            animator.SetFloat("Speed", 0);
            utilityScript.WalkWaitSwitch();
        }
        if(other.gameObject.tag == "Player"){
            float force = 15;
            if(other.gameObject.GetComponent<HealthScript>() != null){
                if(this.gameObject.GetComponent<AIUtility>().getIsDay())
                    gameObject.GetComponent<HealthScript>().LoseHealth(1);
                else
                    gameObject.GetComponent<HealthScript>().LoseHealth(2);
                    //THIS IS WERE I LEFT, TRYIHNG TO ADD PUSHBACK TO THE PLAYER
                Debug.Log("X: " + this.gameObject.GetComponent<Rigidbody2D>().velocity.normalized.x * force + " Y: " + this.gameObject.GetComponent<Rigidbody2D>().velocity.normalized.y * force);
                Vector2 temp = new Vector2(other.transform.position.x, other.transform.position.y);
                Vector2 dir = other.contacts[0].point + temp;
                dir = -dir.normalized;
                other.gameObject.GetComponent<Rigidbody2D>().AddForce(this.gameObject.GetComponent<Rigidbody2D>().velocity.normalized * force);
            }
        }
    }
}

Utility script

public class AIUtility : MonoBehaviour
{
    Animator animator;
    Rigidbody2D rbody;
    public GameObject projectile;
    [HideInInspector] public bool guard;
    [HideInInspector] public bool walkTime;
    [HideInInspector] public bool attack = false;
    [SerializeField] private bool isDay;
    [SerializeField] private bool isRanged;
    [SerializeField] private bool isSuicidal = false;
    private int sec;
    [SerializeField] private int maxWalkTime = 6;
    [SerializeField] public int maxSleepTime = 3;
    private int numOfDirections = 4;
    private int numOfTeleports = -1;
    private System.Random _random;
    private void Start() {
        animator = GetComponent<Animator>();
        rbody = GetComponent<Rigidbody2D>();
        _random = new System.Random();
        guard = false;
        walkTime = true;
    }
    public void WalkWaitSwitch() {
        if(_random.Next(4) == 0){
            attack = true;
        }
        else{
            attack = false;
        }
        StartCoroutine(WalkTime());
        //Set attack bool before walkTime, then if attack set correct wait time and anim trigger
    }
    public IEnumerator WalkTime()
    {
        guard = true;
        if(walkTime)
        {
            walkTime = false;
            sec = _random.Next(0,maxWalkTime);
        }
        else
        {
            walkTime = true;
            if(!attack)
                sec = _random.Next(0,maxSleepTime);
            else
                sec = _random.Next(0,maxSleepTime/2);
        }
        yield return new WaitForSeconds(sec);
        if(attack)
        {
            StartCoroutine(Attack());
        }
        animator.SetInteger("Face", _random.Next(0,numOfDirections));
        guard = false;
    }

    public IEnumerator Attack(){
        animator.SetBool("IsAttacking", true);
        this.rbody.velocity = Vector2.zero;
        AnimationClip[] clips = animator.runtimeAnimatorController.animationClips;
        foreach(AnimationClip clip in clips){
            if(clip.name.Contains("Attack"))
            {
                yield return new WaitForSeconds(clip.length);
                    if(isRanged)
                    {
                        SpriteRenderer rend = GetComponent<SpriteRenderer>();
                        GameObject temp = GameObject.Instantiate(projectile, new Vector3(this.transform.position.x + rend.bounds.extents.x, this.transform.position.y - rend.bounds.extents.y, 0), Quaternion.Euler(0,0,0));
                        //I'm a dummy, just create a bool that is set in inspector. Any mob can have
                        //this script and still have it set to whatever
                        temp.GetComponent<Projectile>().SetDay(isDay);
                        temp.GetComponent<Projectile>().SetFace(animator.GetInteger("Face"));
                    }
                    else if(isSuicidal)
                    {
                        Vector2[] velocities= new Vector2[]
                        {
                            new Vector2(1,0),
                            new Vector2(.75f,.75f),
                            new Vector2(0,1),
                            new Vector2(-.75f,.75f),
                            new Vector2(-1,0),
                            new Vector2(-.75f,-.75f),
                            new Vector2(0,-1),
                            new Vector2(.75f,-.75f)
                        };
                        for(int i = 0; i < 8; i++)
                        {
                            GameObject temp = GameObject.Instantiate(projectile,this.transform.position, Quaternion.Euler(0,0,45 * i));
                            temp.GetComponent<Projectile>().SetDay(isDay);
                            temp.GetComponent<Rigidbody2D>().velocity = velocities[i];
                        }
                    }
                    animator.SetBool("IsAttacking", false);
                    break;
            }
        }
    }

    public bool getIsDay(){
        return isDay;
    }
}
4

0 回答 0