我试图创造一个“聪明”的敌人,如果它没有弹药,并且如果它的所有武器都耗尽了弹药,那就换一个武器,找到最近的武器并更换武器。
到目前为止,我有一个敌人可以巡逻,在射程内找到玩家,追逐和攻击玩家。
以下是代码:
public class EnemyControler : MonoBehaviour
{
[Header("Attack")]
[SerializeField] float shootingDistance =10.0f;
[SerializeField] float shootDelay = 3.5f;
[Range(0,1.0f)][SerializeField] float shootingAccuracy =0.5f;
[SerializeField] int shootDamage =5;
[SerializeField] int ammo = 1;
[Header("User Interface")]
public Transform canvasTr;
public Slider Healthbar;
[Header("Health/Damage/Death")]
public float MaxHealth;
public float Damage;
public float AttackRange;
public int deathCounter;
public Transform ammoObject;
private NavMeshAgent navAgent;
private Collider enemycollider;
private Transform PlayerTr;
private Animator EnemyAnim;
float Health;
bool showingHealthBar, alive;
bool isPatrolling =false;
bool isInShootingRange =false;
bool canResumeIdleState =true;
bool isPreparingToShoot=false;
bool isDead =false;
bool isAlerted =false;
float shootTimer = Mathf.Infinity;
AIPatrolBehavior aIPatrolBehavior = null;
void Start()
{
Health = MaxHealth;
canvasTr.gameObject.SetActive(false);
navAgent = GetComponent<NavMeshAgent>();
EnemyAnim = GetComponent<Animator>();
enemycollider = GetComponent<Collider>();
PlayerTr = GameObject.FindGameObjectWithTag("Player").transform;
aIPatrolBehavior = GetComponent<AIPatrolBehavior>();
alive = true;
ammo = 100;
StartCoroutine(Idle());
// are you sure you want to randomly change MaxHealth after settting health = maxHealth?
//the slider gets weirdly bugged
// MaxHealth = Random.Range(50, 200);
Healthbar.maxValue = MaxHealth; // set the max value to MaxHelth
}
private void Update()
{
if(isDead)return;
if(Vector3.Distance(PlayerTr.transform.position, transform.position) > 20 && !isAlerted
|| PlayerTr.GetComponent<PlayerController>().HealthBar.value <= 0.0f){
StopAllCoroutines();
GetComponent<AIPatrolBehavior>().enabled =true;
return;
}
if(Vector3.Distance(PlayerTr.transform.position, transform.position) < 20 && isAlerted) isAlerted=false;
isInShootingRange = DistanceToPlayer() < shootingDistance &&
DistanceToPlayer() > AttackRange - 0.5f &&
PlayerTr.GetComponent<PlayerController>().HealthBar.value > 0;
if(isInShootingRange)
{
if(canResumeIdleState){
StopAllCoroutines();
canResumeIdleState=false;
}
ProcessShooting();
} else{
if(!canResumeIdleState){
isPreparingToShoot =false;
StartCoroutine(Idle());
canResumeIdleState =true;
navAgent.enabled =true;
}
}
}
private void ProcessShooting()
{
if(!isPreparingToShoot) shootTimer +=Time.deltaTime;
navAgent.enabled =false;
transform.LookAt(PlayerTr);
float randomProbability =Random.Range(0,1.0f);
if(shootTimer > shootDelay){
ShootAtPlayer();
}
EnemyAnim.SetFloat("MovmentSpeed", 0, 0.3f, Time.deltaTime);
}
private void ShootAtPlayer(){
if(isPreparingToShoot)return;
EnemyAnim.SetBool("PrepareAttack", false);
shootTimer =0.0f;
isPreparingToShoot = true;
EnemyAnim.SetTrigger("shoot");
}
public void ShootPlayerAnimationEvent(){
Debug.Log("Player got shot");
float randomAccuracy = Random.Range(0, 1.0f);
bool willHitTarget = randomAccuracy > 1.0f - shootingAccuracy;
if(willHitTarget && DistanceToPlayer() < shootingDistance){
PlayerTr.GetComponent<PlayerController>().DoDamage(shootDamage,true);
}
GetComponentInChildren<AIWeapon>().UseWeapon();
isPreparingToShoot =false;
}
IEnumerator Idle()
{
EnemyAnim.SetBool("PrepareAttack", false);
yield return new WaitUntil(() => Vector3.Distance(PlayerTr.transform.position, transform.position) < 20 || isAlerted);
StartCoroutine(RunToTarget());
}
IEnumerator RunToTarget()
{
aIPatrolBehavior.enabled =false;
if(navAgent.isOnNavMesh) { // save from error apperng
navAgent.isStopped = false;
}
EnemyAnim.SetTrigger("Attack");
while (Vector3.Distance(PlayerTr.transform.position, transform.position) > AttackRange - 0.5f)
{
if(navAgent.isOnNavMesh) { // save from error apperng
navAgent.SetDestination(PlayerTr.position);
}
// navAgent.SetDestination(PlayerTr.position);
EnemyAnim.SetFloat("MovmentSpeed", 1, 0.3f, Time.deltaTime);
yield return null;
}
StartCoroutine(Attack());
}
IEnumerator Attack()
{
EnemyAnim.SetBool("PrepareAttack", true);
navAgent.isStopped = true;
while (Vector3.Distance(PlayerTr.position, transform.position) < AttackRange)
{
EnemyAnim.SetTrigger("Attack");
float t = 0.5f;
while (t > 0)
{
Vector3 rotation = Vector3.RotateTowards(transform.forward, PlayerTr.position - transform.position, 5f * Time.deltaTime, 1f);
transform.forward = rotation;
t -= Time.deltaTime;
yield return null;
}
yield return null;
}
EnemyAnim.SetBool("PrepareAttack", false);
StartCoroutine(RunToTarget());
}
float DistanceToPlayer(){
return Vector3.Distance(transform.position,PlayerTr.position);
}
public void DoDamage(float damage)
{
Alert();
if (!showingHealthBar)
{
showingHealthBar = true;
StartCoroutine(ShowHealthBar());
}
Health -= damage;
Debug.Log("Health: " + Health + " of: " + MaxHealth);
Healthbar.value = Health;
if (Health <= 0)
{
StopAllCoroutines();
if(navAgent.isOnNavMesh) { // save from error apperng
navAgent.isStopped = true;
}
if (alive)
{
alive = true; // does this make sense?
StartCoroutine(Death());
}
}
}我曾尝试通过谷歌搜索,以找到任何教程,但没有成功。有人有什么想法吗?
发布于 2022-10-29 19:53:00
如果在地图上放置的武器是固定的,你可以让敌人停止巡逻或追逐玩家,当他的弹药== 0被布尔值控制时,你可以使用MoveTowrds()武器。你可以用某种方法来计算敌人的位置和阵列上所有武器之间的距离,然后它向最近的方向飞去。你将使用一系列的向量来存储武器的位置。现在轮到你试试了。
https://stackoverflow.com/questions/74247677
复制相似问题