Modify Enemy AI

How would I make it so I have a enemy that uses a rigidbody that is dynamic, it can have a animation use where if it sees the player is play’s a running animation but if it does not it plays a walking animation. It can run into things, and finally it has a chase theme that plays when it sees the player.

It seems like a lot which it is, but it will pay off and make games with enemy’s 10x better.

What we could work off of Credit to @Albertos:

var Enemy = pc.createScript('enemy');

Enemy.attributes.add('enemyCamera', {type: 'entity', title: 'Camera Entity'});
Enemy.attributes.add('enemyTarget', {type: 'entity', title: 'Target Entity'});
Enemy.attributes.add('enemyGround', {type: 'entity', title: 'Ground Entity'});
Enemy.attributes.add('enemySpeed', {type: 'number', default: 0.1, title: 'Enemy Speed'});

// initialize code called once per entity
Enemy.prototype.initialize = function() {
    this.enemyCanSeeTarget = false;
    this.enemyDestination = new pc.Entity();
};

// update code called every frame
Enemy.prototype.update = function(dt) {
    this.searchTarget();
    this.detectObstacle();
    this.moveEnemy(dt);
};

Enemy.prototype.moveEnemy = function (dt) {
    var destination = new pc.Vec3(this.enemyDestination.getPosition().x, 1, this.enemyDestination.getPosition().z);
    var distanceToDestination = this.entity.getPosition().distance(destination);

    // move the enemy based on the current state
    if (!this.enemyCanSeeTarget) {
        if (distanceToDestination > 0.1) {
            this.entity.lookAt(destination);
            this.entity.translateLocal(0,0, -this.enemySpeed*dt);
        }
        else {
            this.randomDestination();
        }
    }
    else {
        this.entity.lookAt(this.enemyDestination.getPosition());
        
        if (distanceToDestination > 2) {
            this.entity.translateLocal(0,0, -this.enemySpeed*dt*2);
        }
    }
};

Enemy.prototype.detectObstacle = function () {
    this.app.systems.rigidbody.raycastFirst(this.entity.getPosition(), this.enemyDestination.getPosition(), function (result) {
        
        // check if there is an obstacle in the way
        // prevent the enemy is moving inside an obstacle
        if (result.entity.name == 'Obstacle') {
            var distanceToObstacle = this.entity.getPosition().distance(result.point);
            
            if (distanceToObstacle < 2) {
                this.randomDestination();
            }
        }
    }.bind(this));
};

Enemy.prototype.searchTarget = function () {
    var target = this.enemyTarget.getPosition();
    var distanceToTarget = this.entity.getPosition().distance(target);
    
    // check if target is in range, so close enough to see
    if (distanceToTarget < 40) {
        target.sub(this.entity.getPosition()).normalize();
        var dot = target.dot(this.entity.forward);
        
        // check if target is front, so spottable or already spotted
        if (dot > 0.5 || this.enemyCanSeeTarget) {
            this.app.systems.rigidbody.raycastFirst(this.entity.getPosition(), this.enemyTarget.getPosition(), function (result) {
                
                // check if target is in view, so no obstacles in the way
                if (result.entity.name == 'Player') {
                    this.enemyCanSeeTarget = true;
                    this.enemyDestination.setPosition(this.enemyTarget.getPosition().x, 1, this.enemyTarget.getPosition().z);
                }
                else {
                    this.enemyCanSeeTarget = false;
                }
            }.bind(this));
        }
        else {
            this.enemyCanSeeTarget = false;
        }
    }
    else {
        this.enemyCanSeeTarget = false;
    }
};

Enemy.prototype.randomDestination = function () {
    var xPosition = pc.math.random(-this.enemyGround.getLocalScale().x/2, this.enemyGround.getLocalScale().x/2);
    var zPosition = pc.math.random(-this.enemyGround.getLocalScale().z/2, this.enemyGround.getLocalScale().z/2);
    this.enemyDestination.setPosition(xPosition, 1, zPosition);
};

Hi @Mason_Rocchio!

I suppose your current enemy has a kinematic rigidbody? Why you want to make this dynamic?

You can easily see where the enemy is moving with translateLocal and you can start your move animation at this point.

What do you mean with this?

If this.enemyCanSeeTarget is true you can start your chase theme. If it is false you can stop it.

I want a dynamic rigidbody so it can run into stuff and so it won’t go through the floor

And that is what the collision is for.

You mean you don’t want your enemy avoiding obstacles, so the enemy gets stuck against a wall or something?

No it goes through walls and other entity’s.

For that you can disable this.detectObstacle(); in the update function of the script.

1 Like

I did this and he still goes through stuff. Yes I do have a rigid body. If use mesh on other entity’s would that effect it? He does also go through other stuff that does not have a mesh.

// update code called every frame
Enemy.prototype.update = function(dt) {
    this.detectObstacle();
    this.searchTarget();
    this.detectObstacle();
    this.moveEnemy(dt);
};

i saw that he is in the floor (i know its arendia because i saw you fixed it and it has the same problem as what your talking about and its the same script), it is possible that it might be because of a setting in the rigid body.

He is going through walls even with a rigid body of dynamic

Please check what I said and compare it with what you did.

Oh I added it I have to do this.detectObstable = false ?

No.

You have to replace this:

this.detectObstacle();

with this:

//this.detectObstacle();

As a result, this line (and function) will no longer be executed and the enemy will go through obstacles.

I did it in the function code like you said

// update code called every frame
Enemy.prototype.update = function(dt) {
    //this.detectObstacle();
    this.searchTarget();
    this.detectObstacle();
    this.moveEnemy(dt);
};

wait this will make it so he goes through stuff?

If you delete your duplicated line too…

I thought this would make it so it can’t go through other entity’s. The only thing it runs into is the player entity. I wan’t it to be able to detect a wall or something in the way.

Can you please check the result of my suggestion first?

ok!

My game won’t launch. It keeps running out of memory

What did you do?