Three.js与PHP多人游戏中立方体定位异常问题求助
核心问题定位
红立方体位置被绿立方体覆盖的本质是位置更新/读取逻辑出现了字段混淆——要么是PHP后端错误地将红玩家的位置写入了绿玩家的数据库字段,要么是客户端错误地将绿玩家的位置赋值给了红立方体,或是身份判断逻辑导致更新分支错误。
具体排查步骤
1. 验证PHP后端的更新分支与参数绑定
检查身份判断逻辑:在
game.php中添加日志,打印每次请求的$_SESSION['username']和$_POST['player']值,确认红玩家操作时是否进入了正确的else分支(更新player2的位置字段):// 加入日志,查看服务器错误日志(如Apache的error.log) error_log("Session User: " . $_SESSION['username'] . ", POST Player: " . $_POST['player']); if ($_SESSION['username'] == $_POST['player']) { error_log("Updating Player1 position"); $query = "UPDATE fight SET player1_position_x=?, player1_position_y=?, player1_position_z=? WHERE id=?"; } else { error_log("Updating Player2 position"); $query = "UPDATE fight SET player2_position_x=?, player2_position_y=?, player2_position_z=? WHERE id=?"; }如果红玩家操作时日志显示
Updating Player1 position,说明身份判断逻辑错误,导致更新了绿玩家的字段。检查参数绑定的正确性:确认分支对应的位置参数是否正确绑定,避免无论哪个分支都复用同一组变量的错误:
// 正确示例:绑定当前请求的位置参数(从POST获取) $x = $_POST['x']; $y = $_POST['y']; $z = $_POST['z']; $stmt->bind_param("dddi", $x, $y, $z, $fight_id);
2. 排查客户端AJAX请求参数
在浏览器Network面板查看红玩家移动时发送的POST请求,确认:
player参数是红玩家的用户名,而非绿玩家的x/y/z参数是红立方体的当前位置,不是绿立方体的fight_id参数与当前战斗ID一致,没有串号
3. 验证客户端位置读取逻辑
检查拉取位置的代码,确认红立方体读取的是player2_position_*字段,绿立方体读取player1_position_*字段,不要搞混:
// 正确示例 greenCube.position.set(data.player1_position_x, data.player1_position_y, data.player1_position_z); redCube.position.set(data.player2_position_x, data.player2_position_y, data.player2_position_z);
4. 确认Session隔离性
测试时使用不同浏览器/隐私窗口登录不同玩家账号,避免Session共享导致身份判断混乱(比如两个浏览器用了同一个登录Session,后端误判都是绿玩家)。
修复方案
1. 优化后端身份判断逻辑(推荐)
不要依赖$_POST['player']参数判断更新字段,直接从数据库获取当前战斗的玩家分配关系,确保每个用户只能更新自己对应的位置字段:
$fight_id = $_GET['fight_id']; // 先获取当前战斗的玩家信息 $stmt = $conn->prepare("SELECT player1_username, player2_username FROM fight WHERE id=?"); $stmt->bind_param("i", $fight_id); $stmt->execute(); $result = $stmt->get_result(); $fight = $result->fetch_assoc(); // 根据Session用户判断更新哪个字段 $current_user = $_SESSION['username']; if ($current_user == $fight['player1_username']) { $query = "UPDATE fight SET player1_position_x=?, player1_position_y=?, player1_position_z=? WHERE id=?"; } elseif ($current_user == $fight['player2_username']) { $query = "UPDATE fight SET player2_position_x=?, player2_position_y=?, player2_position_z=? WHERE id=?"; } else { http_response_code(403); exit("Unauthorized access"); } // 绑定参数并执行 $x = $_POST['x']; $y = $_POST['y']; $z = $_POST['z']; $stmt = $conn->prepare($query); $stmt->bind_param("dddi", $x, $y, $z, $fight_id); $stmt->execute();
2. 客户端增加参数校验
发送AJAX请求时,强制player参数为当前登录用户的用户名,避免参数错误:
function updateCubePosition(x, y, z) { // 假设当前登录用户名存在全局变量currentUser中 const player = currentUser; const xhr = new XMLHttpRequest(); xhr.open('POST', `game.php?fight_id=<?php echo $fightId; ?>`, true); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send(`player=${encodeURIComponent(player)}&x=${x}&y=${y}&z=${z}`); }
3. 增加数据库字段约束
在fight表中确保player1_username和player2_username不为空,且唯一对应每个战斗,避免身份判断时出现歧义。
内容的提问来源于stack exchange,提问作者John

