Unity中如何将射门方向钳制在玩家前向45度范围内?
射门角度限制在玩家前向45度范围内的实现方案
现有功能概述
- 已实现360度环绕玩家的相机,能计算玩家与相机前向的水平夹角(相机在玩家正后方时夹角为0,前方朝向玩家时为180),代码如下:
void AngleBetweenCameraAndPlayer() { var playerAngle = _playerTransform.forward; var camAngle = _cameraTransform.forward; playerAngle.y = 0; camAngle.y = 0; var horizDiffAngle = Vector3.Angle(playerAngle, camAngle); }
- 射门逻辑:通过
Rigidbody.AddForce让球沿相机前向运动:
_ballrb.AddForce(_cameraForward * (power * _timer), ForceMode.Impulse); // 按相机前向,结合蓄力时间和力量参数射门
- 轨迹绘制:基于运动学方程绘制球的轨迹,脚本挂载在球上运行正常:
private void DrawProjection() { lineRenderer.positionCount = Mathf.CeilToInt(linePoints / timeBetweenPoints) + 1; Vector3 startPosition = transform.position; Vector3 startVelocity = _cameraForward * (power * _timer); int i = 0; lineRenderer.SetPosition(i, startPosition); for (float time = 0; time < linePoints; time += timeBetweenPoints) { i++; Vector3 point = startPosition + time * startVelocity; point.y = startPosition.y + startVelocity.y * time + (Physics.gravity.y/2f * Mathf.Pow(time, 2)); lineRenderer.SetPosition(i, point); } }
需求
射门角度需限制在玩家前向的±45度范围内:当相机前向与玩家前向的夹角超出45度时,仍允许射门,但射门方向锁定在45度边界位置。此前尝试通过判断夹角是否小于45度来控制,导致超出角度时无法射门和绘制轨迹,不符合需求。
解决方案
核心是将相机的水平前向向量约束在玩家前向±45度范围内,得到修正后的射门方向,用该方向统一处理射门和轨迹绘制。
1. 封装获取约束后射门方向的方法
private Vector3 GetConstrainedShootDirection() { // 提取玩家和相机的水平前向(忽略Y轴) Vector3 playerHorizontalForward = _playerTransform.forward; playerHorizontalForward.y = 0; Vector3 cameraHorizontalForward = _cameraTransform.forward; cameraHorizontalForward.y = 0; // 计算相机前向相对于玩家前向的带符号夹角(区分左右) float relativeAngle = Vector3.SignedAngle(playerHorizontalForward, cameraHorizontalForward, Vector3.up); // 将夹角限制在-45°到45°之间 float clampedAngle = Mathf.Clamp(relativeAngle, -45f, 45f); // 根据修正后的角度生成约束后的水平方向 Vector3 constrainedHorizontalDir = Quaternion.Euler(0, clampedAngle, 0) * playerHorizontalForward; constrainedHorizontalDir.Normalize(); // 保留相机原有的垂直方向分量,保证射门俯仰角度不变 constrainedHorizontalDir.y = _cameraTransform.forward.y; constrainedHorizontalDir.Normalize(); return constrainedHorizontalDir; }
2. 修改射门逻辑
替换原相机前向为约束后的方向:
Vector3 finalShootDir = GetConstrainedShootDirection(); _ballrb.AddForce(finalShootDir * (power * _timer), ForceMode.Impulse);
3. 修改轨迹绘制逻辑
同样使用约束后的方向计算初始速度:
private void DrawProjection() { lineRenderer.positionCount = Mathf.CeilToInt(linePoints / timeBetweenPoints) + 1; Vector3 startPosition = transform.position; Vector3 finalShootDir = GetConstrainedShootDirection(); Vector3 startVelocity = finalShootDir * (power * _timer); int i = 0; lineRenderer.SetPosition(i, startPosition); for (float time = 0; time < linePoints; time += timeBetweenPoints) { i++; Vector3 point = startPosition + time * startVelocity; point.y = startPosition.y + startVelocity.y * time + (Physics.gravity.y/2f * Mathf.Pow(time, 2)); lineRenderer.SetPosition(i, point); } }
关键说明
- 用
Vector3.SignedAngle获取带正负的夹角,能精准区分左右方向,确保约束范围是玩家前向左右各45度。 - 保留相机前向的Y轴分量,仅限制水平方向角度,不影响射门的上下俯仰操作。
- 无论相机角度是否超出范围,都能生成有效射门方向,避免无法射门或绘制轨迹的问题。
内容的提问来源于stack exchange,提问作者SamuraiCoder17
相关产品推荐
相关产品推荐

