ShurikenVR Devlog#2: Enemy AI, Animation and Basic Combat

Thanks to the bank holiday I was able to get a lot of work done on this game in the weekend, but the changes made are just too much to list out in detail so I’ll just mention the important ones.

So the main thing is making the enemy. Using model from the Synty Samurai pack, and free animations from mixamo, I’ve made 3 different variant of enemy: Ninja, Samurai Grunt and Samurai Warrior. The latter two are using two-handed weapons, which causes some issue with the animation where the other end of the weapon doesn’t align with the off-hand. To deal with this I placed the weapon under the dominant hand transform and wrote a simple script to point the bottom end of the weapon towards the non-dominant hand.

    void Update()
        if (offHandTransform != null)
            transform.LookAt(transform.position + transform.position - offHandTransform.position);

Next, for the enemy AI and path-finding, I used the Unity built-in NavMesh feature to move the enemy towards the player. I created a static singleton PlayerManager which holds the player transform, so the enemies can get a reference to the player’s position.

In terms of animation, there’s a lot to talk about it (rigging, layers, parameters, mask, blend tree, etc) so I’ll just write another note for that.

The code for the enemy AI is very long and complex, so instead of pasting the actual code here, it might be better to present it in Pseudo code.

// code below is executed every update cycle

if dead:
    return // prevent corpse from moving or attacking or react to attack

every 1 second: // NavMesh is quite expensive, refresh every 1 sec to save performance
    Pursue player (using NavMesh)

if player within range:
    Turn towards player (using Slerp to smooth motion) // NavMesh not running if within range, turn manually

    if facing player (<30 degrees) and attack cooled-down:
        Attack player
        Rotate around player // makes the enemy seems somewhat cautious and "combat intelligent"

if player within slowdown range:
    Reduce speed in half // so the enemy wont simply rush to player's face, enemy seems somewhat cautious

Update locomotion animation

I’m pretty happy with the effect rotate around player and reduce speed in half when approaching player made, it makes it feel like you’re not fighting against some stupid AI.

The locomotion animation will be overridden by death, attack and impact animation if they’re triggered, ordered by priority.

For the combat system, I’ve made a GameCharacter base class, which the Enemy and Player will inherit from. This base class holds HP and virtual function TakeDamage(int damage) and Die(). The latter will be executed if HP dropped to zero or below.

In the projectile code, it will try to get a GameCharacter component from the collided object, and apply damage to it.

I’ve also wrote a simple Spawner class to spawn enemy in an interval. At this point I have a very barely playable game.

Other than that, I’ve looked into how to publish a game to Oculus AppLab. There seems to be a lot of guidelines and regulation a game need to be adhere to, and the prototype I have now is just too far away from it. So I’ll just leave it for now and come back to it when the game is somewhat polished.

Next, I’m going to implement the locomotion system (teleport via projectile), game menu and making levels.

Leave a Comment

Your email address will not be published. Required fields are marked *