Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Bug Helping , I spend three hours but useless

Discussion in 'Animation' started by TonyStrack1, May 17, 2023.

  1. TonyStrack1

    TonyStrack1

    Joined:
    May 17, 2023
    Posts:
    1
    NullReferenceException: Object reference not set to an instance of an object
    EnemyControl.OnEnable () (at Assets/Scripts/Characters/EnemyControl.cs:72)

    Thank very much

    Code (CSharp):
    1.  
    2. [code=CSharp]public class Signleton<T> : MonoBehaviour where T : Signleton<T>
    3. {
    4.     private static T instance;
    5.  
    6.     public static T Instance
    7.     {
    8.         get { return instance; }
    9.         set { instance = value; }
    10.     }
    11.  
    12.     //只允许继承类访问的函数变量与方法
    13.     //纯虚函数
    14.     protected virtual void Awake()
    15.     {
    16.         if(instance != null) Destroy(gameObject);
    17.         else instance = (T)this;
    18.     }
    19.  
    20.     public static bool IsInitialized
    21.     {
    22.         get { return instance != null; }
    23.     }
    24.  
    25.     protected virtual void OnDestroy()
    26.     {
    27.         if(instance == this)
    28.         {
    29.             instance = null;
    30.         }
    31.     }
    32.  
    33. }
    public class EnemyControl : MonoBehaviour , IEndGameObserver
    {
    private NavMeshAgent agent;
    private EnemyStates enemystates;
    private Animator Anim;
    private Collider Coll;

    [Header("Basic Setting")]
    public float sighRadius;
    private GameObject attacktarget;
    public bool isGuard;
    private float speed;
    public float LookAtTime;
    private float remainLookAtTime;
    private CharacterStats characterStats;
    private float lastAttackTime;
    private Vector3 guardPos;
    private Quaternion guardRotation;
    //配合动画
    bool isWalk;
    bool isChase;
    bool isFollow;
    bool Critical;
    bool isDeath;
    bool PlayerDead;

    [Header("Patrol State")]
    public float patroRange;
    private Vector3 wayPoint;
    private Vector3 targetPoint;

    private void Awake()
    {
    agent = GetComponent<NavMeshAgent>();
    Anim = GetComponent<Animator>();
    Coll = GetComponent<Collider>();
    speed = agent.speed;
    targetPoint = transform.position;
    remainLookAtTime = LookAtTime;
    guardPos = transform.position;
    guardRotation = transform.rotation;
    characterStats = GetComponent<CharacterStats>();
    }

    private void Start()
    {
    if(isGuard)
    {
    enemystates = EnemyStates.GUARD;
    }
    else
    {
    enemystates = EnemyStates.PATROL;
    GetNewWayPoint();
    }
    }

    private void OnEnable()
    {
    GameManager.Instance.AddObserver(this);
    }

    private void Update()
    {
    isDeath = characterStats.CurrentHealth == 0;
    if(!PlayerDead)
    {
    SwitchStates();
    SwitchAnim();
    lastAttackTime -= Time.deltaTime;
    }
    }

    private void SwitchAnim()
    {
    Anim.SetBool("walk", isWalk);
    Anim.SetBool("chase", isChase);
    Anim.SetBool("follow", isFollow);
    Anim.SetBool("Critical", characterStats.isCritical);
    Anim.SetBool("Death", isDeath);
    }

    private void SwitchStates()
    {
    //如果死了 , 切换死亡状态
    if(isDeath)
    {
    enemystates = EnemyStates.DEAD;
    }
    else if(FoundPlayer())
    {
    //如果发现Player ,切换CHASE
    enemystates = EnemyStates.CHASE;
    }

    switch (enemystates)
    {
    case EnemyStates.GUARD:
    isChase = false;
    if(transform.position != guardPos)
    {
    isWalk = true;
    agent.isStopped = false;
    agent.destination = guardPos;
    if(Vector3.SqrMagnitude(transform.position - guardPos) <= agent.stoppingDistance)
    {
    isWalk = false;
    transform.rotation = Quaternion.Lerp(transform.rotation, guardRotation, 0.01f);
    }
    }
    break;
    case EnemyStates.PATROL:
    isChase = false;
    agent.speed = speed * 0.5f;
    //判断是否走到了某个点
    if(Vector3.Distance(wayPoint , transform.position) <= agent.stoppingDistance)
    {
    isWalk = false;
    if(remainLookAtTime > 0) remainLookAtTime -= Time.deltaTime;
    else GetNewWayPoint();
    }
    else
    {
    isWalk = true;
    agent.destination = wayPoint;
    }
    break;
    case EnemyStates.CHASE:
    //追击Player
    //Player脱离,回归原状态
    isWalk = false;
    isChase = true;
    agent.speed = speed;
    //没找到
    if(!FoundPlayer())
    {
    isFollow = false;
    if (remainLookAtTime > 0)
    {
    agent.destination = transform.position;
    remainLookAtTime -= Time.deltaTime;
    }
    else
    {
    if (isGuard) enemystates = EnemyStates.GUARD;
    else enemystates = EnemyStates.PATROL;
    }
    }
    else
    {
    //找到了
    //启动追击
    isFollow = true;
    agent.isStopped = false;
    agent.destination = attacktarget.transform.position;

    //在攻击范围内则重拳出击
    if(TargetInAttackRange() || TargetInSkillRange())
    {
    isFollow = false;
    agent.isStopped = true;

    if(lastAttackTime < 0)
    {
    lastAttackTime = characterStats.attackData.CoolDown;
    //暴击判断
    //随机数值是否小于暴击率,如果是 则暴击
    characterStats.isCritical = Random.value < characterStats.attackData.CriticalChance;
    //执行攻击
    Attack();
    }
    }
    }
    break;
    case EnemyStates.DEAD:
    Coll.enabled = false;
    agent.enabled = false;
    Destroy(gameObject, 2);
    break;
    }
    }

    //攻击方法
    private void Attack()
    {
    transform.LookAt(attacktarget.transform);
    if(TargetInAttackRange())
    {
    //普通攻击动画
    Anim.SetTrigger("Attack");
    }
    if(TargetInSkillRange())
    {
    //技能攻击动画
    Anim.SetTrigger("Skill");
    }
    }

    //判断Enemy是否找到了Plyaer
    bool FoundPlayer()
    {
    var colliders = Physics.OverlapSphere(transform.position, sighRadius);
    foreach(var target in colliders)
    {
    if (target.CompareTag("Player"))
    {
    attacktarget = target.gameObject;
    return true;
    }
    }
    attacktarget = null;
    return false;
    }

    private void GetNewWayPoint()
    {
    remainLookAtTime = LookAtTime;
    float randomX = Random.Range(-patroRange, patroRange);
    float randomZ = Random.Range(-patroRange, patroRange);
    Vector3 randomPoint = new Vector3(randomX + targetPoint.x, transform.position.y , targetPoint.z + randomZ);
    NavMeshHit hit;
    wayPoint = NavMesh.SamplePosition(randomPoint, out hit , patroRange , 1) ? hit.position : this.transform.position;
    }

    private bool TargetInAttackRange()
    {
    if (attacktarget != null)
    {
    return Vector3.Distance(attacktarget.transform.position, this.transform.position) <= characterStats.attackData.AttackRange;
    }
    return false;
    }

    private bool TargetInSkillRange()
    {
    if (attacktarget != null)
    return Vector3.Distance(attacktarget.transform.position, this.transform.position) <= characterStats.attackData.SkillRange;
    return false;
    }

    private void OnDrawGizmosSelected()
    {
    Gizmos.color = Color.blue;
    Gizmos.DrawWireSphere(transform.position, sighRadius);
    }

    //Animation Event
    private void Hit()
    {
    if(attacktarget != null)
    {
    var targetStats = attacktarget.GetComponent<CharacterStats>();
    targetStats.TakeDamage(characterStats, targetStats);
    }
    }

    //获取 Player 消失的广播
    public void EndNotify()
    {
    //获取动画
    //停止所有移动
    //停止Agent
    Debug.Log("Player已死");
    Anim.SetBool("Win", true);
    PlayerDead = true;
    isChase = false;
    isWalk = false;
    attacktarget = null;
    }
    }[/code]
    Code (CSharp):
    1. public class GameManager : Signleton<GameManager>
    2. {
    3.     public CharacterStats playerStats;
    4.  
    5.     List<IEndGameObserver> endGameObservers = new List<IEndGameObserver>();
    6.  
    7.     protected override void Awake()
    8.     {
    9.         base.Awake();
    10.     }
    11.  
    12.     public void RigisterPlayer(CharacterStats player)
    13.     {
    14.         playerStats = player;
    15.     }
    16.  
    17.     public void AddObserver(IEndGameObserver observer)
    18.     {
    19.         endGameObservers.Add(observer);
    20.         Debug.Log(endGameObservers.Count);
    21.     }
    22.  
    23.     public void RemoveObserver(IEndGameObserver observer)
    24.     {
    25.         endGameObservers.Remove(observer);
    26.     }
    27.  
    28.     public void NotifyObserver()
    29.     {
    30.         foreach (var observer in endGameObservers)
    31.         {
    32.             observer.EndNotify();
    33.         }
    34.     }
    35. }