AI Laggy

Okay, so right now whenever my spawner spawns my models, there is no framerate drop, but the second they start moving(I came into range and they started to chase me) it lags my game. It cuts it practically in half(with 4 spawned. I go from 80fps to 40, with 8 spawned down to 20-25 fps). I am going to post the script, see anything I can alter to make it not lag so bad?

using UnityEngine;
using System.Collections;

public class EnemyAI : MonoBehaviour {
    public Transform _target;
    public int moveSpeed;
    public int rotationSpeed;
    public int maxDistance;
    private SphereCollider _sphereCollider;
    public float perceptionRadius = 10f;
    private const float ROTATION_DAMP = .3f;
    private const float FORWARD_DAMP = .9f;
    public float baseMeleeRange = 3.5f;
    private Transform _myTransform;

    private Transform myTransform;

    void Awake() {
        myTransform = transform;
    }

    // Use this for initialization
    void Start () {
        //Setup ();
        GameObject go = GameObject.FindGameObjectWithTag("Player");

        _target = go.transform;

        maxDistance = 2;
   
   
    }
   
    // Update is called once per frame
    void Update () {
        Debug.DrawLine (_target.position, myTransform.position, Color.yellow);
        Move ();
        /*//Look at target
        myTransform.rotation = Quaternion.Slerp (myTransform.rotation, Quaternion.LookRotation(target.position - myTransform.position), rotationSpeed * Time.deltaTime);

        if (Vector3.Distance (target.position, myTransform.position) > maxDistance) {

        //Move towards target
        myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
        }*/
    }

    private void Move() {
        Debug.Log ("Moving");
        //stopWatch.Start ();
        if (_target) {
            Vector3 dir = (_target.position - myTransform.position).normalized;
            float direction = Vector3.Dot(dir, transform.forward);
           
            float dist = Vector3.Distance(_target.position, myTransform.position);
           
            Debug.Log("dist");
            if(direction > FORWARD_DAMP && dist > baseMeleeRange) {
                SendMessage("MoveMeForward", AdvancedMovement.Forward.forward);
            }
            else {
                SendMessage("MoveMeForward", AdvancedMovement.Forward.none);
            }
           
            dir = (_target.position - myTransform.position).normalized;
            direction = Vector3.Dot(dir, transform.right);
           
            if(direction > ROTATION_DAMP) {
                SendMessage("RotateMe", AdvancedMovement.Turn.right);
            }
            else if(direction < -ROTATION_DAMP) {
                SendMessage("RotateMe", AdvancedMovement.Turn.left);
            }
            else {
                SendMessage("RotateMe", AdvancedMovement.Turn.none);
            }
        }
        else {
            SendMessage("MoveMeForward", AdvancedMovement.Forward.none);
            SendMessage("RotateMe", AdvancedMovement.Turn.none);
        }
    }

    private void Setup() {
        _sphereCollider.center = GetComponent<CharacterController> ().center;
        _sphereCollider.radius = perceptionRadius;
        _sphereCollider.isTrigger = true;
    }
}

Using character controller is not a good choice for AI its pretty nasty resource wise. Switching it out for rigidbody and capsule collider I guarantee you can get a bunch more then 8.

I had this issue a ways back. I could get about 20 before it started dropping fps. Switched it over to rigidbody and capsule and I was able to get 300+. Upwards of 600 with 30fps.

Also you use plenty SendMessage which is known for its poor performances. It really isn’t much hasle to replace it with proper references to object/method delegates…

Simply add the script with thoose methods as a private variable and gather it with GetComponent() then call the methods directly and you’ll gain a lot of execution speed.

May I be curious why you have 2 “myTransform” variables ?

private Transform _myTransform;
private Transform myTransform;

Haha, well I am new at programming, so I didn’t realize i had that when I did that and now have one gone. Going to post my new code in a sec as I’m stuck on a new problem

Okay, I have now fixed the AI with the rigid bodies, but now they just play their walk animation, but just sit there. will post gif along with this so you get an idea along with a picture of the scripts in the editor.

GIF: Screen capture - ef70fe08b188d88ebdd988eeb066a4ba - Gyazo(not that laggy in game, that’s just Gyazo)
Image of Inspector: Screenshot - 15fc150bf449f38c9565ea0d6a45f387 - Gyazo

And the code:

/// <summary>
/// Advanced movement.cs
/// May 14th, 2014
///
/// This script is responsible for getting the player movement inputs and adjusting the characters animations accordingly.
///
/// This script will be automatically attach to your player or mob with the use of the PlayerInput.cs and AI.cs scripts.
///
/// This script assumes that you have these animations with the following names
/// Player:
/// walk    - a walk animation
/// run        - a run animatino
/// jump    - a jump animation
/// fall    - a falling animation
/// idle    - an idle animation
///
/// Mob:
/// run        - a run animation
/// jump    - a jump animation
/// fall    - a falling animation
/// idle    - an idle animation
///
/// </summary>
using UnityEngine;
using System.Collections;

[RequireComponent (typeof(Rigidbody))]
public class EnemyAdvancedMovement : MonoBehaviour {
    public enum State {
        Idle,
        Init,
        Setup,
        Run
    }
  
    public enum Turn {
        left = -1,
        none = 0,
        right = 1
    }
    public enum Forward {
        back = -1,
        none = 0,
        forward = 1
    }
  
    public string walkAnimName;
    public string runAnimName;
    public string jumpAnimName;
    public string idleAnimName;
    public string fallAnimName;
    public string attackAnimName1;
    public string attackAnimName2;
  
    public float strafeSpeed = 3.5f;            //the speed our character strafes at
    public float runMultiplier = 4;                //how fast the player runs compared to the walk speed
    public float walkSpeed = 3;                    //the speed our character walks at
    public float rotateSpeed  = 125;            //the speed our character turns at
    public float gravity = 20;                    //the setting for gravity
    public float airTime = 0;                    //how long have we been in the air since the last time we touched the ground
    public float fallTime = .5f;                //the length of time we have to be falling before the system knows its a fall
    public float jumpHeight = 8;                //the height we move when we are jumping
    public bool doRun = true;
    public float jumpTime = 1.5f;
  
    private CollisionFlags _collisionFlags;        //the collisionFlags we have from the last frame
  
    private Vector3 _moveDirection;                //this is the direction our character is moving
    private Transform _myTransform;                //our cached transform
    private Rigidbody _rigidBody;                //our cached RigidBody
  
    private Turn _turn;
    private Forward _forward;
    private Turn _strafe;
    private bool _run;
    private bool _jump;
    private float distToGround;
  
    private State _state;
  
  
    //Called before the script starts
    public void Awake() {
        _myTransform = transform;
        _rigidBody = GetComponent<Rigidbody> ();
        distToGround = collider.bounds.extents.y;
      
        _state = EnemyAdvancedMovement.State.Init;
    }

    // Use this for initialization
    IEnumerator Start () {
        while (true) {
            switch(_state) {
            case State.Init:
                Init ();
                break;
            case State.Setup:
                Setup ();
                break;
            case State.Run:
                ActionPicker();
                break;
              
            }
            yield return null;
          
        }
    }
  
    void Update() {
        _rigidBody.AddForce (transform.forward * runMultiplier);
    }
  
    private void Init() {
        if(!GetComponent<Rigidbody>())return;
        if(!GetComponent<Animation>())return;
      
        _state = EnemyAdvancedMovement.State.Setup;
    }
    private void Setup() {
        animation.Stop ();                                        //stop any animations that might be set to play automatically
        animation.wrapMode = WrapMode.Loop;                        //set all animations to loop by default
        //        animation [jumpAnimName].layer = 1;                        //move jump to a higher layer
        animation [jumpAnimName].wrapMode = WrapMode.Once;        //set jump to only play once
        animation.Play(idleAnimName);                            //start the idle animation when the script starts
      
        _moveDirection = Vector3.zero;                            //zero our the vector3 we will use for moving our player
        _turn = EnemyAdvancedMovement.Turn.none;
        _forward = EnemyAdvancedMovement.Forward.none;
        _strafe = Turn.none;
        _run = true;
        _jump = false;
      
        _state = EnemyAdvancedMovement.State.Run;
    }
  
    private void ActionPicker() {
        //allow the player to turn left and right
        _myTransform.Rotate(0, (int)_turn * Time.deltaTime * rotateSpeed, 0);
      
      
      
        //if we are on the ground, let us move
        if (_rigidBody) {
            //reset the air time if we are on the ground
            airTime = 0;
          
          
            //get the user input if we should be moving forward or sideways
            //we will calculate a new vector3 for where the player needs to be
            _moveDirection = new Vector3((int)_strafe,0, (int)_forward);
            _moveDirection = _myTransform.TransformDirection(_moveDirection).normalized;
            _moveDirection *= walkSpeed;
          
            if(Input.GetKeyDown(KeyCode.Slash)) {           
                doRun = !doRun;                              
            }
            if(_forward != Forward.none) {  
                if(_run) {              
                    _moveDirection *= runMultiplier;        //move user at run speed
                    Run();                                    //play run animation
                }
                else {
                    Walk();                                    //play walk animation
                }
            }
            else if(_strafe != EnemyAdvancedMovement.Turn.none) {
                Strafe ();
            }
            else {
                Idle ();                                    //play idle animation
            }
          
            if(_jump) {                                        //if the user presses the jump key
                if(airTime < jumpTime) {                    //if we have not already been in the air to long
                    _moveDirection.y += jumpHeight;            //move them upwards
                    Jump ();                                //play jump animation
                    _jump = false;
                }
            }
          
        }
        else {
            if((_collisionFlags & CollisionFlags.CollidedBelow) == 0) {
                airTime += Time.deltaTime;
              
                if(airTime > fallTime) {
                    Fall();
                }
            }
          
        }
      
        //_moveDirection.y -= gravity * Time.deltaTime;
      
        //_collisionFlags =
        //_rigidBody.AddForce (transform.forward * runMultiplier);
    }
  
    public void MoveMeForward(Forward z) {
        _forward = z;
    }
  
    public void ToggleRun() {
        _run = !_run;
    }
  
    public void RotateMe(Turn y) {
        _turn = y;
    }
  
    public void Strafe(Turn x) {
        _strafe = x;
    }
  
    public void JumpUp() {
        _jump = true;
    }
  
    public void Idle() {
        if(idleAnimName == null)
            return;
        animation.CrossFade(idleAnimName);
    }
  
    public void Walk() {
        if(walkAnimName == null)
            return;
        animation [walkAnimName].speed = 2;
        animation.CrossFade(walkAnimName);
    }
  
    public void Run () {
        if(runAnimName == null)
            return;
      
        animation [runAnimName].speed = 1.5f;
        animation.CrossFade(runAnimName);
    }
  
    public void Jump () {
        if(jumpAnimName == null)
            return;
        animation.CrossFade(jumpAnimName);
    }
  
    public void Strafe () {
        if(runAnimName == null)
            return;
        animation.CrossFade(runAnimName);
    }
  
    public void Fall () {
        if(fallAnimName == null)
            return;
        animation.CrossFade(fallAnimName);
    }
  
    public void AttackOne() {
        if(attackAnimName1 == null)
            return;
        animation.CrossFade(attackAnimName1);
    }
  
    public void AttackTwo() {
        if(attackAnimName2 == null)
            return;
        animation.CrossFade(attackAnimName2);
    }

    public bool IsGrounded() {
        return Physics.Raycast(transform.position, - Vector3.up ,distToGround + 0.1f);
    }
}

Hmm okay, so yea, if I take off gravity they just go flying at me, LOL. Can not figure this one out :frowning: Still pretty new to C#

Not sure where your telling them to move. But if you want to move with the rigidbody you want to use the rigidbody.AddForce.

Example:

 _targetVelocity = new Vector3(1, 0, 1);
        _targetVelocity = transform.TransformDirection(_targetVelocity);
Vector3 velocity = rigidbody.velocity;
        Vector3 velocityChange = (_targetVelocity - velocity);
//You can do clamping to limit how much is applied.
        velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
rigidbody.AddForce(velocityChange, ForceMode.VelocityChange);

I use

private Rigidbody _rigidBody;

_rigidBody.AddForce (transform.forward)

That is at the end of ActionPicker
Right now it just kind of keeps gaing speed, then flies by me, turn around and start again

Depending on your game, I would recommend using a navmesh for movement instead (it became free in the 4.x cycle).
it’s what I use, works great.

Woah, yea that looks awesome. Now to learn how to use it! haha

300?! I am now using navmeshagent, but whenever my animation plays, with 4 spawned I get 30FPS, 8 20FPS. Without animations it’s 4 60FPS, 8 30FPS. Not a clue how you managed that! Any ideas?

Did you change the colliders to Capsule Colliders and remove all the CharacterController items? If you just added rigidbody but still used the Character controller its kind of pointless.

Its hard to know whats wrong with very small pieces of information.

All i have on there now is my scripts + nav mesh agent and a capsule collider. Screenshot - 88ce3aad9ec2fb92692468efa74eb6e0 - Gyazo

Might want to update your script so we can see what you have now.
I know it’s possible to make this work, as I have with a AI package I built (not released yet though, having problems getting the interface working).

I have fixed it now, it was all of my Debugs. Thanks to Ereous! Thanks a ton for all the help.