YueZHeng_917 2023-02-17 23:00 采纳率: 57.9%
浏览 45
已结题

Unity,攻击动画不显示

我的Uinty版本是2020.3.31,我照抄了这个视频中的大部分代码,其中攻击动画的部分,我想的是:敌人会追踪玩家》当敌人追到玩家时》会停滞》展现攻击特效(如果玩家在特效范围内则掉血)》再停滞》追踪玩家。问题就在于,我想要在以下仅一个脚本中完成上述操作。我的代码是

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
[RequireComponent(typeof(NavMeshAgent))]
public class Enemy : LivingEntilty
{
    NavMeshAgent agent;//FY:导航网格代理 代理;
    //public Transform target;//FY:建立公有 变换 目标;
    Transform target;//FY:变换 目标;
    float attackDistanceThreshold = 1.5f;//攻击距离阈值
    float timebetweenAttack = 1f;//攻击时间的间隔
    float nextAttackTime;//攻击时间的间隔的中间数
    State currentState;//FY:状态 当前状态
    public GameObject gongjitexiao;//建立一个游戏物体————攻击特效

    public enum State
    {
        Idle,//待机
        Chasing,//追逐
        Attack,//攻击
    }

    protected override void Start()//索敌机制2
    {
        target = GameObject.Find("Player").transform;//FY:目标 = 游戏对象.寻找(“玩家”).变换;这里的“玩家”是Unity中玩家操控角色的名字
        base.Start();
        agent = GetComponent<NavMeshAgent>();//FY:目标=获取组件<导航网格代理>();
        StartCoroutine(UpdatePath(0.25f, new Vector3()));
        currentState = State.Chasing;//使之刷新出来就是追逐状态
    }

    
    void Update()
    {
        //索敌机制1:agent.SetDestination(target.position);//FY:代理.设置目的地(目标.位置);但是如果把此行代码打在Update里,就会每帧获取一次目标位置,甚消耗性能
        if (Time.time > nextAttackTime)
        {
            float distance = (target.position - transform.position).sqrMagnitude;
            if (distance < Mathf.Pow(attackDistanceThreshold, 2))
            {
                Attack();//调用Attack(攻击动画)的代码进行运行
            }
        }
    }

    #region 攻击动画
    void Attack()
    {
        currentState = State.Attack;
        agent.enabled = false;
        /*Vector3 originalPosition = transform.position;//FY:矢量3 原始位置 = 变换.位置;
        Vector3 attackPosition = target.position;//FY:矢量3 攻击位置 = 目标.位置;
        float percent = 0;
        float attackSpeed = 3;
        while (percent <= 1)
        {
            percent += Time.deltaTime * attackSpeed;
            float t = 4 * (-Mathf.Pow(percent, 2) + percent);//这个数它会当percent的值在0~1之间的时候它的值会从0~1再从1~0完美符合我们的需求,我们的需求是敌人攻击的玩家然后再回到原来的位置,和插值函数配合我们符合需求
            transform.position = Vector3.Lerp(originalPosition, attackPosition, t);
            yield return null;//yield return掉null就是等待一帧的意思
        }*/
        GameObject.Instantiate(gongjitexiao);//生成攻击特效
        Destroy(gongjitexiao, 1);//1秒后删除攻击特效
//我是第63行代码及就近
        currentState = State.Chasing;
        agent.enabled = true;
    }
    #endregion

    IEnumerator UpdatePath(float refreshRate,Vector3 targePosition)
    {
        while (target != null)
        {
            if(target != null)
            {
                targePosition = new Vector3(target.position.x, 0, target.position.z);
                if (!dead)
                {
                    agent.SetDestination(targePosition);
                }
            }
            yield return new WaitForSeconds(refreshRate);
        }
        
    }
}

问题在于第63行代码及就近地方,我想让敌人在攻击的时候,生成一个攻击特效,我想的方法就在那里。但在Unity中然并没有出现我所制定的攻击特效,我认为是这个代码不够完善(可能是没有指定生成的坐标或者是),但是我再尝试了“GameObject.Instantiate(gongjitexiao,gongjitexiao.position,gongjitexiao.rotation);”发现position和rotation划了红色波浪线。也不知道怎么修改,又给删了才没报错。
顺便想要问一下,开头说的停滞一段时间,在同一个脚本内,(希望教我一下能实现上述内容的所有可行的方案,或是指个详细、面对的教程),要怎么写才能实现开头说的停滞的要求

  • 写回答

2条回答 默认 最新

  • qq_46161207 2023-02-18 10:25
    关注

    根据你提供的代码,生成攻击特效的代码是GameObject.Instantiate(gongjitexiao);,但是没有指定生成的位置,所以特效可能被生成在了场景之外或者太远的地方。你可以尝试将生成特效的代码修改为GameObject.Instantiate(gongjitexiao, transform.position, transform.rotation);,这将在敌人所在的位置生成特效。如果你想要特效生成在其他位置,可以修改transform.position的值来指定生成位置。另外,如果特效在一秒后要被删除,可以使用Destroy函数的第二个参数来指定延迟删除的时间,例如Destroy(gongjitexiao, 1f);。

    要实现在同一个脚本中,停滞一段时间的功能,你可以使用C#中的协程(Coroutine)来实现。

    在Unity中,协程是一种特殊的函数,它可以在执行过程中暂停一段时间,然后再继续执行,常用于等待一段时间后再执行某个动作。使用协程可以避免使用Thread.Sleep()等等线程阻塞方法,从而保证游戏的流畅性。

    你可以在需要停滞的地方使用yield return new WaitForSeconds()语句,括号里面填写需要等待的时间(单位为秒),例如:

    
    yield return new WaitForSeconds(2f);
    

    上面的代码表示等待2秒后再执行下面的代码。

    下面是一个使用协程实现停滞一段时间的例子:

    using UnityEngine;
    using System.Collections;
    
    public class Example : MonoBehaviour
    {
        IEnumerator WaitAndPrint(float waitTime)
        {
            yield return new WaitForSeconds(waitTime);
            Debug.Log("WaitAndPrint " + Time.time);
        }
    
        void Start()
        {
            Debug.Log("Starting " + Time.time);
            StartCoroutine(WaitAndPrint(2.0f));
            Debug.Log("Before WaitAndPrint Finishes " + Time.time);
        }
    }
    

    在这个例子中,我们定义了一个WaitAndPrint的协程,用于等待一段时间后打印一条日志。在Start函数中,我们通过StartCoroutine方法启动这个协程,并在等待期间执行了一些其他操作。

    需要注意的是,协程只能在MonoBehaviour派生类中使用,而且协程只有在游戏物体处于激活状态时才会运行。如果需要在非激活状态下使用协程,可以考虑使用Unity提供的协程管理插件“UniTask”。

    望能给你提供思路

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 3月5日
  • 已采纳回答 2月25日
  • 创建了问题 2月17日