How to get game script to create attack damage and actually get my enemy to move towards me <3

Yo! I’m using Unity 2019.3 to make a low poly, lower level Outlast-type game.

So I used a Brackeys-like, 6-min tutorial on how to create an Enemy AI.

Thing is,

  • I can’t seem to fathom how to get the enemy to appear suddenly in front of the protagonist, move in hot pursuit after me and effectively throw knives at me. “Misogynist” (name of the antagonist) throws his projectiles too high up in the air, and they’re sideways, not obvious enough to see.

  • The knives (projectile of my choice) are horizontal facing and I don’t really know how to get them to point at the protagonist obviously and maliciously.

  • I also do not know how to make the fire in my game damage the enemy alone, and make an animation for my character taking damage from the knives.

  • I also do not know how to get my character to hide and be undetectable behind the gravestones.

This is for a beginner project made for the sake of experience and becoming the girlboss games dev I wish to be!

The script for the enemy:


using UnityEngine;
using UnityEngine.AI;

public class EnemyAiTutorial : MonoBehaviour
{
    public NavMeshAgent agent;

    public Transform player;

    public LayerMask whatIsGround, whatIsPlayer;

    public float health;

    //Patroling
    public Vector3 walkPoint;
    bool walkPointSet;
    public float walkPointRange;

    //Attacking
    public float timeBetweenAttacks;
    bool alreadyAttacked;
    public GameObject projectile;

    //States
    public float sightRange, attackRange;
    public bool playerInSightRange, playerInAttackRange;

    private void Awake()
    {
        player = GameObject.Find("Dove").transform;
        agent = GetComponent<NavMeshAgent>();
    }

    private void Update()
    {
        //Check for sight and attack range
        playerInSightRange = Physics.CheckSphere(transform.position, sightRange, whatIsPlayer);
        playerInAttackRange = Physics.CheckSphere(transform.position, attackRange, whatIsPlayer);

        if (!playerInSightRange && !playerInAttackRange) Patroling();
        if (playerInSightRange && !playerInAttackRange) ChasePlayer();
        if (playerInAttackRange && playerInSightRange) AttackPlayer();
    }

    private void Patroling()
    {
        if (!walkPointSet) SearchWalkPoint();

        if (walkPointSet)
            agent.SetDestination(walkPoint);

        Vector3 distanceToWalkPoint = transform.position - walkPoint;

        //Walkpoint reached
        if (distanceToWalkPoint.magnitude < 1f)
            walkPointSet = false;
    }
    private void SearchWalkPoint()
    {
        //Calculate random point in range
        float randomZ = Random.Range(-walkPointRange, walkPointRange);
        float randomX = Random.Range(-walkPointRange, walkPointRange);

        walkPoint = new Vector3(transform.position.x + randomX, transform.position.y, transform.position.z + randomZ);

        if (Physics.Raycast(walkPoint, -transform.up, 2f, whatIsGround))
            walkPointSet = true;
    }

    private void ChasePlayer()
    {
        agent.SetDestination(player.position);
    }

    private void AttackPlayer()
    {
        //Make sure enemy doesn't move
        agent.SetDestination(transform.position);

        transform.LookAt(player);

        if (!alreadyAttacked)
        {
            ///Attack code here
            Rigidbody rb = Instantiate(projectile, transform.position, Quaternion.identity).GetComponent<Rigidbody>();
            rb.AddForce(transform.forward * 32f, ForceMode.Impulse);
            rb.AddForce(transform.up * 8f, ForceMode.Impulse);
            ///End of attack code

            alreadyAttacked = true;
            Invoke(nameof(ResetAttack), timeBetweenAttacks);
        }
    }
    private void ResetAttack()
    {
        alreadyAttacked = false;
    }

    public void TakeDamage(int damage)
    {
        health -= damage;

        if (health <= 0) Invoke(nameof(DestroyEnemy), 0.5f);
    }
    private void DestroyEnemy()
    {
        Destroy(gameObject);
    }

    private void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, attackRange);
        Gizmos.color = Color.yellow;
        Gizmos.DrawWireSphere(transform.position, sightRange);
    }
}

The script for my character:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DoveMovement : MonoBehaviour
{
    public float moveSpeed = 10f;
    public float turnSpeed = 50f;
    public float runSpeed = 30f;

    void Update()
    {
        if (Input.GetKey(KeyCode.UpArrow))
            transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);

        if (Input.GetKey(KeyCode.DownArrow))
            transform.Translate(-Vector3.forward * moveSpeed * Time.deltaTime);

        if (Input.GetKey(KeyCode.LeftArrow))
            transform.Rotate(Vector3.up, -turnSpeed * Time.deltaTime);

        if (Input.GetKey(KeyCode.RightArrow))
            transform.Rotate(Vector3.up, turnSpeed * Time.deltaTime);

        else if (Input.GetKey(KeyCode.Space))
            transform.Translate(Vector3.forward * runSpeed * Time.deltaTime);
    }
}

Scene view of my project:

Name for the enemy AI is Misogynist, name for the protagonist is Dove.

2 Answers

2

That is a lot of questions for a single thread. It may help to tackle and solve one problem at a time before moving on to the next one. Tutorials are a great place to learn and I personally also like Brackeys’s tutorials.

I don’t have much experience with 3D, but I can maybe help with this one:

If you want the fire to only affect enemies, you could put it on a different physics layer that only interacts with enemies. The “Layer” in the upper-right corner of the inspector is used for physics interactions. Under Edit->Project Settings->Physics menu there is a table that specifies which layers can interact with one another. See the manual below:

For example, you could create an “EnemyHazard” layer and disable the interaction between this Layer and the Player’s Layer.

To have your enemy suddenly appear in front of Dove, you could script a trigger event where, under certain conditions (like entering a specific area), Misogynist is instantiated or activated in front of Dove. For moving towards Dove, your ChasePlayer() function in the enemy script looks good. Just make sure the enemy can navigate the environment correctly using Unity’s NavMesh system.

If Misogynist’s knives are flying off in weird directions, check the orientation of the projectile prefab. The prefab itself should be oriented correctly in its local space. You might want to adjust the rotation when instantiating the projectile:

Rigidbody rb = Instantiate(projectile, transform.position, Quaternion.LookRotation(player.position - transform.position)).GetComponent<Rigidbody>();
rb.AddForce(transform.forward * 32f, ForceMode.Impulse);