一段时间以来,我一直在尝试在 Unity 中真实地在盒子的墙壁上反射 3d 球体。出于某种原因,反射通常是正确的,但是当球在某些方向撞到墙壁时,反射是不正确的。为了说明球在撞墙时会发生什么:T = 顶墙,R = 右墙,L = 左墙,B = 底墙。令 r = 球向右移动/向右移动,l = 向左移动,s = 球停止/显着减速。下面的说明采用这种格式:Xyz,其中 X = 球即将撞击的墙壁,y = 球的初始方向,z = 反射。游戏有一个自上而下的视角,说明是基于墙的视角。我也是 C# 的新手,所以代码可能会令人眼花缭乱。
说明:Tll、Trl;比尔, 比尔; Rls 或撞到另一面墙后 Rlr、Rrl;Lls 或撞到另一面墙后 Llr, Lrl
通常,当球停止时,它会在空中跳跃。我想知道这是否是因为角度沿错误的轴反射,但为什么这种情况有时会发生?此外,当只按住一个键时,球会来回弹跳,直到它离开竞技场。我知道离散和连续击球检测,并且设置是离散的,但是墙壁通常可以很好地容纳球,这种情况是例外。
我尝试了什么:
- 弄清楚如何使用 Vector3.Reflect。我不明白这个函数应该包含哪些变量以及如何将它应用到我的代码中。我确实查看了 Unity 文档页面以寻求帮助,但它没有回答我的问题。
- 更改负号,因为角度必须是 y 轴上的反射,这确实会改变反射的工作方式,但不能解决问题。目前订购底片的方式是我发现的最理想的方式。
- 为球提供弹性的物理材料。
- 在反正切方程的分母上添加一个小数,以帮助防止除以零。这根本没有帮助。
- 为正负加速度的不同组合创建不同的方程(基本上改变负数)。由于每次按下按钮都会产生一定的正加速度或负加速度(请参阅运动脚本),并且所述符号似乎存在问题,我想知道将每个加速度与其自己的一组方程相关联是否可以解决问题。那没起效。
- 检查墙壁是否处于不同的角度。
- 删除变量 xA 和 yA,或将它们放在不同的位置。
- 尝试找到对象的速度,但不知道如何实现它。
名为 Controller 的玩家的运动脚本代码:
public class Movement : MonoBehaviour
{
public static float xAcceleration = 0.0f;
public static float yAcceleration = 0.0f;
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.W)) //If the key W is pressed:
{
Vector3 position = this.transform.position; //Variable position is set to transform the players placement in the game.
if (yAcceleration >= -5 && yAcceleration <= 5) //If the y vector of the acceleration is >= -5 and <= 5:
{
yAcceleration = yAcceleration + 0.01f; //The y vector of the acceleration increases by 0.01 as long as the key W is pressed.
}
position.z = position.z + (0.1f * yAcceleration); //The position of the object on the z-axis (pretend it is the y-axis in the game world) is transformed by its original position plus its speed times its yAcceleration.
this.transform.position = position; //The gameObject is now transformed to a position equal to the variable position by the z-axis.
}
else //If the key W is let go of:
{
Vector3 position = this.transform.position;
position.z = position.z + (0.1f * yAcceleration);
this.transform.position = position; //The position of the gameObject continues to update, but its acceleration does not change. Basically, it continues to move forward.
}
//The rest of the code is very similar to the above, but I included it just in case there was something wrong.
if (Input.GetKey(KeyCode.S))
{
Vector3 position = this.transform.position;
if (yAcceleration >= -5 && yAcceleration <= 5)
{
yAcceleration = (yAcceleration) - 0.01f;
}
position.z = position.z + (0.1f * yAcceleration);
this.transform.position = position;
}
else
{
Vector3 position = this.transform.position;
position.z = position.z + (0.1f * yAcceleration);
this.transform.position = position;
}
if (Input.GetKey(KeyCode.A))
{
Vector3 position = this.transform.position;
if (xAcceleration >= -5 && xAcceleration <= 5)
{
xAcceleration = (xAcceleration) - 0.01f;
}
position.x = position.x + (0.1f * xAcceleration);
this.transform.position = position;
}
else
{
Vector3 position = this.transform.position;
position.x = position.x + (0.1f * xAcceleration);
this.transform.position = position;
}
if (Input.GetKey(KeyCode.D))
{
Vector3 position = this.transform.position;
if (xAcceleration >= -5 && xAcceleration <= 5)
{
xAcceleration = (xAcceleration) + 0.01f;
}
position.x = position.x + (0.1f * xAcceleration);
this.transform.position = position;
}
else
{
Vector3 position = this.transform.position;
position.x = position.x + (0.1f * xAcceleration);
this.transform.position = position;
}
}
}
这是碰撞器和反射的代码:
public class Collider : MonoBehaviour
{
public float xA;
public float yA;
void OnCollisionEnter(Collision collision) //If a gameObject enters the collision of another object, this immediately happens once.
{
if (gameObject.tag == "Boundary") //If the gameObject has a tag named Boundary:
{
yA = -Movement.yAcceleration; //yA stores the value of yAcceleration after being called from script Movement as a negative. Its a reflection.
Movement.xAcceleration = (Movement.xAcceleration * -Mathf.Atan(yA / Movement.xAcceleration)); //xAcceleration is changed based on this equation: A * artan(A_y / A_x). The 0.000001 was here, adding to A_x to help prevent a 0 as the denominator.
xA = Movement.xAcceleration; //This is declared now...
Movement.yAcceleration = (Movement.yAcceleration * Mathf.Atan(Movement.yAcceleration / xA)); //This uses xA because Movement.xAcceleration is changed, and the yAcceleration calculation is based on the xAcceleration prior the collision.
}
}
void OnCollisionStay(Collision collision)
{
if (gameObject.tag == "Boundary")
{
yA = Movement.yAcceleration; //The same thing happens as before.
Movement.xAcceleration = (Movement.xAcceleration * -Mathf.Atan(yA / Movement.xAcceleration));
xA = Movement.xAcceleration;
Movement.yAcceleration = (Movement.yAcceleration * Mathf.Atan(Movement.yAcceleration / xA));
Movement.xAcceleration = -Movement.xAcceleration / 2; //On collision, the ball is reflected across the x-axis at half its speed.
Movement.yAcceleration = Movement.yAcceleration / 2; //yAcceleration is half its original value.
}
}
}
下图是游戏设置。我很抱歉这是一个链接;我没有足够的声誉来值得在此页面上加载图像。另外,如果有什么不清楚的,请给我留言。
https://i.stack.imgur.com/VREV4.png
我非常感谢您的帮助。谢谢!