Files
daluandou/Assets/Script/EnemyBaseMove.cs
T
huadexuan b80d31101c ```
feat(EnemyBaseMove): 添加重力系统和物理材质优化

- 添加重力加速度变量和垂直速度控制
- 实现applyGravity()和getVerticalVelocity()方法处理垂直运动
- 在Attack状态和静止时应用重力效果
- 为CharacterController添加新的物理材质引用
- 调整CharacterController中心位置从(0,0,0)到(0,1,0)
- 在场景中禁用根动作应用以配合自定义移动系统
```
2026-08-19 10:53:56 +08:00

218 lines
5.4 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
//移动速度
public float speed = 5f;
//重力加速度
public float gravity = -20f;
//活动范围
public float range = 500f;
//侦查范围
public float detectRange = 200f;
//攻击范围
public float attackRange = 5f;
//角色状态
private State state = State.Alert;
//攻击目标
public GameObject target;
//当前目标点
private Vector3 targetPos;
//初始位置坐标
private Vector3 startPos;
//动画控制器
private Animator animator;
// 角色控制器
private CharacterController controller;
//垂直速度
private float verticalVelocity;
//状态枚举
public enum State
{
//警戒巡逻
Alert,
//追踪状态
Track,
//攻击状态
Attack
}
// Start is called before the first frame update
void Start()
{
//初始化
animator = GetComponent<Animator>();
controller = GetComponent<CharacterController>();
//记录初始坐标
startPos = transform.position;
randomTargetPos();
}
// Update is called once per frame
void Update()
{
//攻击状态直接返回
if (state == State.Attack)
{
animator.SetInteger("speed", 0);
applyGravity();
return;
}
//获取侦查范围内除自己以外的Player层的单位
var players = Physics.OverlapSphere(transform.position, detectRange, LayerMask.GetMask("Player"));
//如果存在单位
if (players.Length > 0)
{
//找出标签是Friend的,并且不是自己
foreach (var player in players)
{
if (player.tag == "Friend" && player != gameObject)
{
//进入追逐状态
state = State.Track;
float dis = Vector3.Distance(transform.position, player.transform.position);
//和目标的距离在攻击范围外则朝目标移动
if (dis > attackRange)
{
move(player.transform.position - transform.position);
//打印动画speed的值
Debug.Log(animator.GetInteger("speed"));
}
else
{
attack(player);
}
return;
}
}
}
if (state == State.Track)
{
state = State.Alert;
}
//没有侦查到敌人则回到巡逻
state = State.Alert;
//角色在攻击状态则返回
if (state == State.Alert)
{
//移动
move(targetPos - transform.position);
//到达目标点时候随机目标点,只判断水平距离
Vector3 patrolOffset = transform.position - targetPos;
patrolOffset.y = 0;
if (patrolOffset.sqrMagnitude < 0.01f)
{
randomTargetPos();
}
}
}
//攻击
private void attack(Collider player)
{
//转向攻击目标
var direction = player.transform.position - transform.position;
direction.y = 0;
if (direction != Vector3.zero)
{
transform.rotation = Quaternion.LookRotation(direction, Vector3.up);
}
//攻击动画动作
animator.SetInteger("speed", 0);
animator.SetTrigger("attack");
state = State.Attack;
}
// 在 Animator 的 Attack 动画结束时调用此方法
public void OnAttackAnimationEnd()
{
//打印
Debug.Log("攻击结束");
state = State.Alert;
randomTargetPos();
}
//角色移动,持续到目标点
void move(Vector3 movement)
{
movement.y = 0;
if (movement == Vector3.zero)
{
animator.SetInteger("speed", 0);
applyGravity();
return;
}
//改变动画控制器的参数
animator.SetInteger("speed", 1);
//向目标点移动,同时应用垂直重力
Vector3 velocity = movement.normalized * speed;
velocity.y = getVerticalVelocity();
controller.Move(velocity * Time.deltaTime);
//改变角色朝向目标点,只改变y轴
transform.rotation = Quaternion.LookRotation(movement, Vector3.up);
transform.rotation = Quaternion.Euler(0, transform.rotation.eulerAngles.y, 0);
}
private float getVerticalVelocity()
{
if (controller.isGrounded && verticalVelocity < 0)
{
verticalVelocity = -2f;
}
else
{
verticalVelocity += gravity * Time.deltaTime;
}
return verticalVelocity;
}
private void applyGravity()
{
controller.Move(Vector3.up * getVerticalVelocity() * Time.deltaTime);
}
//随机目标点
private void randomTargetPos()
{
//以startPos为中心,在水平圆形范围内随机一个点
Vector2 randomOffset = Random.insideUnitCircle * range;
targetPos = startPos + new Vector3(randomOffset.x, 0, randomOffset.y);
}
}