Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using UnityEngine;
- using UnityEngine.AI;
- using UnityEngine.Events;
- using static UnityEngine.GraphicsBuffer;
- [RequireComponent(typeof(NavMeshAgent))]
- [RequireComponent(typeof(Animator))]
- [RequireComponent(typeof(AudioSource))]
- public class ZombieJCLS : MonoBehaviour
- {
- /*
- === Animation ===
- Walk = bool
- Dead = bool
- Food = bool
- Hit = triger
- Attack = triger
- Detect = triger
- */
- [SerializeField] NavMeshAgent agent;
- [SerializeField] Animator animator;
- [SerializeField] GameObject player;
- [SerializeField] AudioSource audioSource;
- [Header("=== Audio ===")]
- public SAudioClip[] AudioClips = new SAudioClip[]
- {
- new SAudioClip() { name = "Dead" },
- new SAudioClip() { name = "Hit" },
- new SAudioClip() { name = "Attack" },
- new SAudioClip() { name = "DetecPlayer" },
- new SAudioClip() { name = "RandomDestination" },
- new SAudioClip() { name = "UnAgro" },
- new SAudioClip() { name = "Food" },
- };
- [Header("=== Life ===")]
- [SerializeField] double HealPoint = 200;
- [Header("=== Range ===")]
- [SerializeField] float DetectPlayerRange = 10;
- [SerializeField] float AttackPlayerRange = 1;
- [SerializeField] float RandomRadiusDestination = 3f;
- [Header("Delay Random Destination")]
- [SerializeField] float RandomDestinationDelay = 3f;
- float RandomRadiusDestinationPause;
- [Header("Delay Attack")]
- [SerializeField] float AttackDelay = 0.5f;
- float AttackPause;
- [Header("Hit Damage Zombie")]
- public HitDmg[] HitProps = new HitDmg[]
- {
- new HitDmg() { name = "Projectile", damage = 10 }
- };
- bool IsHitDamage;
- [Header("Delay after Hit Damage")]
- [SerializeField] float DelayAfterHit = 0.5f;
- float DelayAfterPause;
- [Header("Delay after Detecte Player")]
- [SerializeField] float DelayAfterDetecte = 2f;
- float DetecteAfterPause;
- [SerializeField] float viewRadius = 100;
- [SerializeField] float viewAngle = 90;
- [Header("Zombie Damage player")]
- [SerializeField] float Damage = 20;
- [Header("Add function give damage player")]
- public HitPlayerDamage AttackCallbackPlayer;
- [Header("Delay quand il mange")]
- [SerializeField] float FoodDelay = 2f;
- float FoodPause;
- Transform FoodTarget;
- public LayerMask layerMaskCadravre;
- bool IsTargetAManger;
- [Header("Animations")]
- public AnimationNameKey[] AnimationNameKeys = new AnimationNameKey[]
- {
- new AnimationNameKey() { KeyName = "Attack", AnimationName = "Zombie Attack" },
- new AnimationNameKey() { KeyName = "Detect", AnimationName = "Zombie Scream 0" }
- };
- [System.Serializable]
- public class HitPlayerDamage : UnityEvent<float> { }
- [System.Serializable]
- public struct HitDmg
- {
- public string name;
- public float damage;
- }
- [System.Serializable]
- public struct SAudioClip
- {
- public string name;
- public AudioClip clip;
- }
- [System.Serializable]
- public struct AnimationNameKey
- {
- public string KeyName;
- public string AnimationName;
- }
- string lastAudioClip;
- public bool IsAgro { get; private set; }
- void PlayAudio(string name, bool spam = false)
- {
- if (lastAudioClip != name || spam)
- {
- if (!audioSource)
- return;
- lastAudioClip = name;
- if (spam is false)
- audioSource.Stop();
- if ((audioSource.isPlaying && spam is true) is false)
- foreach (SAudioClip clip in AudioClips)
- {
- if (clip.name == name)
- {
- audioSource.clip = clip.clip;
- audioSource.Play();
- return;
- }
- }
- }
- }
- void Start()
- {
- agent = GetComponent<NavMeshAgent>();
- animator = GetComponent<Animator>();
- audioSource = GetComponent<AudioSource>();
- }
- bool IsPointInTriangle(Vector3 a, Vector3 b, Vector3 c, Vector3 target)
- {
- float alpha = ((b.z - c.z) * (target.x - c.x) + (c.x - b.x) * (target.z - c.z)) /
- ((b.z - c.z) * (a.x - c.x) + (c.x - b.x) * (a.z - c.z));
- float beta = ((c.z - a.z) * (target.x - c.x) + (a.x - c.x) * (target.z - c.z)) /
- ((b.z - c.z) * (a.x - c.x) + (c.x - b.x) * (a.z - c.z));
- float gamma = 1.0f - alpha - beta;
- return (alpha > 0) && (beta > 0) && (gamma > 0);
- }
- bool IsInVision(Vector3 position)
- {
- Vector3 a = Quaternion.AngleAxis(-viewAngle / 2, transform.up) * transform.forward;
- Vector3 b = Quaternion.AngleAxis(viewAngle / 2, transform.up) * transform.forward;
- Vector3 a1 = transform.position + (a * viewRadius);
- Vector3 b1 = transform.position + (b * viewRadius);
- Debug.DrawLine(transform.position, a1, Color.green);
- Debug.DrawLine(transform.position, b1, Color.green);
- return IsPointInTriangle(transform.position, a1, b1, position);
- }
- void Update()
- {
- agent.stoppingDistance = AttackPlayerRange;
- if (!player)
- {
- Debug.LogError(this.name + " : Zombie à pas de player en ref !");
- return;
- }
- if (IsHitDamage)
- {
- if (DelayAfterPause >= DelayAfterHit)
- {
- IsHitDamage = false;
- DelayAfterPause = 0;
- }
- DelayAfterPause += 1 * Time.deltaTime;
- return;
- }
- if (HealPoint <= 0)
- {
- PlayAudio("Dead");
- animator.SetTrigger("Dead");
- Destroy(this.gameObject, 5f);
- return;
- }
- float velocity = agent.velocity.magnitude / agent.speed;
- animator.SetBool("Walk", velocity > 0.3);
- float PlayerDistance = Vector3.Distance(transform.position, player.transform.position);
- bool isReachable = PathIsReachable(agent, player.transform.position);
- bool isInVision = IsInVision(player.transform.position);
- bool IsDetectPlayer =
- (PlayerDistance < DetectPlayerRange)
- && isReachable && (IsAgro ? true : isInVision);
- if ((IsDetectPlayer) is false )
- {
- // ==== à Perdu l'agro ====
- if (IsAgro)
- {
- PlayAudio("UnAgro");
- agent.SetDestination(this.transform.position);
- IsAgro = false;
- }
- // ==== Cherche un truc a manger ====
- if (IsTargetAManger is false)
- if (Physics.SphereCast(this.transform.position, 3,
- transform.forward, out RaycastHit hit, 10, layerMaskCadravre))
- {
- FoodTarget = hit.transform;
- agent.SetDestination(hit.transform.position);
- IsTargetAManger = true;
- }
- // ==== Je Ganbade ====
- if (IsTargetAManger is false)
- {
- //Debug.Log("Je Ganbade");
- RandomDestination();
- animator.SetBool("Food", false);
- }
- // ==== J'ai a mangé ====
- if (IsTargetAManger is true && IsAgro is false)
- {
- if (FoodTarget)
- {
- float d = Vector3.Distance(FoodTarget.position, transform.position);
- if (d < (agent.stoppingDistance + 0.1f))
- {
- PlayAudio("Food", true);
- if (FoodPause >= FoodDelay)
- {
- //Destroy(FoodTarget.gameObject);
- IsTargetAManger = false;
- FoodPause = 0;
- }
- FoodPause += 1 * Time.deltaTime;
- animator.SetBool("Food", true);
- }
- }
- else
- {
- IsTargetAManger = false;
- FoodPause = 0;
- }
- }
- return;
- }
- else
- {
- bool IsAttackRange = PlayerDistance
- < (agent.stoppingDistance) && isInVision;
- if (!IsAttackRange)
- {
- if (IsAgro is false)
- {
- PlayAudio("DetecPlayer");
- animator.SetTrigger("Detect");
- }
- IsAgro = true;
- LookAt(player.transform.position, 2);
- if (!animator.GetCurrentAnimatorStateInfo(0).IsName(GetAnimationName("Detect")))
- {
- AttackPause = 0;
- IsTargetAManger = false;
- if (
- agent.pathStatus == NavMeshPathStatus.PathComplete
- && PlayerDistance <= agent.stoppingDistance
- )
- {
- LookAt(player.transform.position, 2);
- }
- else
- {
- if (DetecteAfterPause >= DelayAfterDetecte)
- {
- agent.SetDestination(player.transform.position);
- Debug.DrawLine(transform.position, player.transform.position, Color.yellow);
- DetecteAfterPause = 0;
- }
- DetecteAfterPause += 1 * Time.deltaTime;
- }
- }
- }
- else
- {
- if(isInVision)
- Attack();
- DetecteAfterPause = 0;
- }
- RandomRadiusDestinationPause = 0;
- }
- }
- private void OnTriggerEnter(Collider other)
- {
- foreach (HitDmg hitprop in HitProps)
- {
- if (hitprop.name == other.tag)
- {
- IsHitDamage = true;
- DelayAfterPause = 0;
- this.HealPoint -= hitprop.damage;
- animator.SetTrigger("Hit");
- PlayAudio("Hit");
- Destroy(other.gameObject);
- return;
- }
- }
- }
- void RandomDestination()
- {
- //========== RandomDestination ==========//
- if (RandomRadiusDestinationPause >= RandomDestinationDelay)
- {
- float randomAngle = Random.Range(0, 2 * Mathf.PI);
- float randomRadius = Random.Range(agent.stoppingDistance + 1, RandomRadiusDestination);
- float x = randomRadius * Mathf.Cos(randomAngle);
- float y = randomRadius * Mathf.Sin(randomAngle);
- Vector3 nextDestination = new Vector3(x, 0, y);
- nextDestination += transform.position;
- debugPosition = nextDestination;
- if (NavMesh.SamplePosition(nextDestination,
- out NavMeshHit hit, RandomRadiusDestination, 1))
- agent.SetDestination(hit.position);
- PlayAudio("RandomDestination", true);
- if (
- (agent.pathStatus == NavMeshPathStatus.PathPartial
- || agent.pathStatus == NavMeshPathStatus.PathInvalid) is false
- )
- RandomRadiusDestinationPause = 0;
- }
- RandomRadiusDestinationPause += 1 * Time.deltaTime;
- Debug.DrawLine(transform.position, agent.destination, Color.red);
- }
- void LookAt(Vector3 target, float speed = 1)
- {
- Vector3 dir = target - transform.position;
- dir.y = 0;
- Quaternion rot = Quaternion.LookRotation(dir);
- transform.rotation = Quaternion.Slerp(transform.rotation, rot, speed * Time.deltaTime);
- }
- string GetAnimationName(string KeyName)
- {
- foreach(AnimationNameKey animationNameKey in AnimationNameKeys)
- {
- if (animationNameKey.KeyName == KeyName)
- return animationNameKey.AnimationName;
- }
- return null;
- }
- void Attack()
- {
- if (AttackPause >= AttackDelay)
- {
- if (animator.GetCurrentAnimatorStateInfo(0).IsName(GetAnimationName("Attack")))
- return;
- //========== Attack ==========//
- animator.SetTrigger("Attack");
- PlayAudio("Attack", true);
- if (AttackCallbackPlayer != null)
- AttackCallbackPlayer.Invoke(Damage);
- AttackPause = 0;
- }
- AttackPause += 1 * Time.deltaTime;
- }
- bool PathIsReachable(NavMeshAgent agentNav, Vector3 position)
- {
- NavMeshPath navMeshPath = new NavMeshPath();
- return agentNav.CalculatePath(position, navMeshPath)
- && navMeshPath.status == NavMeshPathStatus.PathComplete;
- }
- Vector3 debugPosition;
- void OnDrawGizmos()
- {
- Gizmos.color = Color.green;
- Gizmos.DrawWireSphere(transform.position, DetectPlayerRange);
- Gizmos.color = Color.red;
- Gizmos.DrawWireSphere(transform.position, agent.stoppingDistance);
- Gizmos.color = Color.blue;
- Gizmos.DrawWireSphere(debugPosition, 0.5f);
- }
- public void Hurt()
- {
- Debug.Log("Hurt");
- if (IsAgro is false)
- {
- PlayAudio("DetecPlayer");
- animator.SetTrigger("Detect");
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment