This is an old revision of the document!
Table of Contents
NPC Prototyping
ZombieNpcMovingNashMeshController Script
using Sirenix.OdinInspector; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class ZombieNpcMovingNashMeshController : MonoBehaviour { [BoxGroup("Debug Value")] [SerializeField] private string d_tranfsormName; [BoxGroup("Debug Value")] [SerializeField] private float d_remainingDistance; [BoxGroup("Debug Value")] [SerializeField] private float d_velocity; [BoxGroup("Movement Tweak")] [SerializeField] private float _walkSpeed = 1; [BoxGroup("Movement Tweak")] [SerializeField] private float _runSpeed = 3; [SerializeField] private List<Transform> _checkPoint; private int checkPointIndex = 0; private int currentIndex = 0; private NavMeshAgent _navMeshAgent; private ZombieAnimationController _zombieAnimationController; [SerializeField] private Transform movePositionTransform; private void Awake() { _navMeshAgent = GetComponent<NavMeshAgent>(); _zombieAnimationController = GetComponent<ZombieAnimationController>(); _navMeshAgent.updateRotation = false; } private void Update() { if (_navMeshAgent.remainingDistance <= _navMeshAgent.stoppingDistance) { currentIndex = checkPointIndex == _checkPoint.Count - 1 ? checkPointIndex = 0 : checkPointIndex += 1; } MoveAgentToDestination(_checkPoint[currentIndex]); } private void MoveAgentToDestination(Transform transform) { _navMeshAgent.destination = transform.position; d_tranfsormName = transform.gameObject.name; d_remainingDistance = _navMeshAgent.remainingDistance; d_velocity = _navMeshAgent.velocity.magnitude; if (_navMeshAgent.velocity.sqrMagnitude > Mathf.Epsilon) { this.transform.rotation = Quaternion.LookRotation(_navMeshAgent.velocity.normalized); } } [Button] public void MakeCharacterWalk() { _navMeshAgent.speed = _walkSpeed; } [Button] public void MakeCharacterRunning() { _navMeshAgent.speed = _runSpeed; } [Button] public void MakeCharacterPunch() { _zombieAnimationController.PlayAction(_zombieAnimationController.attack); } }
ZombieAnimationController Script
using Animancer; using Sirenix.OdinInspector; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class ZombieAnimationController : MonoBehaviour { private AnimancerComponent _Animancer; [SerializeField] public ClipTransition idle; [SerializeField] public ClipTransition moveFoward; [SerializeField] public ClipTransition runFoward; [SerializeField] public ClipTransition attack; [SerializeField] private AvatarMask _baseBody; [SerializeField] private AvatarMask _upperBody; private AnimancerLayer _baseLayer; private AnimancerLayer _upperBodyLayer; //private CharacterController _characterController; private NavMeshAgent _navMeshAgent; private void Awake() { Initialization(); InitializationAnim(); } private void Initialization() { //_characterController = GetComponent<CharacterController>(); _navMeshAgent = GetComponent<NavMeshAgent>(); _Animancer = GetComponentInChildren<AnimancerComponent>(); } private void InitializationAnim() { _baseLayer = _Animancer.Layers[0]; _upperBodyLayer = _Animancer.Layers[1]; _baseLayer.SetMask(_baseBody); _upperBodyLayer.SetMask(_upperBody); attack.Events.OnEnd = OnActionEnd; } private void Update() { //if(_characterController.velocity.magnitude > 1f) if (_navMeshAgent.velocity.magnitude > 1f) { _baseLayer.Play(moveFoward, 1f); } //if (_characterController.velocity.magnitude > 2f) if(_navMeshAgent.velocity.magnitude > 2f) { _baseLayer.Play(runFoward, 1f); } } bool _canBePlayed = true; public void PlayAction(ClipTransition clip) { if (!_canBePlayed) return; _upperBodyLayer.Play(clip); StartCoroutine(PlayActionDelay(clip.Clip.length)); } private IEnumerator PlayActionDelay(float length) { _canBePlayed = false; yield return new WaitForSeconds(length); _canBePlayed = true; } private void OnActionEnd() { _upperBodyLayer.StartFade(0, 1f); } }
Behaviour Tree
NPC Agro prototype
Agro
There's basically three layers of detection - outer layer when zombie heard shoots they will go agro, and this layer player need to escape from it to stop the agro. - first inner when player move close to zombie. - nearest layer for zombie detect when can it hit player.



