首次上传

This commit is contained in:
tianmo committed 2026-10-10 17:13:46 +08:00
1 parent 2938cd4121
commit 6deaf70152
55 files changed
+14773

No files matched your search

+97
View File
@@ -0,0 +1,97 @@
using UnityEngine;
/// <summary>
/// 标准的“点击地面移动角色”组件。
///
/// 用法:把本脚本挂到一个带 CharacterController 的对象上(本项目中是一个长方体 Cube)。
/// 运行时**按住**鼠标左键(拖拽),角色会持续朝鼠标当前指向的地面点移动并平滑转向,
/// 松开即停止;**按下瞬间**会在点击位置生成一个粒子预制体(可选),2 秒后自动销毁。
/// 角色仅在地表高度移动(保持 y 不变)。
/// </summary>
[RequireComponent(typeof(CharacterController))]
public class ClickToMove : MonoBehaviour
{
[Tooltip("角色移动速度(单位/秒)")]
[SerializeField] private float speed = 3f;
[Tooltip("点击地面时在点击位置动态生成的粒子预制体(需带 ParticleSystem 组件,实例化后 2 秒自动销毁)")]
[SerializeField] private GameObject clickEffect;
private CharacterController _controller;
private Vector3 _target;
private bool _moving;
// “Ground” 层索引,与 ProjectSettings/TagManager.asset 中的配置一致(第 6 层)。
private int _groundLayer = 6;
private void Start()
{
_controller = GetComponent<CharacterController>();
_target = transform.position;
// 优先使用项目里命名的 “Ground” 层;若编辑器尚未刷新层名则回退到默认索引 6。
int named = LayerMask.NameToLayer("Ground");
if (named >= 0)
_groundLayer = named;
else
Debug.LogWarning("[ClickToMove] 未找到 \"Ground\" 层,回退使用默认层索引 6。");
}
private void Update()
{
bool clicked = Input.GetMouseButtonDown(0);
bool holding = Input.GetMouseButton(0);
// 按下瞬间 或 按住拖拽时,都朝当前鼠标指向的地面点更新目标;
// 仅在“按下瞬间”生成一次点击粒子,避免按住过程中每帧重复生成。
if (clicked || holding)
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit, 100f, 1 << _groundLayer))
{
_target = hit.point;
_moving = true;
if (clicked)
SpawnClickEffect(hit.point);
}
}
// 朝目标点移动并转向
if (!_moving) return;
Vector3 dir = _target - transform.position;
dir.y = 0f; // 只在地表水平方向移动
if (dir.sqrMagnitude > 0.05f)
{
_controller.Move(dir.normalized * (speed * Time.deltaTime));
Vector3 facing = new Vector3(dir.x, 0f, dir.z);
if (facing.sqrMagnitude > 0.001f)
transform.rotation = Quaternion.Slerp(
transform.rotation,
Quaternion.LookRotation(facing),
Time.deltaTime * 12f);
}
else
{
_moving = false;
}
}
/// <summary>在点击位置动态生成粒子预制体,2 秒后自动销毁。</summary>
private void SpawnClickEffect(Vector3 position)
{
if (clickEffect == null) return;
// 在点击位置实例化预制体
GameObject effect = Instantiate(clickEffect, position, Quaternion.identity);
// 确保粒子播放(若预制体 playOnAwake 未勾选也能看到)
ParticleSystem ps = effect.GetComponent<ParticleSystem>();
if (ps != null) ps.Play();
// 延迟 2 秒后销毁
Destroy(effect, 2f);
}
}