Unity 5 - How to duplicate enemies whilst making them unique?
Hello,
I am making a game for a school project and I have an animated enemy set up. Basically what I want to do now is duplicate them and put them at certain points on the map. Problem is, when I ctrl+D the enemy in the editor they all get shot when I shoot óne of the enemies and they also ALL die when I kill one.
Please bare with me since I am a novice at unity and coding in general.
My enemy consists of three scripts:
This is the Raycast script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HandGunDamage : MonoBehaviour {
int DamageAmount = 5;
float TargetDistance;
float AllowedRange = 30;
public static bool Is_Hit = false;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown(0))
{
RaycastHit Shot;
if (Physics.Raycast (transform.position, transform.TransformDirection(Vector3.forward), out Shot))
{
TargetDistance = Shot.distance;
if (TargetDistance < AllowedRange)
{
Shot.transform.SendMessage("DeductPoints", DamageAmount, SendMessageOptions.DontRequireReceiver);
Is_Hit = true;
}
}
}
}
}
This is the script that handles the animation and the dying of the enemies:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class SpiderScript : MonoBehaviour
{
public GameObject Player, Enemy001, Enemy002;
public Animator Anim;
public NavMeshAgent NavMeshAgent;
private float Distance_To_Player;
private float m_AnimationTime;
// Use this for initialization
void Start()
{
Anim = GetComponent<Animator>();
NavMeshAgent = GetComponent<NavMeshAgent>();
}
// Update is called once per frame
void Update()
{
transform.position = new Vector3(transform.position.x, transform.position.y, transform.position.z);
Distance_To_Player = Vector3.Distance(Player.transform.position, transform.position);
if (!HandGunDamage.Is_Hit)
{
if (Distance_To_Player > 3 && Distance_To_Player < 20 && EnemyScript.EnemyHealth > 0)
{
Anim.SetBool("b_IsChasing", true);
NavMeshAgent.SetDestination(Player.transform.position);
}
else if (Distance_To_Player > 20)
{
NavMeshAgent.SetDestination(transform.position);
Anim.SetBool("b_IsChasing", false);
}
if (EnemyScript.EnemyHealth <= 0)
{
NavMeshAgent.Stop();
Anim.SetTrigger("t_Die");
}
}
else if (HandGunDamage.Is_Hit)
{
NavMeshAgent.SetDestination(transform.position);
Anim.SetTrigger("t_IsHit");
if (!Anim.GetCurrentAnimatorStateInfo(0).IsName("t_IsHit"))
{
HandGunDamage.Is_Hit = false;
}
}
}
}
And last but not least, the scripts that handles the deduction of healthpoints of the enemy:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
public class EnemyScript : MonoBehaviour {
public static int EnemyHealth = 10;
// Use this for initialization
void Start () {
}
void DeductPoints(int DamageAmount)
{
EnemyHealth -= DamageAmount;
}
// Update is called once per frame
void Update () {
}
}
What is the best way of making unique duplicates of this enemy?
I apologize for the long text.
Any help would be much appreciated!
Answer by Pengocat · Jan 29, 2017 at 12:55 AM
public static bool Is_Hit
should probably not be static. When you make a variable static it belongs to the Class and not the instance which means that a static variable is always the same across all instances.
Thanks for the reply!
Okay, that makes sense. So how would I acces the Is_Hit bool from my SpiderScript.
The int EnemyHealth in EnemyScript is also static, would I also have to change that one?
If the EnemyScript is attached to the same GameObject as the SpiderScript you can simply use GetComponent()
when you want to call something on EnemyScript from the SpiderScript. The HandGunDamage script you probably have on the player GameObject? Then you use your reference to the player and Get the HandGunDamage Script reference there.
using UnityEngine;
public class HandGunDamage : $$anonymous$$onoBehaviour
{
public bool isHit = false;
private float targetDistance;
private float allowedRange = 30;
private int damageAmount = 5;
// Update is called once per frame
void Update()
{
if (Input.Get$$anonymous$$ouseButtonDown(0))
{
RaycastHit Shot;
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out Shot))
{
targetDistance = Shot.distance;
if (targetDistance < allowedRange)
{
Shot.transform.GetComponent<EnemyScript>().DeductPoints(damageAmount);
isHit = true;
}
}
}
}
}
Using strings is prone to errors by spelling mistakes so ins$$anonymous$$d I have used the int Hash with the Animator.
using UnityEngine;
using UnityEngine.AI;
public class SpiderScript : $$anonymous$$onoBehaviour
{
public GameObject player;
private float distanceToPlayer;
private EnemyScript enemyScript;
private HandGunDamage handGunDamage;
private Nav$$anonymous$$eshAgent nav$$anonymous$$eshAgent;
private Animator anim;
private int isChasingHash = Animator.StringToHash("b_IsChasing");
private int dieHash = Animator.StringToHash("t_Die");
private int isHitHash = Animator.StringToHash("t_IsHit");
// Use this for initialization
void Start()
{
anim = GetComponent<Animator>();
nav$$anonymous$$eshAgent = GetComponent<Nav$$anonymous$$eshAgent>();
enemyScript = GetComponent<EnemyScript>();
handGunDamage = player.GetComponent<HandGunDamage>();
}
// Update is called once per frame
void Update()
{
transform.position = new Vector3(transform.position.x, transform.position.y, transform.position.z);
distanceToPlayer = Vector3.Distance(player.transform.position, transform.position);
bool isHit = handGunDamage.isHit;
if (!isHit)
{
int enemyHealth = enemyScript.enemyHealth;
if (distanceToPlayer > 3 && distanceToPlayer < 20 && enemyHealth > 0)
{
anim.SetBool(isChasingHash, true);
nav$$anonymous$$eshAgent.SetDestination(player.transform.position);
}
else if (distanceToPlayer > 20)
{
nav$$anonymous$$eshAgent.SetDestination(transform.position);
anim.SetBool(isChasingHash, false);
}
if (enemyHealth <= 0)
{
nav$$anonymous$$eshAgent.Stop();
anim.SetTrigger(dieHash);
}
}
else if (isHit)
{
nav$$anonymous$$eshAgent.SetDestination(transform.position);
anim.SetTrigger(isHitHash);
if (!anim.GetCurrentAnimatorStateInfo(0).IsName("t_IsHit"))
{
isHit = false;
}
}
}
}
using UnityEngine;
public class EnemyScript : $$anonymous$$onoBehaviour
{
public int enemyHealth = 10;
public void DeductPoints(int damageAmount)
{
enemyHealth -= damageAmount;
}
}