147 lines
4.8 KiB
C#
147 lines
4.8 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
//using UnityEditor.Presets;
|
|
using UnityEngine;
|
|
using UnityEngine.AI;
|
|
|
|
|
|
namespace Beyond
|
|
{
|
|
[RequireComponent(typeof(NavMeshAgent))]
|
|
[RequireComponent(typeof(Animator))]
|
|
public class Animal : MonoBehaviour
|
|
{
|
|
enum State { IDLE, WALK, RUN };
|
|
State m_state;
|
|
UnityEngine.AI.NavMeshAgent m_Agent;
|
|
Vector3 startPosition;
|
|
Vector3 destination;
|
|
Animator m_Animator;
|
|
public float StoppingDistance = 2f;
|
|
float m_timer = 0f;
|
|
float m_targetTime = 0f;
|
|
public float m_wanderRange = 40f;
|
|
public float m_minPlayerDistance = 10f;
|
|
int m_maxTrials = 15;
|
|
GameObject m_Player;
|
|
// Start is called before the first frame update
|
|
void Start()
|
|
{
|
|
m_Animator = GetComponent<Animator>();
|
|
m_Agent = GetComponent<NavMeshAgent>();
|
|
|
|
startPosition = transform.position;
|
|
m_Agent.acceleration = 50;
|
|
m_Agent.angularSpeed = 1000;
|
|
m_Agent.stoppingDistance = StoppingDistance;
|
|
SetState(State.IDLE);
|
|
m_Player = GameObject.FindGameObjectWithTag("Player");
|
|
}
|
|
|
|
void SetState(State state)
|
|
{
|
|
m_Animator.SetInteger("Random", Random.Range(0, 2));
|
|
switch (state)
|
|
{
|
|
case State.IDLE:
|
|
m_Animator.SetBool("IDLE", true);
|
|
m_Animator.SetBool("WALK", false);
|
|
m_Animator.SetBool("RUN", false);
|
|
m_targetTime = Random.Range(5f, 10f);
|
|
break;
|
|
case State.WALK:
|
|
m_Animator.SetBool("IDLE", false);
|
|
m_Animator.SetBool("WALK", true);
|
|
m_Animator.SetBool("RUN", false);
|
|
if (!FindAPath(m_wanderRange, false))
|
|
{
|
|
Debug.LogError("Animal AI: didn't find a path");
|
|
}
|
|
|
|
break;
|
|
case State.RUN:
|
|
m_Agent.speed = 12f;
|
|
m_Animator.SetBool("IDLE", false);
|
|
m_Animator.SetBool("WALK", false);
|
|
m_Animator.SetBool("RUN", true);
|
|
if (!FindAPath(m_wanderRange, true))
|
|
{
|
|
Debug.LogError("Animal AI: didn't find a path");
|
|
}
|
|
break;
|
|
}
|
|
m_timer = 0f;
|
|
m_state = state;
|
|
}
|
|
|
|
void OnAnimatorMove()
|
|
{
|
|
m_Agent.velocity = m_Animator.deltaPosition / Time.deltaTime;
|
|
}
|
|
|
|
|
|
bool FindAPath(float range, bool awayFromPlayer = true)
|
|
{
|
|
for (int i = 0; i < m_maxTrials; i++)
|
|
{
|
|
Vector3 dest;
|
|
if (awayFromPlayer)
|
|
{
|
|
dest = transform.position + (transform.position - m_Player.transform.position).normalized * range;
|
|
}
|
|
else
|
|
{
|
|
dest = startPosition;
|
|
}
|
|
dest += new Vector3(Random.Range(-range * .5f - 2f, range * .5f + 2f), 0, Random.Range(-range * .5f - 2f, range * .5f + 2f));
|
|
NavMeshPath path = new NavMeshPath();
|
|
m_Agent.CalculatePath(dest, path);
|
|
if (path.status != NavMeshPathStatus.PathInvalid)
|
|
{
|
|
m_Agent.SetPath(path);
|
|
destination = dest;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
// Update is called once per frame
|
|
void Update()
|
|
{
|
|
switch (m_state)
|
|
{
|
|
case State.IDLE:
|
|
if (m_timer > m_targetTime)
|
|
{
|
|
SetState(State.WALK);
|
|
}
|
|
break;
|
|
case State.WALK:
|
|
if (m_Agent.remainingDistance < StoppingDistance)
|
|
{
|
|
SetState(State.IDLE);
|
|
}
|
|
break;
|
|
case State.RUN:
|
|
if (m_Agent.remainingDistance < StoppingDistance)
|
|
{
|
|
SetState(State.RUN);
|
|
}
|
|
break;
|
|
}
|
|
if (m_state != State.RUN)
|
|
{
|
|
float dist = (m_Player.transform.position - transform.position).magnitude;
|
|
if (dist < m_minPlayerDistance)
|
|
{
|
|
if (!FindAPath(m_wanderRange, true))
|
|
{
|
|
Debug.LogError("Animal AI: didn't find a path");
|
|
}
|
|
}
|
|
}
|
|
|
|
m_timer += Time.deltaTime;
|
|
}
|
|
}
|
|
} |