Unity中实现随移动角色平滑发射并归位的拳头机制
解决方案:拳头发射后归位到移动玩家的实现
核心思路
- 给拳头设置三种状态:待机(跟随玩家保持固定偏移)、发射中(沿朝向移动指定时长)、归位中(追踪玩家位置返回)
- 发射逻辑可参考玩家dash的速度参数,但单独控制拳头移动,不干扰玩家自身动作
- 归位逻辑实时计算玩家当前位置,用平滑移动实现追踪,适配玩家持续移动的场景
修改后的拳头脚本(FakeLeft)
using UnityEngine; public class FakeLeft : MonoBehaviour { // 关联玩家对象(Inspector面板拖入) public ManScript player; // 待机时拳头相对玩家的偏移距离 public Vector3 offset; // 发射速度(可复用玩家dashSpeed) public float launchSpeed = 15f; // 发射持续时长 public float launchDuration = 0.3f; // 归位移动速度 public float returnSpeed = 10f; private enum FistState { Idle, Launching, Returning } private FistState currentState; private float launchTimer; private Vector3 launchDirection; void Start() { currentState = FistState.Idle; // 初始化偏移(场景中已摆好位置时自动获取相对坐标) if (player != null) { offset = transform.position - player.transform.position; // 可选:直接复用玩家的dash速度 launchSpeed = player.dashSpeed; } } void Update() { if (player == null) return; // 按下F键触发发射(仅待机状态可触发) if (Input.GetKeyDown(KeyCode.F) && currentState == FistState.Idle) { StartLaunch(); } switch (currentState) { case FistState.Idle: // 待机时跟随玩家,保持偏移位置 transform.position = player.transform.position + offset; // 同步玩家方向旋转 UpdateRotation(); break; case FistState.Launching: LaunchMovement(); break; case FistState.Returning: ReturnToPlayer(); break; } } // 启动发射流程 void StartLaunch() { currentState = FistState.Launching; launchTimer = launchDuration; // 根据当前朝向确定发射方向 launchDirection = transform.right; } // 发射阶段移动逻辑 void LaunchMovement() { transform.Translate(launchDirection * launchSpeed * Time.deltaTime, Space.World); launchTimer -= Time.deltaTime; // 发射时长结束,切换到归位状态 if (launchTimer <= 0) { currentState = FistState.Returning; } } // 归位到玩家逻辑 void ReturnToPlayer() { // 实时更新目标位置(玩家当前位置+偏移) Vector3 targetPos = player.transform.position + offset; // 平滑移动到目标点 transform.position = Vector3.MoveTowards(transform.position, targetPos, returnSpeed * Time.deltaTime); // 接近目标后切换回待机状态 if (Vector3.Distance(transform.position, targetPos) < 0.1f) { transform.position = targetPos; currentState = FistState.Idle; } } // 保留原旋转逻辑,同步方向时更新偏移 void UpdateRotation() { if (Input.GetKeyDown(KeyCode.A)) { transform.eulerAngles = Vector3.forward * 180; offset = Quaternion.Euler(0,0,180) * Vector3.right * offset.magnitude; } if (Input.GetKeyDown(KeyCode.D)) { transform.eulerAngles = Vector3.forward * 0; offset = Quaternion.Euler(0,0,0) * Vector3.right * offset.magnitude; } if (Input.GetKeyDown(KeyCode.W)) { transform.eulerAngles = Vector3.forward * 90; offset = Quaternion.Euler(0,0,90) * Vector3.right * offset.magnitude; } if (Input.GetKeyDown(KeyCode.S)) { transform.eulerAngles = Vector3.forward * 270; offset = Quaternion.Euler(0,0,270) * Vector3.right * offset.magnitude; } } }
玩家脚本(ManScript)的补充说明
无需修改核心移动逻辑,仅需在Unity编辑器中,将玩家对象拖入拳头脚本的player字段即可。如果需要严格复用dash参数,可在拳头脚本的Start方法中直接读取玩家的dashSpeed(已在脚本中注释示例)。
关键细节
- 状态枚举清晰区分不同阶段,避免逻辑冲突
- 归位时实时更新玩家位置,确保拳头能追踪移动中的玩家
- 切换方向时同步更新偏移向量,保证待机状态下拳头位置始终正确
内容的提问来源于stack exchange,提问作者Kr00mmi
相关产品推荐
相关产品推荐

