这套教程比较基础,在Udemy上评分很高,我觉得用作新人学习Unity非常合适,学习前提,最好是掌握一些基本C#编程。
P29章前主要是简单介绍了如何使用Unity自带的AI寻路烘焙,使用AI来制作角色的移动,相机的跟随,制作玩家的动画混合,并对动画进行更新。
玩家的移动主要通过射线检测碰撞,如果点击处没有寻路网格,玩家则不会前往,防止玩家走出世界之外。
还制作了攻击的基本逻辑和被攻击的敌人目标,点击敌人,角色会自动前往到敌人身边。
一些代码和教程有出入,自己做了一些修改,大致基本上一致。
以下是代码部分:
Mover
- using RPG.Combat;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.AI;
- using UnityEngine.UI;
-
- //角色的移动
- namespace RPG.Movement
- {
-
- public class Mover : MonoBehaviour
- {
-
- private NavMeshAgent navMeshAgent;
- private Fighter fighter;
- Animator animator;
-
- private void Start()
- {
- animator = GetComponent<Animator>();
- navMeshAgent = GetComponent<NavMeshAgent>();
- fighter = GetComponent<Fighter>();
- }
-
- private void Update()
- {
-
- UpdateAnimator();
- }
-
- /// <summary>
- /// 开始移动行为
- /// </summary>
- /// <param name="destination">移动的位置</param>
- public void StartMoveAction(Vector3 destination)
- {
- fighter.Cancel();
- MoveTo(destination);
- }
-
- /// <summary>
- /// 寻路移动到射线检测点
- /// </summary>
- /// <param name="hit"></param>
- public void MoveTo(Vector3 destination)
- {
- navMeshAgent.destination = destination;//获取寻路目的地 = 射线碰撞的点
- navMeshAgent.isStopped = false;
- }
-
- /// <summary>
- /// 停止寻路
- /// </summary>
- public void Stop()
- {
- navMeshAgent.isStopped = true;
- }
-
- /// <summary>
- /// 动画更新
- /// </summary>
- private void UpdateAnimator()
- {
- Vector3 velocity = navMeshAgent.velocity;//创建寻路速度
- Vector3 localVelocity = transform.InverseTransformDirection(velocity);// 将世界向前变换到本地空间:
- float speed = localVelocity.z;
-
- animator.SetFloat("forwardSpeed", speed);
- }
- }
- }
复制代码
PlayerController
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using RPG.Movement;
- using RPG.Combat;
-
-
-
- //角色的控制
- namespace RPG.Control
- {
-
- public class PlayerController : MonoBehaviour
- {
- private Mover mover;
-
- private void Start()
- {
- mover = GetComponent<Mover>();
- }
-
- private void Update()
- {
- if (InteractWithCombat()) return;
- if (InteractWithMovement()) return;
-
- }
-
-
- // 战斗交互
- private bool InteractWithCombat()
- {
- RaycastHit[] hits = Physics.RaycastAll(GetMouseRay());
- foreach (RaycastHit hit in hits)
- {
- CombatTarget target = hit.transform.GetComponent<CombatTarget>();//被射线击中的物体获取战斗目标组件
- if(target == null) continue;//为空则继续
-
- if(Input.GetMouseButtonDown(0))//按下左键
- {
- GetComponent<Fighter>().Attack(target);//攻击目标
-
- }
- return true;//射线找到目标
- }
- return false;//射线没有找到目标
- }
-
- // 移动和交互
- private bool InteractWithMovement()
- {
- RaycastHit hit;//存储射线碰撞的信息
- bool hasHit = Physics.Raycast(GetMouseRay(), out hit); //通过射线检测是否有接触到碰撞物体
- if (hasHit)//如果有检测到
- {
- if (Input.GetMouseButton(0))//如果按下鼠标左键
- {
- mover.StartMoveAction(hit.point);
-
- }
- return true;
- }
- return false;
- }
-
-
-
- //创建射线
- private static Ray GetMouseRay()
- {
- return Camera.main.ScreenPointToRay(Input.mousePosition);
-
- }
- }
- }
-
复制代码
Fighter
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using RPG.Movement;
-
-
- namespace RPG.Combat
- {
- //攻击
- public class Fighter : MonoBehaviour
- {
- [SerializeField] float weaponRange = 2f;//武器范围
-
- Transform target;
-
- private Mover mover;
- private bool isInRange;
-
- private void Start()
- {
- mover = GetComponent<Mover>();
- }
-
- private void Update()
- {
- if (target == null) return;
-
-
- if (target != null && !GetIsInRange())//目标不为空并且在距离范围内
- {
- mover.MoveTo(target.position);
- }
- else
- {
- mover.Stop();
- }
- }
-
- private bool GetIsInRange()
- {
- return Vector3.Distance(transform.position, target.position) < weaponRange;//创建玩家距离和敌人距离是否小于2
- }
-
- public void Attack(CombatTarget combatTarget)
- {
- target = combatTarget.transform;
-
- }
-
- public void Cancel()
- {
- target = null;
- }
- }
- }
复制代码
FollowCamera
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- public class FollowCamera : MonoBehaviour
- {
- [SerializeField]
- private Transform target;
-
- public Vector3 offset;
-
- private void LateUpdate()
- {
- transform.position = target.position + offset;
- }
- }
复制代码
CombatTarget
暂时为空,仅仅用于检测敌人脚本,将其挂在攻击目标上
|