[SOLVED] How to make enemy rotate to the direction they are about to move in

So, I’m trying to make an amoeba-based enemy for my game. I was thinking that it moves by sliding around, but it faces in the direction that it is applying a force to, so I have an angle variable. I apply a force that is equal to x = sin (angle) and y = cos(angle), but I don’t know how to make the Amoeba rotate to face the direction it is about to move.

Here is V1 of the script:

EnemyMovementAndAttack.prototype.moveTypeSlide = function() {
    if (this.randomRNGTime == -30) {
        this.randomRNGTime = Math.round(Math.random() * 2000) + (8000 / this.speed)
        this.randomRNGDir = Math.round((Math.random() - 0.5) * 2)
    } else if (this.randomRNGTime < 0){
        this.randomRNGTime = Math.round(Math.random() * 2000) + (8000 / this.speed)
        this.randomRNGPauseTime = (Math.random() * 5) + 8
    } else if (this.randomRNGPauseTime > 0) {
        this.randomRNGPauseTime -= 1
        this.entity.rigidbody.applyTorque(0, 0, (this.randomRNGDir / (Math.abs(this.randomRNGDir))) * 5)
        this.angle = this.entity.getRotation()
    } else if (this.randomRNGTime >= 0) {
        if ((this.randomRNGTime % 20) == 0) {
        this.randomRNGDir = Math.round((Math.random() - 0.5) * 8) * 5
        }
        this.angle += this.randomRNGDir
        this.entity.rigidbody.applyForce((Math.sin(this.angle * (Math.PI / 180))) * this.speed, (Math.cos(this.angle * (Math.PI / 180))) * this.speed, 0)
        var targetPosition = new pc.Vec3(this.myPosition.x + (Math.sin(this.angle * (Math.PI / 180))), this.myPosition.y + (Math.cos(this.angle * (Math.PI / 180))), -0.25)
        if ((this.randomRNGTime % 2) == 0) {
            var pos = this.entity.getPosition()
            this.entity.rigidbody.teleport(pos,0,0,this.angle)
        }
        this.randomRNGTime -= 1
    }
};

3 notes: Yes I used a dynamic rigid body, I’m not doing the teleport every frame otherwise it won’t move, and no, it doesn’t work

what is the problem with the script? and how do I fix it?

In the “initialize” function, I make “this.randomRNGTime” equal to 30 because it isn’t guaranteed that “this.randomRNGDir” will be defined during frame one of the script, so I forced it to be defined instead of moving.

also the part that plays during “this.randomRNGPauseTime” is only a few frames cuz I’m trying to focus on the movement and natural rotation first.

Hi @Linkplayer!

What exactly isn’t working at this point?

It could be that the teleport on line 21 isn’t working, because of how you’re currently applying the position and rotation. As far as I know, they need to be applied in the same way (either both using a Vector3 or both using separate values).

Thanks, it’s now rotating too fast, but I know how to do this one. so this is solved, Thank you.

1 Like

OK, just a question? is Conecast a function in ammo.js? I want to make a triangle-shaped sight function to detect the player, but I don’t know if it would work like that. It’s for the Seamoeba(Yes, the amoeba can see). When it sees the player while pauseTime is active(AKA in the part where if (this.randomRNGPauseTime > 0) is the section I’m talking about), it is supposed to try to chase them down, but I need to figure out how to make it see the player to activate chase mode. So is coneCast a possible function? Is there something better for this situation?

No, that doesn’t exist in Ammo unfortunately. What I personally do is using a single raycast and if there is a hit with the target, I use the dot producten to determine if it is in a certain angle.

oh, I see.

I also just found this: PlayCanvas physics extension

I might try them out once I figure out how to activate it.

1 Like

Yes, there is an extension, but keep in mind that it is more expensive to use

more expensive? so it is less optimized or greater storage usage?

either way, I don’t fully understand your method.

Do I fire multiple raycasts at different angles to see if it hits the player, or check to see if the player is within a selected distance and angle infront of the enemy by firing a raycast with the player as the end point.

OK, with the help of Google Gemini, I made this as an alternitive

    var myPos = this.entity.getPosition();
    var playerPos = this.app.root.findByName('Qiste').getPosition();
    var distance = myPos.distance(playerPos)
    var directionToTarget = new pc.Vec3();
    directionToTarget.sub2(myPos, playerPos).normalize();
    var myAng = this.entity.up;
    var dotProduct = myAng.dot(directionToTarget);
    if (distance <= this.sightDis) {
        var angleInRadians = Math.acos(dotProduct);
        var angleInDegrees = angleInRadians * pc.math.RAD_TO_DEG;
        angleInDegrees = (angleInDegrees - 180)
        var toleranceAngle = this.sightAng; // degrees
        console.error(angleInDegrees)
        if (Math.abs(angleInDegrees) <= toleranceAngle) {
            this.action = 'attack'
        }
    }
}

is there a simpler and more optimised solution to the problem?

BTW I subreacted 180 because it was spreading out from the bottom of the entity, not the top, where I wanted it.

In my basic enemy AI example project, you can see how I have done this in the enemy.js script.

https://playcanvas.com/project/870482/overview/basic-enemy-ai

It’s similar to what Gemini suggested to be honest.