3D RPG Course | Core | Unity学习笔记(四)

(一)敌人创建与基本参数的调整

        课程中使用的的怪物模型资源Assert地址.模型不能正常显示就升级到URP。如果模型材质不满意可在其子对象中调整材质,但在hierarchy中修改的材质属性也会反映到其他使用相同材质的物体上。

        接下来创建脚本EnemyController.cs用于控制敌人,获取获得Agent的控制权并在unity中修改Agent数据。为敌人添加碰撞体组件来让MouseManager脚本能够识别到敌人。可以使用自动机来控制敌人的状态切换,为了简化开发可先使用switch语句代替。使用enum类型表示敌人的状态,通过switch语句组成的方法来实现状态的切换。

        接下来可以在鼠标控制的代码中完成对敌人的光标切换。首先需要将敌人对象的layer设为Enemy,并在URPSetting文件中将filter的layer里加上Enemy层,从而将上一节的遮挡剔除也应用到所有敌人身上,最后将敌人Tag改为对应的值。

                

(二)协程实现移动到敌人并攻击

        在MouseManager.cs中创建一个新的事件OnEnemyClicked来实现点击敌人,在MouseControl()方法中补充点击到敌人的行为,完成后在PlayerController.cs中添加事件和方法。

        所添加的攻击函数EventAttack(GameObject target),当开始移动时需要使用协程的方式同步判断距离敌人的距离是否满足攻击条件,当靠的足够近后就开始攻击。

        在编写攻击代码之前,需要先为角色添加攻击动画。在Animator编辑器中为player添加一个trigger类型的变量Attack,并将攻击动画Attack Base添加进Animator,然后从移动到攻击设置转换条件即变量Attack的激活与关闭(同时取消退出时间),并从攻击到移动使用时间为1的自动退出。冷却时间的减少则要通过update函数控制。

        写好协程后,使用StartCoroutine(MoveToAttackTarget())在EventAttack中执行.

        运行后可以发现无法在攻击后移动,因为攻击函数把agent关闭了,在移动函数中先打开即可.

        想要实现前往攻击过程中打断并移动,需要在脚本中打断协程。在地面移动函数中先打断所有协程即可。

        PlayerController.cs:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;//用于调用NavMeshAgent

public class PlayerController : MonoBehaviour
{
    private NavMeshAgent agent;
    private Animator anim;//Animator controller
    private GameObject attackTarget;
    private float lastAttackTime;//攻击冷却


    private void Awake()
    {
        agent = GetComponent<NavMeshAgent>();//获得NavMeshAgent方法
        anim = GetComponent<Animator>();
    }

    private void Update()
    {
        SwitchAnimation();
        lastAttackTime -= Time.deltaTime;//冷却时间减少
    }

    private void Start()
    {
        MouseManager.Instance.OnMouseClicked+=MoveToTarget;//将方法注册到事件中,每当事件启用就会执行该方法
        MouseManager.Instance.OnEnemyClicked += EventAttack;

    }
    private void SwitchAnimation()//获得人物Speed并写入animator controller
    {
        anim.SetFloat("Speed", agent.velocity.sqrMagnitude);//sqrMagnitude可将Vector3转换为浮点数值
    }

    public void MoveToTarget(Vector3 target)//参数要与注册事件的参数一致,实现点击地面移动
    {
        StopAllCoroutines();//打断所有协程,实现改变移动
        agent.isStopped = false;//确保每次点击到地面都是可移动的
        agent.destination = target;
    }
    private void EventAttack(GameObject target)//功能:点击到object后移动并攻击
    {
        if (target != null)
        {
            attackTarget = target;//设定目标
            StartCoroutine(MoveToAttackTarget());

        }
    }

    IEnumerator MoveToAttackTarget()//攻击函数的移动协程
    {
        agent.isStopped = false;//确保每次点击到敌人都是可移动的
        //移动
        transform.LookAt(attackTarget.transform);//首先让角色面对目标
        while(Vector3.Distance(attackTarget.transform.position,transform.position)>1)//循环判断距离是否大于攻击距离
        {
            agent.destination = attackTarget.transform.position;
            yield return null;//该语句使下一帧继续执行该循环,直到不满足循环条件
        }
        agent.isStopped = true;
        //攻击
        if (lastAttackTime < 0)
        {
            anim.SetTrigger("Attack");//激活Animator的攻击动画。
            //CD
            lastAttackTime = 0.5f;
        }

    }

}

(三)cinemachine的自由移动相机

        使用cinemachine的freelook camera可以实现大多数第三人称摄像机需求,创建后先屏蔽原本的虚拟摄像机,然后设置好freelook camera的跟随和目标。此时相机和角色之间的红圈为相机的可移动范围,相机会在三个圈围成的球体内移动,在freelook camera的axis control中设置移动的范围和方式。在unity的edit-project settings-input manager中有所有的Axes输入,寻找到合适的控制方法后,复制到freelook camera中即可。摄像机的跟踪方式等参数可在orbits中更改。

        freelook camera的最终参数:

(四)敌人追击的实现

        首先要在EnemyController.cs脚本中添加相关参数,并在状态切换的方法中实现识别角色并切换到追踪状态。查找对象一定范围内是否有指定对象的方法要使用Physics.OverlapSphere,寻找中心点周围球体范围的所有碰撞体。若查找到玩家,就将Enemy的状态更改为追踪。想要检测到玩家,需要为player先设置好tag和碰撞体。

        敌人和玩家的修改可以保存为预制体,已有预制体的可以使用overrides等方法接受修改。

        接下来要实现敌人追击的动画和移动。首先敌人的追击要使用上面的范围搜寻,然后朝玩家方向移动,超出范围则停止,最后在攻击范围内则执行攻击动画,与Animator协同工作。

        创建slime的Animator,希望由脚本控制动画转换参数时,可将参数的修改放入update中。Animator如下:

其中注意修改Layer的权重,权重为0的Layer不会生效,权重为覆盖之前动画Layer的百分比。

追击方法的实现:

private void ChasePlayer()
{
    isWalk = false;
    isChase = true;//动画控制
    agent.speed = speed;
    if(FoundPlayer()==false)//再次判断是为了实现停止追击
    {
        isFollow = false;
        agent.destination = transform.position;//脱战后停止有一点延迟,通过此方法消除延迟
    }
    else//使用Navmesh追击
    {
        isFollow = true;
        agent.destination = attackTarget.transform.position;
    }
}

(五)巡逻点与巡逻状态

        为了编辑方便,一些参数的效果可以通过脚本在Sence窗口画出来,如EnemyController.cs中的几个范围变量,方法属于unity自带的方法,因此只要实现即可,代码如下:

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

        然后使用代码在指定范围内随机生成一个巡逻点:

private void GetNewWayPoint()
{
    //生成随机巡逻点
    float rx = Random.Range(-patrolRadius, patrolRadius);
    float rz = Random.Range(-patrolRadius, patrolRadius);
    Vector3 tempWayPoint = new Vector3(guardPosition.x + rx, transform.position.y,guardPosition.z + rz);

    //判断是否可移动,防止出现移动bug
    NavMeshHit hit;//检测信息
    //检测函数,将返回一个bool值判断是否成立,可移动则设置移动点,反之不移动
    wayPoint = NavMesh.SamplePosition(tempWayPoint, out hit, patrolRadius, 1) ? hit.position : transform.position;
    
}  

        然后执行Patrol状态:

 case EnemyStates.PATROL:
     isChase = false;
     agent.speed = speed * 0.5f;//设置动画和巡逻速度
     if(Vector3.Distance(transform.position,wayPoint)<=agent.stoppingDistance)//敌人到达巡逻点停止距离,获取新的巡逻点
     {
         isWalk = false;
         GetNewWayPoint();
     }
     else//敌人以行走动画前往巡逻点
     {
         isWalk = true;
         agent.destination = wayPoint;
     }
     break;

        此外,可以使用计时器的方式实现敌人巡逻到一个巡逻点后先停止一会再找下一个巡逻点,其中每次计时器减少方式为remainLookAtTime -= Time.deltaTime;        此外为了实现拉脱后仍然能回到原有的巡逻状态,需要在拉脱判断处添加状态切换。


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
学习Unity3D时,以下是一些重要的笔记: 1. Unity3D基础知识: - 游戏对象(Game Objects)和组件(Components):了解游戏对象的层次结构和组件的作用。 - 场景(Scenes)和摄像机(Cameras):学会如何创建场景并设置摄像机视角。 - 材质(Materials)和纹理(Textures):掌握如何创建和应用材质和纹理。 - 动画(Animations):学习如何创建和控制游戏对象的动画。 2. 脚本编程: - C#语言基础:了解C#语言的基本语法和面向对象编程概念。 - Unity脚本编写:学习如何编写脚本来控制游戏对象的行为和交互。 - 常见组件和功能:掌握常见的Unity组件和功能,如碰撞器(Colliders)、刚体(Rigidbodies)、触发器(Triggers)等。 3. 游戏开发流程: - 设计游戏关卡:了解如何设计游戏场景和关卡,包括布局、道具、敌人等。 - 游戏逻辑实现:将游戏规则和玩家交互转化为代码实现。 - UI界面设计:学习如何设计游戏中的用户界面,包括菜单、计分板等。 - 游戏优化和调试:优化游戏性能,解决常见的错误和问题。 4. 学习资源: - Unity官方文档和教程:官方提供了大量的文档和教程,逐步引导你学习Unity3D。 - 在线教程和视频教程:网上有很多免费和付费的Unity教程和视频教程,可根据自己的需求选择学习。 - 社区论坛和博客:加入Unity开发者社区,与其他开发者交流并获取帮助。 通过系统地学习这些内容,你将能够掌握Unity3D的基础知识并开始开发自己的游戏项目。记得不断实践和尝试,不断提升自己的技能!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值