Files
daluandou/Assets/Script/SummonerClickMovement.cs
T
huadexuan f06a1d8f92 ```
feat(gameplay): 实现召唤师对决模式核心功能

- 新增召唤师对决管理模式,支持点卡片直接召唤单位
- 添加召唤师点地移动控制,移动时不攻击、站定时自动攻击
- 实现召唤师模式开关,单位不再自动追击远处敌人
- 更新卡牌按钮逻辑,对决模式下按能量消耗直接召唤
- 修改单位基础行为,支持移动中不攻击的召唤师模式
- 更新核心玩法文档,从建筑生产模式转向召唤师对决模式
- 添加召唤师对决测试场景,整合新的战斗逻辑
```
2026-09-16 18:16:13 +08:00

158 lines
4.0 KiB
C#

using UnityEngine;
using UnityEngine.EventSystems;
/// <summary>
/// 召唤师对决:召唤师点地移动操控(直线移动,无寻路)。
/// 点击己方区域地面 → 直线走到目标点(clamp 在己方带内)。
/// 移动时不攻击;站定后自动攻击射程内目标。
/// </summary>
public class SummonerClickMovement : MonoBehaviour
{
[Header("己方半场 clamp(世界坐标)")]
public float minX = -9f;
public float maxX = 9f;
public float minZ = -29f;
public float maxZ = -11f;
[Header("移动速度")]
public float moveSpeed = 5f;
public float stopDistance = 0.2f;
[Header("地面射线")]
public LayerMask groundMask = ~0;
private Camera mainCamera;
private MainCharacterCombat combat;
private Animator animator;
private Vector3 targetPosition;
private bool hasTarget;
private void Awake()
{
combat = GetComponent<MainCharacterCombat>();
animator = GetComponent<Animator>();
}
private void Start()
{
mainCamera = Camera.main;
}
private void Update()
{
HandleClickToMove();
HandleMovement();
}
// 点地移动:点击地面即设置目标点(EventSystem 判定不在 UI 上时才生效)。
private void HandleClickToMove()
{
if (Input.GetMouseButtonDown(0) && !IsPointerOverUI())
{
if (RaycastGround(out Vector3 groundPoint))
{
Vector3 clamped = ClampToOwnHalf(groundPoint);
MoveTo(clamped);
}
}
}
// 执行直线移动
private void HandleMovement()
{
if (!hasTarget) return;
Vector3 currentPos = transform.position;
Vector3 direction = targetPosition - currentPos;
direction.y = 0f;
float distance = direction.magnitude;
// 到达目标
if (distance <= stopDistance)
{
ClearTarget();
return;
}
// 移动
direction.Normalize();
transform.position += direction * moveSpeed * Time.deltaTime;
// 朝向移动方向
if (direction.sqrMagnitude > 0.001f)
{
transform.rotation = Quaternion.LookRotation(direction, Vector3.up);
}
// 播放走路动画
if (animator != null)
{
animator.SetInteger("speed", 1);
}
}
// 外部入口:把召唤师移动到某点(clamp 后设置目标)。
public void MoveTo(Vector3 worldPosition)
{
Vector3 clamped = ClampToOwnHalf(worldPosition);
targetPosition = clamped;
targetPosition.y = transform.position.y; // 保持 Y 不变
hasTarget = true;
// 移动中暂停攻击(防风筝规则)
if (combat != null)
{
combat.enabled = false;
}
}
public void ClearTarget()
{
hasTarget = false;
// 停止动画
if (animator != null)
{
animator.SetInteger("speed", 0);
}
// 站定后恢复自动攻击
if (combat != null)
{
combat.enabled = true;
}
}
// 半场 clamp:X 与 Z 均限制在己方带内。
private Vector3 ClampToOwnHalf(Vector3 position)
{
return new Vector3(
Mathf.Clamp(position.x, minX, maxX),
position.y,
Mathf.Clamp(position.z, minZ, maxZ));
}
private bool RaycastGround(out Vector3 point)
{
point = Vector3.zero;
if (mainCamera == null)
{
mainCamera = Camera.main;
if (mainCamera == null) return false;
}
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit, 200f, groundMask.value))
{
point = hit.point;
return true;
}
return false;
}
private bool IsPointerOverUI()
{
return EventSystem.current != null && EventSystem.current.IsPointerOverGameObject();
}
}