You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Minecraft Bukkit中玩家向目标玩家方向的平滑旋转?

玩家向目标平滑旋转的实现方案

问题描述

我正尝试让玩家向另一名玩家的方向平滑旋转。若忽略「平滑」要求,可直接使用以下简单方法:

@Override
public void run() {
    for (Player player : Bukkit.getOnlinePlayers()) {
        if (player != target) {
            player.setRotation(Pitch, Yaw);
        }
    }
}

但此方法会产生卡顿的转动效果,不符合需求。请问是否存在实现平滑旋转的方案?


解决方案

核心思路是通过分步角度插值,让玩家的旋转角度逐帧趋近目标值,而非直接跳转。利用Bukkit的定时任务框架,每帧(或固定间隔)更新少量角度,实现自然的平滑过渡。

具体实现步骤

  • 计算玩家需要转向的目标俯仰角(Pitch)与偏航角(Yaw)
  • 每帧计算当前角度与目标角度的差值,按比例更新当前角度
  • 处理角度的360度循环与边界限制(如Pitch的-90~90度范围)
  • 当角度足够接近目标值时,停止任务以避免冗余计算

示例代码

import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;

public class SmoothRotationTask extends BukkitRunnable {
    private final Player player;
    private final float targetPitch;
    private final float targetYaw;
    // 旋转速度系数,值越大转动越快
    private final float rotationSpeed = 2.0f;

    public SmoothRotationTask(Player player, float targetPitch, float targetYaw) {
        this.player = player;
        this.targetPitch = targetPitch;
        // 标准化Yaw到0-360范围,避免循环计算异常
        this.targetYaw = (targetYaw + 360) % 360;
    }

    @Override
    public void run() {
        // 玩家离线或不存在时终止任务
        if (player == null || !player.isOnline()) {
            this.cancel();
            return;
        }

        float currentPitch = player.getLocation().getPitch();
        float currentYaw = (player.getLocation().getYaw() + 360) % 360;

        // 平滑更新Pitch
        float pitchDiff = targetPitch - currentPitch;
        if (Math.abs(pitchDiff) < 0.1f) {
            currentPitch = targetPitch;
        } else {
            currentPitch += pitchDiff * 0.1f * rotationSpeed;
            // 限制Pitch在Minecraft允许的范围内
            currentPitch = Math.max(-90, Math.min(90, currentPitch));
        }

        // 平滑更新Yaw,处理360度循环的近路问题
        float yawDiff = targetYaw - currentYaw;
        if (yawDiff > 180) {
            yawDiff -= 360;
        } else if (yawDiff < -180) {
            yawDiff += 360;
        }

        if (Math.abs(yawDiff) < 0.1f) {
            currentYaw = targetYaw;
        } else {
            currentYaw += yawDiff * 0.1f * rotationSpeed;
            currentYaw = (currentYaw + 360) % 360;
        }

        // 应用更新后的旋转角度
        player.setRotation(currentYaw, currentPitch);

        // 角度足够接近时终止任务
        if (Math.abs(currentPitch - targetPitch) < 0.1f && Math.abs(currentYaw - targetYaw) < 0.1f) {
            this.cancel();
        }
    }

    // 启动任务,每1tick执行一次(20tick=1秒)
    public void start() {
        this.runTaskTimer(YourPluginInstance.getPlugin(), 0, 1);
    }
}

使用方式

当需要让玩家转向目标玩家时,调用以下代码:

// 假设player是需要转向的玩家,targetPlayer是目标玩家
Location targetLoc = targetPlayer.getLocation();
float targetPitch = targetLoc.getPitch();
float targetYaw = targetLoc.getYaw();
new SmoothRotationTask(player, targetPitch, targetYaw).start();

注意将YourPluginInstance.getPlugin()替换为你的插件实例对象。


内容的提问来源于stack exchange,提问作者Hexanilix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 08:12:44