``` docs(readme): 更新文档说明 - 添加项目使用指南 - 完善API接口说明 - 修正错误的配置示例 ``` 注意:由于您提供的code differences部分为空,以上是一个示例模板。当您有具体的代码变更时,请提供详细的变更内容以便生成更准确的commit message。
245 lines
6.0 KiB
C#
245 lines
6.0 KiB
C#
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// 主角自动巡逻移动:不再支持点击地面移动(避免与拖动屏幕、建筑放置的输入冲突)。
|
|
/// 没有敌人时在己方主建筑周围小范围来回走动,所有移动被限制在基地附近(栓绳范围)。
|
|
/// 战斗组件发现敌人后调用 SetPatrolEnabled(false) 停止巡逻进行攻击。
|
|
/// </summary>
|
|
public class MainCharacterDebugMovement : MonoBehaviour
|
|
{
|
|
[Header("巡逻移动")]
|
|
[Min(0f)]
|
|
public float moveSpeed = 4f;
|
|
|
|
[Min(0f)]
|
|
public float patrolStopDistance = 0.15f;
|
|
|
|
[Min(0f)]
|
|
public float patrolPause = 1.5f;
|
|
|
|
[Header("巡逻区域(以主建筑为锚点)")]
|
|
[Min(0f)]
|
|
public float patrolRadius = 5f;
|
|
|
|
[Min(0f)]
|
|
public float leashRadius = 8f;
|
|
|
|
public string friendlyBuildingTag = "Friend";
|
|
|
|
private Animator animator;
|
|
private Transform baseAnchor;
|
|
private Vector3 fallbackAnchor;
|
|
private Vector3 patrolTarget;
|
|
private Vector3 chaseTarget;
|
|
private bool hasPatrolTarget;
|
|
private bool hasChaseTarget;
|
|
private float pauseTimer;
|
|
private bool patrolEnabled = true;
|
|
|
|
public bool IsMoving { get; private set; }
|
|
|
|
private Vector3 AnchorPosition
|
|
{
|
|
get
|
|
{
|
|
Vector3 position = baseAnchor != null ? baseAnchor.position : fallbackAnchor;
|
|
position.y = transform.position.y;
|
|
return position;
|
|
}
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
animator = GetComponent<Animator>();
|
|
fallbackAnchor = transform.position;
|
|
baseAnchor = FindMainBase();
|
|
SetWalking(false);
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (!patrolEnabled)
|
|
{
|
|
UpdateChase();
|
|
return;
|
|
}
|
|
|
|
if (pauseTimer > 0f)
|
|
{
|
|
pauseTimer -= Time.deltaTime;
|
|
IsMoving = false;
|
|
SetWalking(false);
|
|
return;
|
|
}
|
|
|
|
if (!hasPatrolTarget)
|
|
{
|
|
patrolTarget = GetNextPatrolPoint();
|
|
hasPatrolTarget = true;
|
|
}
|
|
|
|
Vector3 toTarget = patrolTarget - transform.position;
|
|
toTarget.y = 0f;
|
|
|
|
if (toTarget.magnitude <= patrolStopDistance)
|
|
{
|
|
hasPatrolTarget = false;
|
|
pauseTimer = patrolPause;
|
|
IsMoving = false;
|
|
SetWalking(false);
|
|
return;
|
|
}
|
|
|
|
Move(toTarget.normalized);
|
|
}
|
|
|
|
private void UpdateChase()
|
|
{
|
|
if (!hasChaseTarget)
|
|
{
|
|
IsMoving = false;
|
|
SetWalking(false);
|
|
return;
|
|
}
|
|
|
|
Vector3 toTarget = chaseTarget - transform.position;
|
|
toTarget.y = 0f;
|
|
|
|
if (toTarget.magnitude <= patrolStopDistance)
|
|
{
|
|
IsMoving = false;
|
|
SetWalking(false);
|
|
return;
|
|
}
|
|
|
|
// 追击同样受栓绳限制,不会完全离开基地
|
|
Move(toTarget.normalized);
|
|
}
|
|
|
|
private Transform FindMainBase()
|
|
{
|
|
Transform firstBuilding = null;
|
|
foreach (GameObject candidate in GameObject.FindGameObjectsWithTag(friendlyBuildingTag))
|
|
{
|
|
if (candidate == null || candidate.transform.root == transform.root)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (candidate.GetComponentInParent<BuildingHealth>() == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// 主建筑按名称优先匹配;找不到时退回第一个己方建筑
|
|
if (candidate.name.Contains("主要") || candidate.name.Contains("基地"))
|
|
{
|
|
return candidate.transform;
|
|
}
|
|
|
|
if (firstBuilding == null)
|
|
{
|
|
firstBuilding = candidate.transform;
|
|
}
|
|
}
|
|
|
|
return firstBuilding;
|
|
}
|
|
|
|
private Vector3 GetNextPatrolPoint()
|
|
{
|
|
Vector2 offset = Random.insideUnitCircle * patrolRadius;
|
|
return ClampToLeash(AnchorPosition + new Vector3(offset.x, 0f, offset.y));
|
|
}
|
|
|
|
private Vector3 ClampToLeash(Vector3 position)
|
|
{
|
|
Vector3 offset = position - AnchorPosition;
|
|
offset.y = 0f;
|
|
if (offset.magnitude > leashRadius)
|
|
{
|
|
offset = offset.normalized * leashRadius;
|
|
}
|
|
|
|
return AnchorPosition + offset;
|
|
}
|
|
|
|
public bool IsWithinLeash(Vector3 position)
|
|
{
|
|
Vector3 offset = position - AnchorPosition;
|
|
offset.y = 0f;
|
|
return offset.magnitude <= leashRadius;
|
|
}
|
|
|
|
public void SetPatrolEnabled(bool enabled)
|
|
{
|
|
if (patrolEnabled == enabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
patrolEnabled = enabled;
|
|
if (!enabled)
|
|
{
|
|
hasPatrolTarget = false;
|
|
pauseTimer = 0f;
|
|
IsMoving = false;
|
|
SetWalking(false);
|
|
}
|
|
else
|
|
{
|
|
hasChaseTarget = false;
|
|
}
|
|
}
|
|
|
|
public void SetChaseTarget(Vector3 position)
|
|
{
|
|
chaseTarget = position;
|
|
chaseTarget.y = transform.position.y;
|
|
hasChaseTarget = true;
|
|
}
|
|
|
|
public void ClearChaseTarget()
|
|
{
|
|
hasChaseTarget = false;
|
|
}
|
|
|
|
public void StopMovement()
|
|
{
|
|
hasPatrolTarget = false;
|
|
hasChaseTarget = false;
|
|
IsMoving = false;
|
|
SetWalking(false);
|
|
}
|
|
|
|
private void Move(Vector3 direction)
|
|
{
|
|
direction.y = 0f;
|
|
if (direction.sqrMagnitude <= 0.001f)
|
|
{
|
|
IsMoving = false;
|
|
SetWalking(false);
|
|
return;
|
|
}
|
|
|
|
IsMoving = true;
|
|
SetWalking(true);
|
|
transform.position += direction * moveSpeed * Time.deltaTime;
|
|
|
|
// 栓绳:任何情况下都不能完全离开基地
|
|
Vector3 clamped = ClampToLeash(transform.position);
|
|
clamped.y = transform.position.y;
|
|
transform.position = clamped;
|
|
|
|
transform.rotation = Quaternion.LookRotation(direction, Vector3.up);
|
|
}
|
|
|
|
private void SetWalking(bool walking)
|
|
{
|
|
if (animator != null)
|
|
{
|
|
animator.SetInteger("speed", walking ? 1 : 0);
|
|
}
|
|
}
|
|
}
|