Welcome to GEMENTAR TOUR PUO V2 Development Documentation. Enjoy your stay!

This is an old revision of the document!


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);
    }
}

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.

NavMesh Agent AI


QR Code
QR Code wiki:npc_prototyping (generated for current page)
Hello World!
DokuWiki with monobook... rules!