所以,Dani 在他的稍微新的视频中 -> “制作游戏,但我只有 3 天”(https://youtu.be/S7Dl6ATRK2M)制造了一个拥有弓箭的敌人(5:39)。我试图重新创建它,但没有运气...我也找不到他使用的网站...今天我发现了这个https://physicals.stackexchange.com/questions/56265/how-to-get-the-angle-needed-for-a-projectile-to-pass-through-a-given-point-for-t。它工作得很好,但如果目标很远,而且它不那么准确,仍然会出现问题。到目前为止的代码是
float CalculateAngle()
{
float gravity = Physics.gravity.magnitude;
float deltaX = targetPositionMod.x - currentPosition.x;
float deltaY = targetPositionMod.y - currentPosition.y;
float RHSFirstPart = (velocity * velocity) / (gravity * deltaX);
float RHSSecondPart = Mathf.Sqrt(
((velocity * velocity) * ((velocity * velocity) - (2 * gravity * deltaY))
/ (gravity * gravity * deltaX * deltaX))
- 1);
float tanθ = RHSFirstPart - RHSSecondPart;
float angle = Mathf.Atan2(tanθ, 1) * Mathf.Rad2Deg;
if (angle < 0) return angle;
return -angle;
}
- 角度是因为当 x 旋转为负值 (Unity) 时,前轴起点向上。也许这没有按预期进行的原因是我不太擅长这种物理(部分原因是我只有 14 岁)。也许问题出在代码上,也许问题出在公式上。任何帮助表示赞赏。
谢谢...
编辑:
弓箭手类别是:
using UnityEngine;
using System;
public class Archer : MonoBehaviour
{
[SerializeField] float velocity = default;
[SerializeField] Transform target = default;
[SerializeField] GameObject arrowPrefab = default;
[SerializeField] float coolDown = default;
Vector3 targetPositionMod;
Vector3 currentPosition;
Vector3 targetPosition;
float countDown = 0f;
void Start()
{
countDown = coolDown;
UpdateVariables();
}
void Update()
{
UpdateVariables();
SetAngle();
ShootBullet();
}
void UpdateVariables()
{
currentPosition = transform.position;
targetPositionMod = Mod(target.position);
targetPosition = target.position;
targetPosition.x /= 10;
targetPosition.y /= 10;
targetPosition.z /= 10;
countDown -= Time.deltaTime;
}
void SetAngle()
{
Vector3 direction = targetPosition - currentPosition;
Quaternion lookRotation = Quaternion.LookRotation(direction);
Vector3 rotation = lookRotation.eulerAngles;
rotation.x = (float) CalculateAngle();
transform.rotation = Quaternion.Euler(rotation.x, rotation.y, 0f);
}
void ShootBullet()
{
if (!(countDown <= 0f)) return;
countDown = coolDown;
GameObject arrow = Instantiate(arrowPrefab, transform.position, transform.rotation);
Rigidbody Rigidbody = arrow.GetComponent<Rigidbody>();
Rigidbody.AddForce(transform.forward * velocity, ForceMode.Impulse);
}
double CalculateAngle()
{
double gravity = Physics.gravity.magnitude;
double deltaX = targetPositionMod.x - currentPosition.x;
double deltaY = targetPositionMod.y - currentPosition.y;
double RHSFirstPart = (velocity * velocity) / (gravity * deltaX);
double RHSSecondPart = Math.Sqrt(
(((velocity * velocity) * ((velocity * velocity) - (2 * gravity * deltaY))
/ (gravity * gravity * deltaX * deltaX))
- 1));
double tanθ = RHSFirstPart - RHSSecondPart;
double angle = Math.Atan2(tanθ, 1) * Mathf.Rad2Deg;
if (angle < 0) return angle;
return -angle;
}
Vector3 Mod(Vector3 Vec)
{
if (Vec.x < 0) Vec.x -= 2 * Vec.x;
if (Vec.y < 0) Vec.y -= 2 * Vec.y;
if (Vec.z < 0) Vec.z -= 2 * Vec.z;
Vec.x /= 10;
Vec.y /= 10;
Vec.z /= 10;
return Vec;
}
}
好的,正如我所看到的,您从 StackExchange 实现的公式是正确的,但您必须记住两件事:
- Unity中有一个3D世界,所以水平距离不仅仅是
pos1.x - pos2.x
, but
Mathf.Sqrt( deltaX * deltaX + deltaZ * deltaZ )
, where deltaX = targetPositionMod.x - currentPosition.x
and deltaZ = targetPositionMod.z - currentPosition.z
- 在计算机实现中,你没有 100% 的数学准确性,因此由于计算准确性可能会出现一些问题。它可以对很远的距离产生影响。您可以尝试使用
double
代替float
或者找到反正切函数的另一个实现(我认为,这真的很有帮助)。但只有当第一个建议没有帮助时才尝试这个(第二个)建议。它更难实现并且会稍微减慢计算速度。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)